DEV Community

StarkMan
StarkMan

Posted on

953 Magento stores, one loader that asks your browser whether you are a scanner

953 Magento stores, one loader that asks your browser whether you are a scanner

Sansec counted 953 online stores carrying a JavaScript loader that has been running since July 2025. Most of them run Magento. The detail that makes this campaign different from the usual card-skimming injection is what the loader does before it decides to do anything: it works out whether the request comes from a real shopper or from a security scanner, and gives the scanner nothing.

Where the code sits

The loader is stored in the cms_block table of the Magento database, so it is served as ordinary CMS content on the storefront. The visitor's browser then fetches further instructions from the attacker. That arrangement explains why automated scanning so often reports a clean site. When Sansec loaded an infected store through urlscan.io, an automated browser, it found no injected content at all.
The campaign has cycled through five loader domains. The most recent was registered on October 6 and was found in the CMS blocks of 83 stores, 60 of which had carried an earlier version of the same loader. A return visit is therefore not a coincidence; it is the same estate, re-infected.

What changed in October

Before October, the operator used the Keitaro traffic distribution system to decide, per visitor, whether to deliver a payload, redirect the browser, or return nothing.
The loader Sansec found on October 7 stopped relying on that intermediary. It called the new domain directly and replayed code stored in the browser, so a visitor who had already been served the payload would run it again on later page loads, even if the domain was taken down or blocked.
An October 23 rewrite added browser fingerprinting. The script checks for signs of browser automation and collects hardware details, screen size, time zone and language, then the server chooses its response. This is a filtering step in front of delivery, not a detection of a specific tool.
Sansec has not obtained the final payload, so what the campaign does with the visitors it decides to keep is still unknown. A loader that reaches this stage without a visible payload is a supply-chain problem for the merchant rather than a known fraud pattern for the shopper.

Patching alone did not stop it

In March, a wave of the campaign planted the loader on 471 stores within an hour. The entry point was webshells placed through PolyShell, tracked as CVE-2026-48356. Of 169 infected Magento 2 installations missing at least one core patch, 102 showed evidence of file uploads through PolyShell or SessionReaper, CVE-2025-54236.
The counter-example is more useful than the statistics. A fully patched store running Magento 2.4.7-p10 picked up the newest loader on October 23, an hour after passing a clean scan. In September, Sansec had found a rogue administrator account and a GSocket backdoor on that same store. The patch closed the vulnerability; it did not remove the access the attacker had already built.
That is the operational lesson. Removing the script from a CMS block leaves the attacker's write access to the database intact, so the store can be re-infected while the original way in remains open.

A recovery order that matches the failure

Sansec's guidance is a sequence rather than a checklist, and the order matters.

  • Look for the loader in CMS content, including blocks that are not currently rendered on a page.
  • Review administrator accounts, since a rogue admin is one of the observed persistence mechanisms.
  • Hunt for backdoors rather than assuming the injection is the only artefact.
  • Rotate database, administrator and integration credentials only once the store is clean, because rotating first hands the attacker the new values along with the old access.
  • Apply the current Magento and Adobe Commerce security updates, which address the entry paths behind the March wave. The order is deliberately inconvenient. Most incident workflows want to clean first and rotate later; here the cleaning step is the one that can be undone in an hour.

What to instrument

Three signals would have surfaced this campaign earlier.
A file-integrity or database-content check on cms_block and similar CMS tables catches the injection point without depending on the loader's own delivery logic. Sansec's finding that the code lives in a database table rather than in a template file is the reason a filesystem scan alone would miss it.
Administrator account creation and permission changes are low-volume events on a normal store. An account that appears outside a change window is worth investigating even when the storefront looks clean.
Outbound callbacks from the storefront to a newly registered domain are the third signal, but they only appear for visitors the loader decides to keep. A scanner will not see them, which is the point of the filtering.

References

[1] Infosecurity Magazine, "Hackers Infect 953 Online Stores With Scanner-Evading Code", October 27, 2026. https://www.infosecurity-magazine.com/news/hackers-infect-953-online-stores/

Top comments (0)