Komentoinjektiot

Mitä komentoinjektiot ovat?

Helppo
30 min

Käyttöjärjestelmäkomennot

Käytännössä kaikissa käyttöjärjestelmissä on jonkunlainen komentotulkki, tekstipohjainen käyttöliittymä. Windowsissa se on komentokehoite (cmd.exe) tai powershell, Linuxissa ja Macissa se on bash, sh, zsh, jne. Ja näistä komentotulkeista voi käynnistää tekstipohjaisia ohjelmia ja komentoja. Esimerkiksi, voimme pingata Googlea:

$ ping google.com
PING google.com (209.85.233.101) 56(84) bytes of data.
64 bytes from lr-in-f101.1e100.net (209.85.233.101): icmp_seq=1 ttl=114 time=82.4 ms

Käyttöjärjestelmäkomennot ohjelmoinnissa

Joskus sovellukset hyödyntävät taustalla konsolityökaluja. Meillä voisi olla vaikka Pythonilla tehty web-sovellus, jonka tarkoitus on pingata tiettyä IP-osoitetta ja näyttää sivustolla pingauksen tulos. Koodi voisi näyttää tältä:

def do_GET(request):
    ip = request.get_parameter("ip")
    result = os.popen(f"ping -c1 {ip}").read()
    return {"result": result}

Injektio

Ongelma tässä on, että käyttäjältä tulevan syötteen lisääminen käyttöjärjestelmäkomentoon on hirvittävän vaarallista. Lisäämällä tiettyjä erikoismerkkejä "IP-osoitteeseen", hyökkääjän on mahdollista huijata sovellus ajamaan ihan eri käyttöjärjestelmäkomentoja kuin ping.

Komentosubstituutio

Otetaan vaikka komentosubstituutio (command substitution), jolla voidaan ottaa toisen komennon tuloste osaksi komentoa. Substituutio voidaan tehdä syntaksilla $(komento) tai `komento`.

$ pwd
/tmp
$ echo "pwd on: $(pwd)"
pwd on: /tmp
$ echo "pwd on: `pwd`"
pwd on: /tmp

Eli syöttämällä IP-osoite kuten 1.2.3.4$(id) voisimme saada vastauksen "Ping 1.2.3.4$(id) tulos: ping: uid=0(root) gid=0(root) groups=0(root): Name or service not known." Kyseessä on siis id-komennon tuloste (tässä tapauksessa käyttäjä oli root).

Mielikuvitus on rajana

On lukemattomia tapoja saada omia komentoja ujutettua väliin tai perään jos pääsee kirjoittamaan käyttöjärjestelmäkomennon sisälle. Joitakin esimerkkejä:

# Puolipiste, aloittaa uuden komennon.
echo abc; id

# Yksi putki, ottaa edellisen komennon tulosteen ja ohjaa sen uuteen komentoon
echo abc | id;

# Kaksi et-merkkiä, aloittaa uuden komennon jos edellinen komento onnistuu.
echo abc && id;

Harjoitus

Labrassa on verkkodiagnostiikkatyökalu, joka tarkistaa onko nettisivu ylhäällä. Taustalla työkalu käyttää curl-komentoa. Näet sivun ylälaidasta mitä komentoja palvelimella ajetaan.

Yritä saada luettua tiedosto /flag.txt.

Komentoinjektioilta suojautuminen

Käyttöjärjestelmäkomentojen ajamista kannattaa lähtökohtaisesti välttää, ja pyrkiä saavuttamaan sama asia koodilla. Jos tämä ei ole mieluinen vaihtoehto, niin on tärkeää että:

1. Käyttöjärjestelmäkomentoja ei koskaan rakenneta tekstiä yhdistelemällä, kuten:

os.system("ping " + ip)

Komennot tulee rakentaa sellaisella ohjelmistokirjastolla, joka osaa turvallisesti huolehtia, ettei syöte leviä kyseisen parametrin ulkopuolelle:

subprocess.Popen(['ping', ip])

2. Parametri, joka tulee mistään ohjelman ulkopuolelta (kuten käyttäjän syötteestä, tietokannasta, rajapinnasta, jne), tulee validoida mahdollisimman tarkasti.

3. Parametri, johon esimerkiksi sovelluksen käyttäjän annetaan vaikuttaa, tulee ymmärtää kunnolla. Otetaan esimerkiksi curl. Riittääkö, että käytetään turvallista kirjastoa muodostamaan curl-kutsu, ja annetaan käyttäjän vain päättää URL-osoite? Jos vielä validoidaan että URL on oikeanmuotoinen?

Ei riitä! Curlilla voi lukea tiedostoja palvelimen levyltä.

$ curl file:///etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin

Entäs jos varmistaa että URL-osoitteet alkavat http:// tai https://? Ei riitä! Curlilla voisi kutsua palvelimella olevia paikallisia tai sisäverkon HTTP-rajapintoja, joiden ei ollut tarkoitus olla auki Internetiin.

Pointti on, että käyttöjärjestelmäkomennoilla on usein sellaisia kyvykkyyksiä joita ei olisi tullut ajatelleeksi. Jos niitä on pakko käyttää, on syytä noudattaa varovaisuutta.

Verkkodiagnostiikkaa

Tässä labrassa pääset harjoittelemaan komentoinjektiohyökkäystä haavoittuvaa verkkodiagnostiikkapalvelua vastaan.

Tavoite

Hanki root-oikeudet palvelimelle ja lue (vaikka cat-komennolla) tiedosto /flag.txt.

Tehtävät

Flag

Löydä lippu (flag) labraympäristöstä ja syötä se alle.

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ä.