Unpatched Magento and Adobe Commerce Zero-Day Exploited to Backdoor Online Stores
A new unpatched vulnerability, dubbed StyleSmuggler, is being exploited to backdoor online stores using Magento and Adobe Commerce. Attackers are leveraging a PHP dropper to install a persistent backdoor, bypassing login requirements. The vulnerability allows code execution on the server and installation of a backdoor, and Adobe has not yet released a patch. Sansec and Disrex have independently identified and documented the attack, with Disrex providing mitigation strategies including custom nginx and Apache rules and composer patches. The vulnerability is particularly concerning because it can be triggered through seemingly legitimate email operations, such as failed payment reminders. Adobe has scheduled a security release on September 8, but it remains uncertain whether it will address the issue.
Attackers are exploiting a new unpatched vulnerability in Magento Open Source and Adobe Commerce that lets them run malicious code on an online store's server without logging in, Dutch e-commerce security company Sansec said in an advisory published on September 5. Sansec, which discovered the flaw and named it StyleSmuggler, said attacks started on September 4. "Sansec is publishing early because stores are being compromised right now," the company said.
As of September 6, Adobe has not published an advisory, a CVE identifier, a patch, or a workaround, and its Adobe Commerce security bulletin index lists nothing after the August 11 update. A successful attack gives the attacker code execution on the store's server and installs a persistent backdoor. Sansec has not published a reproduction on Adobe Commerce or on Adobe Commerce on Cloud, and Adobe has not confirmed which versions are affected. Sansec has not said how many stores have been compromised.
The researchers' interim advice for stores not running its Shield product is to disable GraphQL until Adobe releases a temporary fix. Disrex Group, a Magento hosting and development company that responded to two of the compromised stores, notes that headless and progressive web app storefronts require GraphQL, whereas most classic and Hyvä storefronts do not.
Adobe's next scheduled security release is on September 8, Sansec said, and it is not yet known whether that release will cover this bug. Disrex's findings are independent evidence of exploitation from outside Sansec. In an incident-response repository published on September 5, the company said it handled two stores compromised on September 5 and a third that was attacked but not breached, and that its web-server rules are based on attack traffic captured on one of the compromised stores.
That store ran Magento 2.4.7-p2, a security patch level that Adobe's version history dates to August 2024, eight levels behind the current 2.4.7-p10. The store Disrex labels Store A was a Sansec Shield customer and was hit at 23:10 UTC on September 4, hours before Sansec's first blocking rules went live.
The repository carries its own warning. "This repository was written with AI assistance, during a live incident, in a few hours," its README says, adding that it has not been reviewed, that its Apache rules were never run against a live Apache server, and that most of its cleanup commands were written rather than executed.
Sansec's indicators describe the implant as a background process disguised under [kworker/u:8:0], a name that belongs to a Linux kernel thread, with a binary installed at ~/.local/share/.gvfsd/gvfsd-user under the site user's home directory rather than the web root, and a cron entry that restarts it every five minutes. Disrex described the binary as a stripped, statically linked Rust program of roughly 1.9 MB built for x86-64 and arm64, and said the cron entry is written straight to the spool file under /var/spool/cron/crontabs/, so the system log shows no crontab replacement.
One store carried the same line 1,728 times, and the implant re-added it within a second of removal. On one of the two stores, the implant made no outbound connection at all. It held 28 connections to the store's own Redis instance on port 6379. It read Magento's session storage from it, Disrex said, and neither of its two packet captures, each over 200 MB and taken. At the same time, the implant was live, contained a single packet to the download host or the command-and-control address that Sansec listed.
Sansec said that for Shield customers attacked before its rules went live, it has no indication that the backdoor was actually used, and recommended rotating Magento credentials wherever the process has been identified. The attack works in two stages, according to Sansec's outline. It first plants PHP code in a file that Magento itself writes, for example, when generating a failure report. Then it makes Magento execute that file by triggering the platform's standard "Payment Transaction Failed Reminder" email. The code runs while Magento renders the message, so no one has to open it, and the attack can succeed even if email delivery fails.
Sansec has not yet published the full exploit chain and said a breakdown of the chain, the dropper, and the implant will follow in an update. Disrex's reading of the chain, published in a mechanism write-up alongside its rules, is that a directive within the injected text drives a sequence of Magento's own classes into code that exists solely to serve the command-line dependency-injection compiler. That code ends by including a file path the attacker chose: the log poisoned a moment earlier. The executed PHP dropper attempts six PHP functions in turn to start a process, then downloads and launches the implant. Disrex names three files under setup/src/Magento/Setup/Module/Di/Code/ as the point where the chain ends. Sansec has not confirmed that reading, and Disrex does not publish the assembled request.
Two locations matter for the first stage. Sansec's published check searches var/report/ for the marker X_TRACE_. Disrex said both of its infections were poisoned through var/log/system.log instead and would have been missed by that check, so both directories need searching. The marker has already drifted: Disrex saw a trigger header of the form X-TRACE- followed by ten hex characters on the morning of September 5 and the same header without the word TRACE by the afternoon, so a search should match the shape rather than the exact string.
A TypeError from array_merge() with an integer argument in system.log, immediately after the include, is evidence that the exploit succeeded, Disrex said. However, a stealthier variant returns an empty array and leaves nothing in the log.
For the process, Disrex said that a genuine kernel thread is owned by root and has no resident memory, so a bracketed name on the site user with real memory usage is the implant. The implant sets its command line to the literal bracketed string, so a check written against the process's comm field matches nothing. Disrex also found that the binary running in memory on one store was a different build from the file on disk, and advises hashing the running process from /proc/<pid>/exe as well as the file. Unexpected bursts of
