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.

953 家 Magento 商店,一个会询问浏览器是否为扫描器的加载器。Sansec 统计发现,有 953 家在线商店携带了一种自 2025 年 7 月起就开始运行的 JavaScript 加载器。其中大多数商店运行的是 Magento 系统。该活动与常见的信用卡窃取注入攻击不同之处在于,加载器在执行任何操作前会先进行判断:它会识别请求是来自真实购物者还是安全扫描器,并对扫描器隐藏自身。

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.

代码位置:该加载器存储在 Magento 数据库的 cms_block 表中,因此它作为普通的 CMS 内容在店面中呈现。访问者的浏览器随后会从攻击者处获取进一步指令。这种安排解释了为什么自动化扫描经常报告网站是“干净”的。当 Sansec 通过自动化浏览器 urlscan.io 加载受感染的商店时,完全没有发现任何注入内容。

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.

该活动已轮换使用了五个加载器域名。最近的一个域名注册于 10 月 6 日,在 83 家商店的 CMS 区块中被发现,其中 60 家商店此前曾携带过该加载器的早期版本。因此,再次访问并非巧合,而是同一资产被重新感染。

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.

10 月份的变化:10 月之前,运营者使用 Keitaro 流量分配系统来决定针对每位访问者是交付有效载荷、重定向浏览器还是不返回任何内容。Sansec 在 10 月 7 日发现的加载器不再依赖该中介。它直接调用新域名并重放存储在浏览器中的代码,因此即使域名被撤销或屏蔽,已经接收过有效载荷的访问者在后续页面加载时仍会再次运行该代码。

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.

10 月 23 日的重写增加了浏览器指纹识别功能。脚本会检查浏览器自动化的迹象,并收集硬件详情、屏幕尺寸、时区和语言,然后由服务器选择响应方式。这是交付前的过滤步骤,而非针对特定工具的检测。Sansec 尚未获取最终的有效载荷,因此该活动对留下的访问者具体做了什么尚不清楚。一个在没有可见有效载荷的情况下达到此阶段的加载器,对商家而言是供应链问题,而非针对购物者的已知欺诈模式。

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.

仅靠打补丁无法阻止它:3 月份,该活动的一波攻势在一小时内向 471 家商店植入了加载器。入口点是通过 PolyShell 放置的 WebShell,追踪编号为 CVE-2026-48356。在 169 个至少缺少一个核心补丁的受感染 Magento 2 安装中,有 102 个显示了通过 PolyShell 或 SessionReaper (CVE-2025-54236) 上传文件的证据。反例比统计数据更有用。一家运行 Magento 2.4.7-p10 并已完全打补丁的商店,在通过干净扫描一小时后,于 10 月 23 日感染了最新的加载器。9 月份,Sansec 曾在同一家商店发现了一个非法管理员账户和一个 GSocket 后门。补丁修复了漏洞,但并未移除攻击者已经建立的访问权限。

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.

这就是运营层面的教训。从 CMS 区块中删除脚本并不能消除攻击者对数据库的写入权限,因此在原始入口保持开放的情况下,商店可能会被重新感染。与故障相匹配的恢复顺序:Sansec 的建议是一个流程而非清单,且顺序至关重要。在 CMS 内容中查找加载器,包括当前未在页面上呈现的区块。审查管理员账户,因为非法管理员是观察到的持久化机制之一。寻找后门,不要假设注入是唯一的痕迹。仅在商店清理干净后才轮换数据库、管理员和集成凭据,因为先轮换会直接将新凭据交给仍拥有访问权限的攻击者。应用当前的 Magento 和 Adobe Commerce 安全更新,以解决 3 月份攻势背后的入口路径。这个顺序是刻意设计的,虽然不便,但大多数事件工作流倾向于先清理后轮换,而在这里,清理步骤可能在一小时内就会失效。

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.

如何监测:三个信号本可以更早地发现此次活动。对 cms_block 及类似 CMS 表进行文件完整性或数据库内容检查,可以在不依赖加载器自身交付逻辑的情况下捕获注入点。Sansec 发现代码存在于数据库表中而非模板文件中,这就是仅靠文件系统扫描会漏掉它的原因。管理员账户创建和权限更改在正常商店中属于低频事件。即使店面看起来干净,在变更窗口之外出现的账户也值得调查。从店面到新注册域名的出站回调是第三个信号,但它们仅出现在加载器决定保留的访问者身上。扫描器无法看到这些回调,这正是过滤机制的目的所在。