Recently, I encountered the PolyShell attack on a Magento 2 store.
This vulnerability allows attackers to upload executable files via Magento’s REST API,
often disguised as harmless images or auto‑generated files in pub/media.
Once inside, these scripts can be executed remotely, leading to backdoors, data theft, and even account takeover.
What is PolyShell?
PolyShell is a critical flaw in Magento’s REST API that lets unauthenticated attackers upload files
directly into pub/media/custom_options. The exploit uses a polyglot technique —
files crafted to look like valid images (GIF/PNG) but containing hidden PHP code.
Because Magento only checks the image header, attackers bypass validation and drop executable shells.
Sansec researchers observed that nearly 80% of Magento and Adobe Commerce stores were probed for PolyShell within days of discovery. No official patch existed for production versions until Magento 2.4.9, leaving older releases (2.4.8 and below) exposed.
Versions Affected
- Unrestricted file upload: All Magento Open Source and Adobe Commerce versions up to 2.4.9-alpha2.
- Stored XSS: Versions prior to 2.3.5 or custom webserver configs.
- RCE via PHP upload: Stock nginx 2.0.0–2.2.x, Apache pre-2.3.5 without proper PHP restrictions.
- Patched: Magento 2.4.9-alpha3+ (pre-release) and final 2.4.9 GA.
How the Exploit Works
Magento’s REST API accepts file uploads as part of cart item custom options.
When a product option has type “file,” Magento processes an embedded file_info object
containing base64-encoded data, MIME type, and filename. The file is written to pub/media/custom_options/quote/.
Three critical checks are missing:
- No validation of the option ID against the product’s actual options.
- No restriction to file-type options — uploads are processed regardless of product configuration.
- No file extension filtering — dangerous extensions like
.php,.phtml, and.pharare allowed.
The most dangerous endpoints are the anonymous guest cart routes:
POST /V1/guest-carts/:cartId/items(no authentication)PUT /V1/guest-carts/:cartId/items/:itemId(no authentication)
What I Saw on My Store
- Auto‑generated suspicious directories like
customer_addressandcustom_optioninsidepub/media. - Corrupted
.htaccessfiles enabling PHP execution in media folders. - Database entries containing obfuscated code (
eval,atob, “casino”). - Unexpected PHP files in media directories where only images should exist.
- Performance issues including unexplained CPU spikes caused by hidden scripts.
Payloads Observed
Attackers uploaded polyglot files — valid GIF headers with embedded PHP shells. Two main payload types were seen:
- Cookie-authenticated webshells: GIF89a polyglot dropped as
index.php, verifying a cookie hash before executing arbitrary code viaeval(base64_decode()). - Password-protected RCE shells: Using
hash_equals()with a hardcoded MD5 hash, then passing commands directly tosystem().
Common filenames included index.php, bypass.phtml, rce.php, static.php,
and obfuscated names like \u0062\u0079\u0070\u0061\u0073\u0073.php (decoded as bypass.php).
Post-Exploitation Backdoor
After initial compromise, attackers deployed a secondary backdoor called accesson.php.
This file was scattered across multiple directories (var/assets/images, vendor/assets/images, etc.)
to ensure persistence. The backdoor provided:
Use this command to find out accesson.php file : find /var/www -name 'accesson.php' -type f
- A beacon fingerprint (printing
8194460). - Remote code execution via cookie-authenticated
eval(). - File upload capability for further malware deployment.
Cleanup Steps I Took
- Scanned the database for malicious strings and removed compromised CMS blocks.
- Deleted rogue directories and PHP files from
pub/media. - Restored clean
.htaccessrules to block PHP execution in media folders. - Applied a hotfix module to mitigate the vulnerability.
- Ran a full malware scan to ensure no hidden backdoors remained.
Hotfix Module
For immediate protection, I deployed the community patch module available here: Magento2 PolyShell Protection Module. This module acts as a hotfix, preventing attackers from exploiting the vulnerable upload path. It’s not a substitute for upgrading Magento, but it provides a quick layer of defense while planning long‑term fixes.
Lessons Learned
- Always monitor
pub/mediafor unexpected PHP files or auto‑generated folders. - Keep Magento patched and upgrade‑safe — older versions are more vulnerable.
- Use a Web Application Firewall (Cloudflare, ModSecurity) to block malicious requests.
- Maintain clean backups before and after incidents for faster recovery.
- Plan upgrades to Magento 2.4.9 or newer, which includes stronger protections.
Conclusion
Facing PolyShell firsthand reminded me that Magento security is never “set and forget.” It requires continuous monitoring, patching, and proactive defense. If you’re running Magento 2.3.x or older, I strongly recommend applying the hotfix module and planning an upgrade to Magento 2.4.9 or newer.
For more details on the hotfix solution, visit the GitHub PolyShell Protection Module.
