Templaattien Injektiohaavoittuvuudet

Mitä ovat Templaatti-Injektiot (SSTI)?

Keskitaso
20 min

Mitä ovat templaatit?

Vanhanaikaiset web-sovellukset rakensivat (ja osittain rakentavat yhä) HTML-vastauksia tämän kaltaisesti.

html = "<h1>Tervetuloa, " + nimi + "</h1>
return html

Tämän kaltainen HTML-rakennus on paitsi kankeaa, myös hirvittävän turvatonta. Tällaisiin sovelluksiin on yleensä aika helppo injektioida hyökkääjän omaa HTML/JavaScript-koodia, joka johtaa XSS-haavoittuvuuksiin.

Modernimpi lähestymistapa on käyttää templaatteja. Templaatit ovat erillisiä HTML-tiedostoja, jotka ovat osittain myös kooditiedostoja. Templaatille annetaan sitten haluttu data ja templaatti rakentaa HTML:n. Tässä koodissa ei ole haavoittuvuutta, koska templaatti osaa rakentaa HTML:ää turvallisesti niin, ettei ole väliä, mitä hyökkääjä on nimeksi syöttänyt, se ei muodostu vaarallisesti osaksi HTML-rakennetta.

template = "<h1>Tervetuloa, {{nimi}}</h1>"
return render_template(template, nimi=nimi)

Templaatti-injektio

Templaatti-injektiohaavoittuvuus on hyvin samankaltainen perinteisen HTML-injektion kanssa (josta seuraa XSS-haavoittuvuus), mutta huomattavasti vakavampi, koska toisin kuin HTML (joka suoritetaan selaimessa), templaatit suoritetaan koodina palvelimen päässä ennen kuin templaatin suorituksen seurauksena rakennettu HTML palautetaan selaimelle.

Tässä on esimerkki haavoittuvasta Flask-sovelluksesta, joka käyttää Jinja2-templaattimoottoria virheellisesti, antaen käyttäjän syötteen vaikuttaa itse templaattiin, eikä vain templaatille annettavaan dataan, kuten olisi pitänyt.

if request.method == 'POST':
        name = request.form['name']
        template = f'<h1>Tervetuloa, { name }!</h1>'
        return render_template_string(template)
    else:
        template = '''
            <form method="POST">
                <label for="name">Nimi:</label>
                <input type="text" name="name" id="name">
                <button type="submit">Lähetä</button>
            </form>
        '''
        return render_template_string(template)

Haavoittuvuuden havaitseminen

Pythonin JInja2 ei suinkaan ole ainoa templaattimoottori, vaan niitä on monta ja eri ohjelmointikielille. Lähes kaikkia templaattimoottoreita kuitenkin yhdistää syntaksi, jossa kahdet kaarisulut suorittavat lausekkeen, kuten vaikkapa kirjoittavat muuttujan tai laskevat laskun.

Perinteinen tapa havaita templaatti-injektioita on siis syöttää {{7*7}} syötteessä ja katsoa että palauttaako sovellus HTML:ssä "49" samalla kohdalla. Tämä on lähes varma merkki templaatti-injektiosta.

Kokeillaan:

Haavoittuvuuden hyväksikäyttö

Templaatti-injektiot johtavat lähes aina siihen, että hyökkääjä pääsee suorittamaan mielivaltaista koodia sovelluspalvelimella (RCE, Remote Code Execution). Se, että miten koodin suoritukseen asti päästään vaihtelee aika paljon ohjelmointikielestä ja templaattimoottorista riippuen. Tutustumme näihin tässä kurssilla.

Injektioilta suojautuminen

Templaatti-injektioilta on helppo välttyä. Ei tarvitse muuta kuin pitää templaatti täysin staattisena niin, ettei itse templaattiin voi vaikuttaa millään tavalla. Pelkästään templaatin dataan saa vaikuttaa, ei rakenteeseen.

Kaikki dynaamisesti rakennetut templaatit ovat vaaranpaikka.

hakatemia pro

Valmis ryhtymään eettiseksi hakkeriksi?
Aloita jo tänään.

Hakatemian jäsenenä saat rajoittamattoman pääsyn Hakatemian moduuleihin, harjoituksiin ja työkaluihin, sekä pääset discord-kanavalle jossa voit pyytää apua sekä ohjaajilta että muilta Hakatemian jäseniltä.