Zadanie č.3

Cieľom zadania je priblížiť metodiku, akou sa hľadajú a zneužívajú zraniteľnosti v reálnych aplikáciach. K dispozícii bude HTTP server napísaný v jazyku C, ktorý obsahuje rôzne zraniteľnosti (frontend webovej aplikácie, ktorý beží na serveri je implementovaný v Pythone pomocou frameworku Flask; v tomto zadaní nás to však nebude zaujímať).  Hlavnou úlohou zadania je nájsť zraniteľnosť na HTTP serveri (budeme sa zaoberať zraniteľnosťami typu stack overflow), ktorého zdrojový kód je k dispozícii a využiť túto zraniteľnosť na spustenie reverse shellu, čím ako útočníci získate kontrolu nad sytémom. Výsledkom zadania bude skript, ktorý skonštruuje špeciálne vytvorený paket a odošle ho na HTTP server; chyba v implementácii však spôsobí spustenie reverse shellu. V tomto zadaní sa bude pracovať s vypnutou NX ochranou, čo znamená že dáta, ktoré obsahuje proces na zásobníku bude možne spustiť, t.j. keď programové počítadlo (IP) skočí na adresu nachádzajúcu sa na zásobníku, procesor bude tieto dáta interpretovať ako inštrukcie a pokúsi sa ich vykonať.

Inštalácia servera

HTTP server bude bežať na 64 bitovom operačnom systéme Debian, ktorý ste si pripravili počas prác na prvom zadaní. Ako prvý krok je nutné nainštalovať niektoré balíčky a naklonovať repozitár:

sudo apt update

sudo apt upgrade

sudo apt install gcc git build-essential openssl libssl-dev execstack python-pip

sudo python -m pip install flask sqlalchemy

git clone https://github.com/petersvec/bispp_lab_01

cd ./bissp_lab_01/

O tom ako skompilovať a spustiť server sa možno dozvedieť viac na githube. Funkčnosť servera môžete otestovať v prehliadači.  Pripomíname, že v tomto zadaní je potrebné spúšťať verziu s vypnutým NX. V repozitári sa potom nachádzajú všetky zdrojové kódy, ktoré môžete použiť pri vývoji exploitu. Pred začatím vývoja odporúčame preštudovať si zdrojový kód (nie úplne do hĺbky), aby bolo jasné aké komponenty obsahuje server, kde a ako sa spracúva obsah prichádzajúcich paketov a pod.

Príprava prostredia na vývoj exploitu

Pracovať na exploite môžete kvôli pohodliu aj priamo na virtuálke kde beží server, avšak potom by bolo vhodné demonštrovať funkčnosť exploitu aj z iného počítača. V systéme na ktorom budete pracovať je vhodné si nainštalovať nasledujúce nástroje:

  1.  Peda; jedná sa o rozšírenie do GDB debuggera. Počas vývoja exploitu je vhodné používať ladiaci nástroj aby sme mohli program krokovať po inštrukciách, prípadne sledovať obsah zásobníka a pod. Rozšírenie poskytuje o niečo prívetivejšie používateľské prostredie spolu s niektorými užitočnými nástrojmi. Návod na inštaláciu nájdete na githube.
  2. Pwntools; jedná sa o Python knižnicu, ktorá slúži na rýchly vývoj exploitov a používa sa najmä pri CTF súťažiach. Knižnicu je možné jednucho nainštalovať pomocou nástroja pip.

    sudo python -m pip install pwntools

    Pomocou tejto knižnice je taktiež implementovaná šablóna exploitu dostupná v repozitári.
  3. Venom; generátor shellcode-u z metasploitu. Tento nástroj môžete použiť na vygenerovanie inštrukcií, ktoré spustia reverse shell. Návod na inštaláciu nájdete na githube. Pre funkčnosť nástroja je nutné nainštalovať aj metasploit. Pri inštalácii sa ponúkne aj možnosť doinštalovať Apache, tento krok však môžete vynechať, keďže štandardne beží na porte 80 a nastal by konflikt s našim HTTP serverom.

Poznámka: vyššie spomínané nástroje sú len odporúčané, t.j. ak uznáte za vhodné, môžete si zvoliť aj iné. V takom prípade však nezabudnite do dokumentácie zahrnúť ich popis, odkaz na stiahnutie, postup inštalácie a pod.

V tomto momente by ste mali mať pripravené všetky potrebné nástroje na začiatok vývoja. V repozitári s HTTP serverom máte pripravený template Python skriptu (aj s nejakými pomôckami) do ktorého doplníte váš kód. Šablóna vytvorí HTTP GET request na stránku index.html a odošle ho na localhost:80 (parametre môžete ľubovoľne zmeniť). Skript sa jednoducho spustí:

./exploit.py

Nástroj Venom funguje tak, že po vygenerovaní kódu sa spustí konzola a čaká kým sa spustí shellcode. Ak sa vám úspešne podarí implementovať exploit a proces HTTP servera spustí vygenerovaný shellcode, vo Venom konzole získate reverse shell na systém, v ktorom daný proces beží.

POZOR: je absolútne nevyhnutné aby ste na počítači, kde beží HTTP server vypli ASLR, ochranu proti exploitácii. V prídade reštartu počítača je nutné ju vypnúť znova (na tento krok sa ľahko zabudne a je častým dôvodom prečo exploit nefunguje). Príkazy:

su

echo 0 > /proc/sys/kernel/randomize_va_space

Ako postupovať

Pri exploitácii sa vždy hodí poznať základy assembleru, avšak nie je to nutné. Keďže budeme exploitovať pretečenie zásobníka, je vhodné minimálne poznať ako vyzerá prológ a epilóg funkcie, aké registre sa používajú na prácu so zásobníkom a ako vyzerá zásobník počas volania funkcie. Najdôležitejšie je však pochopenie, akým spôsobom funguje inštrukcia RET, ktorá načíta do registra RIP (instruction pointer na x64 architektúre) hodnotu na vrchu  zásobníka a vykonávanie programu sa presunie na toto miesto (ak sa nám podarí ovplyvniť hodnotu na vrchu zásobníka v tom momente, získali sme kontrolu nad tokom programu). Pre lepšie pochopenie odporúčam prejsť si nasledujúci tutoriál na jednoduché pretečenie zásobníka (obzvlášť dôležité je poznanie maximálnej možnej adresy na 64 bitových systémoch). Tutoriál poslúži aj na precvičenie si práce v GDB debuggeri s Peda rozšírením. Medzi užitočné príkazy patrí krokovanie, nastavenie breakpointu či sledovanie obsahu adries.

Po spustení servera sa vytvorí viacero procesov (ich popis možno nájsť na githube). Vo výpise môžeme vidieť aké PID majú jednotlivé procesy.

To nám pomôže ak chceme ladiť niektorý z týchto procesov pomocou GDB. Ak chceme napríklad ladiť proces fbankd, GDB spustíme pomocou nasledujúceho príkazu:

gdb -p 1359

Treba si však uvedomiť že niektoré tieto procesy vytvárajú ďalšie detské procesy a GDB v štandardnom móde ostáva vždy v rodičovskom procese. Ak chceme následovať vykonávanie kódu aj do detského procesu, je nutné do súboru .gdbinit (nachádzajúci sa v adresári v ktorom sú zdrojové kódy a spustiteľné súbory serveru) zapísať nasledujúci príkaz:

set follow-fork-mode child

Dôležitou otázkou však stále zostáva ako nájsť zraniteľnosť. Postup môžeme zhrnúť do nasledujúcich krokov:

  1. Úplne prvým krokom, ktorý musíme urobiť je dokázať našim vstupom spôsobiť pád aplikácie (hint: nejaké chyby budú pravdepodobne pri spracovávaní HTTP requestov). Jedným zo spôsobov je teda posielať na server rôzne extrémne vstupy (napr. veľkej dĺžky) a sledovať ako zareaguje server. Táto metóda sa dá robiť buď ručne alebo je možné použiť rôzne fuzzery, avšak v našom prípade je pravdepodobne jednoduchšie to robiť ručne a pomocou Pythonu konštruovať rôzne dlhé vstupy. Keďže máme k dispozícii aj zdrojový kód servera, chyby môžeme priamo hľadať aj analýzou kódu.
  2. Ak sa nám podarilo zhodiť aplikáciu (pravdepodobne prepísaním návratovej adresy nejakými náhodnými znakmi) musíme nájsť offset od začiatku vstupu, kde sa začala prepisovať návratová adresa. Dobrým zvykom je vytvoriť taký vstup že návratová adresa sa prepíše nejakým ľahko identifikovateľným patternom (najčastešie sa používajú znaky „A“, 0x41 hexadecimálne). Exploit by vyzeral potom takto: „nahodnypocetnahodnychznakovAAAAAA“. Ak by sme naším vstupom presne prepísali návratovú adresu znakmi „A“, aplikácia v GDB spadne s nasledujúcou hláškou: Invalid $PC address 0x414141414141 (pozn. reťazec „AAAAAA“ môžeme potom nahradiť reálnou adresou, napr. 0xffffff2548fa).
  3. Keď už vieme ako prepísať adresu kam sa presunie vykonávanie kódu po spracovaní nami vytvoreného paketu, musíme ju prepísať adresou ktorá bude ukazovať na náš vygenerovaný shellcode. Shellcode môžeme priamo zapísať do exploitu a tak ho uložiť na zásobník (v tomto zadaní je zásobník spustiteľný). Adresu potom môžeme nájsť napríklad ladením v GDB a preskúmaním zásobníka (príkaz x). Dôležitým faktom taktiež ostáva, že adresy zásobníka sa zvyknú jemne posúvať medzi každým spustením, keďže na zásobník sa ukladajú aj premenné prostredia, ktoré sa môžu každým spustením líšiť. Z toho dôvodu je nebezpečné ako návratovú adresu použiť prvú inštrukciu shellcode-u na zásobníku. Na ošetrenie tejto situácie sa používa technika zvaná NOP sled.
  4. V tomto momente je exploit už hotový. Dôležité je taktiež zistiť (ladením alebo analýzou zdrojového kódu), či sa s naším špeciálnym vstupom nerobia nejaké transformácie a v prípade ak áno, ošetriť ho tak, aby samotné dáta exploitu prežili transformáciu.

Dokumentácia

Pri zadaní sa bude okrem funkčnosti exploitu primárne hodnotiť kvalita dokumentácie. V dokumentácii je nutné popísať nasledujúce body:

  1. Metodiku, ktorú ste zvolili pri hľadaní zraniteľností. Ak ste používali nejaké automatizované nástroje, treba uviesť aj spôsob inštalácie a použitia.
  2. Detailná identifikácia zraniteľnosti v zdrojovom kóde. Ideálne aj uviesť akým spôsobom by ste ju ošetrili.
  3. Detailný postup, akým ste vyvíjali exploit, ako ste hľadali rôzne adresy a pod.
  4. Zhodnotenie funkčnosti exploitu. Ak exploit funguje iba v špecifických prípadoch, treba uviesť dôvody prečo tomu tak je.

Okrem dokumentácie treba odovzdať aj skript s exploitom.

Deadline

6.4. 2020 15:00

Bonus

V implementácii HTTP servera sa nachádza viacero zraniteľností. Za každú ďalšiu ktorú nájdete (okrem tej, ktorú budete exploitovať) môžete získať bonusový bod. Bonusový bod sa uzná iba v prípade, ak implementujete PoC exploitu, v ktorom však stačí ak ukážete, že dokážete prevziať kontrolu nad tokom programu (prepísať RIP alebo smerník na funkciu), t.j. netreba riešiť žiadny shellcode, stačí vedieť prepísať adresu.

GDB príkazy

V tejto sekcii uvádzame najčastejšie príkazy, ktoré sa môžu zísť počas ladenia servera a vývoja exploitu:

  • b nazov_funkcie – nastavenie breakpointu na začiatok funkcie s názvom nazov_funkcie
  • b *nazov_funkcie+offset – nastavenie breakpointu na offset od začiatku funkcie s nazov_funkcie
  • b *adresa – nastavenie breakpointu na adresu adresa
  • info break – zobrazenie aktuálne nastavených breakpointov
  • del num – odstránenie breakpointu číslo num
  • disas nazov_funkcie – zobrazenie inštrukcii patriacich k funkcii nazov_funkcie
  • x/nfu adresa/$register – preskumanie examine / n počet jednotiek veľkosti u vo formáte f na adrese/registri
    • x/100wx 0x100 – zobrazenie  100 jednotiek typu word (4 bajty) v hexadecimálnom formáte na adrese 0x100
    • x/100i 0x200 – zobrazenie 100 inštrukcií na adrese 0x200
    • x/wx $rsp – zobrazenie obsahu registra RSP (vrch zásobníka)
  • ccontinue; pokračovanie vo vykonávaní programu až po ďalší breakpoint
  • sistep instruction; krok po jednej inštrukcii

Viac možno nájsť v oficiálnej dokumentácii.