Skip to content
MAGEKWIKScanner
critical CVE-2020-9664 CVSS 9.8

Magento 1 after end of life: SUPEE-11346, the CVE-2020-9664 cliff, and the OpenMage bridge

Magekwik Security 6 min read

CRITICAL CVES CVE-2020-9664 CVSS 9.8 scan.magekwik.com

Magento 1 hit end of life on 30 June 2020 after SUPEE-11346. Every flaw since — starting with the 9.8-rated CVE-2020-9664 — has no vendor patch. What Cardbleed exploited, how to check a store, and why OpenMage LTS is the realistic bridge.

What it is

Magento 1 (Community and Commerce) reached end of life on 30 June 2020. Adobe shipped one final security patch, SUPEE-11346, on 22 June 2020 and then stopped. Every vulnerability disclosed against the 1.x codebase since that date has no vendor fix. The install base did not evaporate on the EOL date — tens of thousands of storefronts still serve checkout on unpatched 1.9.x/1.14.x today, which makes "runs Magento 1" a reliable proxy for "has an unremediated remote-code-execution path."

SUPEE-11346 itself closed two issues that define the risk profile of an abandoned platform: CVE-2020-9664 (PHP object injection leading to arbitrary code execution) and CVE-2020-9665 (stored XSS). The first is the one that matters.

The cliff

NVD scores CVE-2020-9664 at CVSS 9.8 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H) — network-reachable, low-complexity code execution with no privileges required. Note a known NVD-vs-vendor discrepancy: Adobe's APSB20-41 bulletin categorised it as exploitable by an authenticated admin, whereas NVD's vector scores it PR:N (unauthenticated). Either way, on an unpatched Magento 1 store there will never be an official fix — the vendor lifecycle ended before most operators applied the last patch. It affects 1.14.4.5 / 1.9.4.5 and earlier.

Root cause

The structural problem is not a single bug; it is a frozen dependency tree. Magento 1 ships a bundled, forked copy of Zend Framework 1 (itself EOL since 2016), Prototype.js, and a large surface of admin controllers (downloader/, Magento Connect, RSS, import/export) that were written before modern deserialization and SSRF hardening. PHP object injection flaws like CVE-2020-9664 exist because untrusted input reaches unserialize() against classes whose __destruct()/__wakeup() methods perform filesystem or database side effects — the classic POP-chain gadget pattern.

Once the codebase is EOL, each newly found gadget or auth-bypass is permanent. There is no backport, no CVSS re-scoring, no advisory. The only parties writing fixes are the community and the attackers, and the attackers move first because a version string on a dead platform is a guaranteed, non-expiring lead.

How attackers abuse it

The pattern is consistent across the Magento 1 skimming campaigns. An unauthenticated RCE or admin-auth bypass gives a foothold; the attacker then uses legitimate platform machinery to persist and to place a card skimmer on the checkout DOM.

  • Reach an object-injection or upload sink to execute code without credentials.
  • Use the Magento Connect / downloader/ subsystem to install a PHP backdoor (Sansec observed a mysql.php dropper) so access survives the initial patchless entry point being closed.
  • Inject JavaScript into a bundled asset such as prototype.js, or into the CMS/layout, so the skimmer loads on every payment page and exfiltrates PAN + CVV to an attacker host.

Because the skimmer rides an existing, trusted script rather than an external <script> tag, naive CSP allowlists and manual "view source" checks miss it.

Who got hit / real examples

In the weekend of 11-13 September 2020 — ten weeks after EOL — Sansec documented the Cardbleed campaign, the largest automated Magecart operation recorded at the time. It infected roughly 1,900 distinct Magento 1 stores in the first days and climbed to 2,806, about 3% of the entire Magento 1 install base. The intrusions abused the /downloader endpoint and Magento Connect to drop mysql.php and patch prototype.js with skimmer code. Sansec linked the timing to a Magento 1 RCE zero-day advertised for sale by an actor using the handle z3r0day shortly before the campaign.

Not a one-off

Follow-on reporting counted 2,000+ then 2,800+ compromised shops within weeks. The common denominator was not a specific merchant mistake — it was running the EOL platform at all. EOL turned a routine skimming operation into a mass, indiscriminate sweep.

How to check

Confirm the version and whether SUPEE-11346 is present, then look for the persistence artifacts.

Version and last-patch check (read-only)
# Version string — load Mage.php, then ask it (getVersion() is self-contained)
php -r "require 'app/Mage.php'; echo Mage::getVersion(), PHP_EOL;"
# or read the version parts straight from the source:
grep -A8 "getVersionInfo" app/Mage.php | grep -E "major|minor|patch|revision"

# Was the final patch applied? SUPEE-11346 touches these files
grep -l "SUPEE-11346" app/etc/applied.patches.list 2>/dev/null
Skimmer / backdoor triage
# Unexpected droppers in webroot
find . -name "mysql.php" -o -name "*.php" -newermt "2020-06-30" \
  | xargs grep -l "eval\|base64_decode\|assert(" 2>/dev/null

# Tampered bundled asset — compare against a pristine copy
git diff --stat js/prototype/prototype.js 2>/dev/null
grep -RiE "onestepcheckout|guaranteed|atob\(|fromCharCode" skin/ js/ | head

Also review admin user list, secret admin path, and outbound connections from the checkout template. An externally reachable downloader/ is itself a finding.

How to fix it

There is no supported patch stream for Magento 1. Two defensible paths exist; picking neither is the failure mode.

  1. Migrate to Adobe Commerce / Magento 2.4.x. The correct long-term answer, but a project, not a patch. It does not help the store that is exposed this week.
  2. Move to OpenMage LTS. The community fork of Magento 1 Community Edition, actively maintained on the 19.x/20.x lines, is the pragmatic bridge. It backports fixes the abandoned codebase never received — e.g. custom-layout RCE hardening in 19.4.22/20.0.19, arbitrary-upload fixes in 19.4.15/20.0.13, and CVE-2023-41879 (weak 6-hex guest-order protect_code, CVSS 7.5) fixed in 19.5.1/20.1.1. Migration is largely composer-driven and preserves the extension architecture.
Adopt the maintained fork
composer require openmage/magento-lts:^20.1
# then diff local core mods against upstream, re-run compile, retest checkout

Whichever path you choose, treat any current Magento 1 install as breached-until-proven-clean: remove the downloader/ subsystem from the public webroot, rotate admin credentials and encryption keys, verify integrity of all bundled JS, and confirm no unknown admin users. A clean scan of a dead platform is a snapshot, not a guarantee — the only durable remediation is getting off the EOL codebase.

References & sources

Primary sources — advisories, vendor research, and the CVE record. Verify against these, not us.

  1. Adobe Security Bulletin APSB20-41 (SUPEE-11346)
  2. NVD — CVE-2020-9664 (CVSS 9.8)
  3. Sansec — Cardbleed: 3% of Magento 1 install base hacked
  4. The Hacker News — 2,800+ outdated Magento shops hit by skimmers
  5. OpenMage LTS — community-maintained Magento 1 fork
CRITICAL CVES CVE-2015-1397 CVSS 6.5 scan.magekwik.com
critical Critical CVEs

Shoplift (CVE-2015-1397): the Magento 1 SQL injection that was weaponised in 24 hours

CVE-2015-1397 is the SQL injection at the centre of the Magento 1 "Shoplift" chain — an unauthenticated grid-export flaw that let attackers write admin accounts straight into the database. Patched by SUPEE-5344 in February 2015, it was mass-exploited within a day of disclosure. The mechanism, the indicators of compromise, and the fix.

6 min read

← All security posts