针对 WordPress wp-login.php 中 CVE-2026-64638("XSS2Shell") 反射原语的非破坏性、零依赖检测器。
CVE-2026-64638 是 WordPress 核心中的一个预认证反射型 XSS 漏洞,由 PWN.AI 于 2026-08-07 披露(CVSS 8.9,CWE-79),已在 7.0.3 中修复,并向后移植到所有受维护的分支(6.9.6、6.8.7、6.7.6、6.6.6、6.5.9 等)。
根本原因是 PHP 的 strip_tags() 与 WordPress 的 KSES 清理器之间的解析器差异:
strip_tags() 在 < 后出现空白字符时拒绝识别标签,因此
像 < area id=x> 这样的用户名会以纯文本形式保留。<area id="x"> 元素。这会产生带有攻击者指定 id/class/href 属性的 DOM 注入——这是已公开的
多阶段攻击链背后的原语(DOM 污染 → REST JSONP → 应用密码窃取 → 插件上传 →
针对已登录管理员受害者的 RCE)。
两个非破坏性探测(使用随机标记用户名进行的一次失败登录):
<b>marker</b> 以未转义形式出现在错误响应中。< area id=marker> 绕过 strip_tags() 并作为活跃/规范化元素
(例如 area id="marker")重新出现在响应中。没有任何有效载荷会被执行;该工具仅检测攻击者提供的 HTML 是否被渲染为活跃 DOM。 可选附加功能:
--version — 通过 feed 的 <generator> 标签识别核心版本。--jsonp — 验证已发布攻击链所使用的 REST JSONP 封装(_jsonp/_envelope)是否可达。python3 xss2shell_check.py https://example.com
python3 xss2shell_check.py --jsonp --verbose https://example.com
python3 xss2shell_check.py --version https://example.com
python3 xss2shell_check.py --json https://example.com
需要 Python 3.6+,仅使用标准库,无任何依赖。
| 代码 | 含义 |
|---|---|
| 0 | 存在漏洞(反射原语存在) |
| 1 | 已修补 / 不存在漏洞 |
| 2 | 错误(无法访问、WAF 质询、意外响应) |
<area id="…">)。
属性引号的写法因 KSES 代次而异(旧版自定义解析器:
<area id=x>;DOMDocument:<area id="x"> / <area id="x" />),因此
会匹配所有形式。原始 < area …> 透传未经过重新解析时,
在浏览器中只是惰性文本而非原语——它会被报告为
RAW_TEXT_ONLY,不会触发误报。login_errors 过滤器或 CDN/WAF
重写了响应,或者登录错误从不回显用户名,则可能出现漏报。仅限经授权的安全测试。本工具仅用于测试您拥有或已获得明确书面许可评估的系统。 未经授权的测试在大多数司法管辖区属于违法行为。
| Flag | 用途 |
|---|
--version | 识别核心版本(feed generator 标签,主页 meta 作为后备) |
--jsonp | 同时验证 REST JSONP 封装(_jsonp/_envelope)是否可达 |
-v, --verbose | 打印探测响应片段(用于报告的取证) |
--json | 机器可读的 JSON 结果(CI / 自动化) |
| 观察到的行为 | 判定 | 退出码 |
|---|
<b>marker</b> 以未转义形式回显 | RAW_HTML — 存在漏洞 | 0 |
< area id=marker> 被重新解析为活跃的 <area id="marker">(任意引号 / 空元素形式) | AREA_BYPASS — 存在漏洞 | 0 |
| 用户名被 HTML 转义 | ESCAPED — 不存在漏洞 | 1 |
| 标签被剥离,文本保留 | STRIPPED — 不存在漏洞 | 1 |
原始 < area …> 透传但从未被重新解析 | RAW_TEXT_ONLY — 惰性文本,不存在漏洞 | 1 |
| 完全没有回显 | NOT_REFLECTED — 不存在漏洞 | 1 |
| 探测被阻止(HTTP ≥ 400 / 质询页面)或目标无法访问 | ERROR | 2 |