XSS基础原理
XSS(Cross-Site Scripting,XSS)类型
反射型:又叫非持久型,攻击者通过右键等方式将XSS代码发给目标,当目标访问连接的时候,服务器接收并处理,浏览器解析这段带有XSS代码,例如http://www.test.com/haha.php?name="><script>alert("xixi")</script>
存储型:攻击脚本通过留言板等地方一起被存储在服务器里,当其他用户浏览了这个被注入恶意脚本的帖子的时候,恶意代码就会被执行
DOM型XSS:一种基于DOM文档对象模型的漏洞,本质上是一种特殊类型的反射型XSS,浏览器为页面创建一个顶级的document object文档对象,接着在生成各个子文档对象,通过JS脚本对文档对象进行编辑来改变页面的元素,攻击者构造一个含有XSS代码的URL,当浏览器处理这个响应的时候,DOM对象就会处理XSS代码
XSS基础
PHP中使用$_REQUEST,所有用户输入的变量数组,包括$_GET$_POST$_COOKIE,4.3版本后不包括$_FILES
例如<?PHP echo $_REQUEST[name];?>
这个代码代表从前面的表单当中获取属性为"name"的提交值
攻击脚本的本质
基于<>的攻击:
我们可以任意的使用<>等引入标记,以此来操纵一个HTML标签,然后通过<script>
标签来插入js或vs编写的恶意脚本代码,如<script>alert('xixi')</script>
基于HTML标签属性:
如果不能构造HTML标记,我们仍然可以通过javascript:code伪协议这一种方式来运行我们的js代码,如<img src="javascript:alert(/xixi/);">
,要注意的是不是所有的浏览器都能够支持伪协议。如果可行的话,我们可以使用href\lowser\bgsound\background\value\action\dynsrc这些属性来测试XSS
空格:
js语句常以分号结尾,如果js引擎认为一个语句是完整的且这一行的结尾有换行符,那么可以省略分号,如果一行中有多个语句,则每个语句必须以分号来结束,除了这两种方式以外,额外的空白字符都不会影响代码的执行,我们可以使用这种方式来拆分关键字以绕过waf,例如<img src="javas cript:alert('haha');" width=100>
这个句子虽然当中有两个空格,但是依旧可以被执行
eval:js中的eval()可以计算字符串并执行内部的js代码,如<script>eval("alert('xxx')");<script>
ASCII:
HTML属性值本身支持ASCII码格式,我们可以参照ASCII码表,把字符转化为对应的码以绕过,如t变成t,同理,我们还可以利用ASCII码来插入空白自如,如 TAB,
换行符,
回车符可以被插入代码中的任何地方,此外,\等字符可以插到js或者vs的头部,如<img src="javascri	pt:alert(xixi)">
示例如下
ASCII表
基于事件的攻击
上面的几种方式都是想办法直接来执行我们的js代码,此外,我们可以靠事件来触发我们的代码,例如<input type="button" value="点这" onclick="alert('xixi')"/>
当我们点击这个按钮的时候,就会触发我们的脚本
可使用的事件列表
onResume
onReverse
onRowInserted
onSeek
onSynchRestored
onTimeError
onTarckChange
onURLFlip
onRepeat
onMediaComplete
onMediaError
onPause
onProgress
onOutOFSync
oncontrolselect
onlayoutcomplete
onafterprint
onbeforeprint
ondatavailable
ondatasetchanged
ondatasetcomplete
onerrorupdate
onrowenter
onrrowexit
onrowsdelete
onrowsinserted
onbounce
onfinish
onstop
onresizeend
利用CSS跨站
CSS样式表在不同浏览器甚至是不同版本之间可能不通用。脚本通常嵌入到style标签或者属性里面,利用expression来执行js代码,如<img style="xss:expression(alert(/xss/));">
,又或者使用样式表里面的url属性来执行xss<img style="background-image:url(javascript:alert('xss'))">
另外,我们可以把CSS脚本写在文件里面,用<link>
标签来引用,如下例
另外还可以使用@import来引入文件,同时,@import能够直接执行javascript代码,如
<style>
@import 'javascript:alert("XSS");
</style>
混淆
混写大小写依旧可以执行代码,同时,属性可以使用双引号也可以使用单引号也可以都不使用,一样能被执行,如<ImG sRc=jaVascRipt:alert(1);>
如果空格被过滤,可以考虑使用/来代替空格<img/scr='javascript:alert(1);'>
可以使用全角字符来绕过
/**/注释符会被浏览器忽略,所以可以使用这个来注释字符,或者插入混淆字符绕过过滤,如<div style="wid/****/th:expre/*heihei*/ssion(alert('xss'));">
面对黑名单式过滤,可以考虑使用注释字符来干扰
或者,样式标签中的\和结束符\0也会被无视,如@\0im\port'\0ja\vascr\000000ipt:alert("xixi")';
或者也可以把关键字进行转码
利用HTML注释存在的问题执行js
<!--<img scr="--><img scr=x onerror=alert(1)//">
<comment><img scr="</comment><img src=x onerror=alert(1)//">
将HTML标签中的某些属性值转码成ASCII码,可以转成十进制(,后面的;可加可不加)或者十六进制(),另外,上面提到的eval()函数,也可以把他内部的js代码转码成为十六进制码(格式为\n),或者配合使用String.fromCharCode()函数使用十进制码<img src="javascript:eval(String.fromCharCode(97,108,101......))">
,另外,样式表也可以使用\连接的十六进制码,js则支持unicode,escapes,十六进制,八进制等等,另外对IE有script encode
拆分法:在未进行过滤但是有字符限制的地方,可以考虑拆分法
防御
XSS Filter:跨站脚本过滤器
XSS Filter一般基于黑白名单的安全过滤策略,如下图一般
preg_replace是一个支持正则的替换函数,用法为ixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )
搜索subject中匹配pattern的部分,再用replacement来替代
过滤除了关键字,还得过滤掉\等特殊字符
css中的expression\javascript\import等关键字