Skip to content
MAGEKWIKScanner
critical CVE-2015-1397 CVSS 6.5

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

Magekwik Security 6 min read

CRITICAL CVES CVE-2015-1397 CVSS 6.5 scan.magekwik.com

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.

What it is

"Shoplift" is the community nickname for the vulnerability chain that Magento's SUPEE-5344 patch closed on 9 February 2015. (Check Point researchers found and reported it; the "Shoplift" name came from the patch and community coverage as stores were exploited, not from the original advisory.) It affects Magento 1 CE up to and including 1.9.1.0 and EE up to and including 1.14.1.0. The chain is three linked CVEs: an admin authentication bypass (CVE-2015-1398), a SQL injection in the admin grid export path (CVE-2015-1397), and a remote file inclusion primitive (CVE-2015-1399). Individually they are unremarkable. Composed, they give an unauthenticated remote attacker arbitrary SQL execution, and from there code execution, against any exposed storefront.

Practical impact

Full compromise with no credentials. The SQLi alone lets an attacker mint an admin_user row, which is enough to install a module, drop a PHP shell, and skim cards. NVD scores CVE-2015-1397 at CVSS v2 6.5, but that number describes the isolated injection, not the chained, pre-auth reality.

Root cause

The injection lives in Mage_Adminhtml_Block_Widget_Grid::getCsvFile(), reached through the admin grid range filters. When a grid column filter is a range (a from/to pair), the value is passed as an associative array into Varien_Db_Adapter_Pdo_Mysql::prepareSqlCondition(). That method builds the SQL fragment from the array keys — and it honours an extra field_expr key that is treated as a raw column expression and interpolated into the statement without quoting or binding. The search-terms report grid exposes this path via its popularity column filter — the popularity[field_expr], popularity[from], and popularity[to] parameters.

None of this matters if the request never reaches an admin controller. That is what CVE-2015-1398 supplies. The admin pre-dispatch authentication check only rewrites the request to the login/denied action when a specific condition is met; when it is not met the controller is left unchanged and execution continues. Supplying a crafted forwarded parameter — logic meant for an alternate dispatch flow — flips that condition, so the auth check falls through and the grid export action runs unauthenticated. The RFI stage then abuses the core_file_storage table plus a phar:// wrapper to turn a written media file into executed PHP.

How attackers abuse it

The public proof of concept (Exploit-DB 37977) is a single POST to the CMS WYSIWYG directive route, carrying the forwarded bypass and a popularity[field_expr] payload whose subquery writes directly into the admin tables.

Representative Shoplift request (structure, not a working exploit)
POST /index.php/admin/Cms_Wysiwyg/directive/index/ HTTP/1.1
Content-Type: application/x-www-form-urlencoded

___directive=e3tibG9jayB0eXBlPUFkbWlu...  # base64 admin grid block
&filter=<url-encoded popularity[field_expr] SQLi>
&forwarded=1

Who got hit

Shoplift became the textbook example of how fast a public Magento bug is weaponised. SecurityWeek reported working exploits within 24 hours of the technical write-up; Sucuri saw them in the wild days later, injecting rogue administrator accounts and card-skimming JavaScript into checkout. Because SUPEE-5344 lagged on a huge share of the install base, well over a hundred thousand stores were exposed at the same moment — a single, largely automated campaign against the whole ecosystem.

How to check

Confirm the version and whether SUPEE-5344 is applied, then look for the persistence attackers leave behind — most often an unexpected admin account.

Read-only checks
# Version — anything <= 1.9.1.0 (CE) / 1.14.1.0 (EE) unpatched is in range
php -r "require 'app/Mage.php'; echo Mage::getVersion(), PHP_EOL;"
grep -l "SUPEE-5344" app/etc/applied.patches.list 2>/dev/null

# Rogue admins created around the compromise window (run in the DB):
# SELECT user_id, username, email, created FROM admin_user ORDER BY created DESC;

How to fix it

  1. Apply SUPEE-5344 immediately. If you cannot apply raw SUPEE patches, move to OpenMage LTS, which bundles every SUPEE fix on a maintained Magento 1 codebase.
  2. Assume compromise if you were unpatched during the wave: audit admin_user for accounts you did not create, review core_config_data and CMS/layout tables for injected scripts, and hunt for PHP shells under media/ and web roots.
  3. Rotate all admin credentials and API keys, then restore code from a known-good build rather than deleting individual injected files.
  4. Magento 1 is end of life — the durable fix is migrating to a supported Adobe Commerce / Magento 2.4.x release.

The real lesson

Shoplift is a decade old, but the pattern repeats every year: patch ships, PoC drops within a day, mass exploitation follows. The only defence that scales is patching fast — measured in hours, not weeks.

References & sources

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

  1. Check Point — Analyzing the Magento Vulnerability
  2. NVD — CVE-2015-1397
  3. Sucuri — Magento Shoplift (SUPEE-5344) Exploits in the Wild
  4. SecurityWeek — Magento Flaw Exploited in the Wild Within 24 Hours
  5. Exploit-DB 37977 — Magento eCommerce Remote Code Execution

← All security posts