之前积累了XSS 有一段时间,因为目前开始了一件有趣的工程,需要整合非常多的知识,其中Web 安全这一块出现最多的,应该就是XSS,SQL注入了,再加上乌云泡着看别人的文章,看各家大网站的漏洞,决定把这一块知识聚拢一下,写成一篇文章。想了想,从简单到难,那就是一条打怪升级之路,所以就从最简单的反射型漏洞开始,一点一点提高,直到把大部分XSS 的形式找出来。
level 1 无过滤规则的XSS
最简单的跨站,也就是我们说的反射型跨站,也叫作非持久型,参数型跨站脚本。这种类型的脚本出现的面非常的广,互联网上这样的漏洞非常多,一般出没在各路小站点,大站点很少出现。乌云的漏洞列表里,海量的XSS 漏洞都来自互联网上访问量不高的小站,被辛苦挖洞的XSSer 们发掘出来的。
站在新手村我们的,需要一个最简单的野怪刷一下,这个野怪上下无任何装备,没有一点防御。也就是说,这个XSS 漏洞对于用户的输入,不做任何过滤行为。
一般来说,XSS 存在的地方,一定是需要有输入和输出概念的,一般的过滤规则,也是出现在输入阶段或者是输出阶段,如果两个都没有过滤,那么很轻松的就造成了漏洞。通常来说,这种洞非常好刷,比较自动化的方式是,建立一个爬虫系统,预设一些URL,爬虫爬取网页,在网页源码中寻找用户可以输入的地方,然后在可以输入的地方,将构造好的XSS 代码以输入形式,构造成请求,然后观察响应,是否对我们的输入做了过滤策略。如果是原本的返回,那么我们就说可能存在有xss漏洞。
同时,有另一种更为简单的漏洞,是直接在URL 中,如果有直接赋值参数的行为,也相当于一个可输入的位置,我们直接在URL 中将XSS 代码构造在URL 中,观察返回是否做了过滤处理,如果没有,那么就是一个最简单的野怪诞生。
在乌云中,有不少这样的漏洞,小站很多,大站很少,因为大站一般都有完备的过滤规则,很难在这些小问题上有任何闪失,再加上如今浏览器基本上都有安全策略对此类型进行防御,所以这种威力相对较小。
之前在HTTP 的文章里,有详细讲过 URL的格式,其基本格式如此:
每个结构对应的含义如下:
通常的注入发生在query 这一块,而一般一个安全的行为,就是对query 中的字符进行过滤,以防止xss。以百度的URL 为例,一个通常的URL 查询之后的造型是下面这样的:
http://www.baidu.com/s?wd=%E6%A0%87%E7%82%B9%E7%AC%A6&rsv_spt=1&issp=1&rsv_bp=0&ie=utf-8&tn=baiduhome_pg&inputT=2969
问号之后有一大堆参数,&用来分割参数,他们对应的是什么意思不是本文关注的重点,可以参见这一篇文章百度搜索URL 参数解析。
其中wd 就是我们所说的搜索关键词,也就是我们的输入,如果我们将此字符改成
在输出时我们看到,URL 变成了如下,可疑的部分被转义了。
https://www.baidu.com/s?wd=%22%3Cscript%3Ealert(%27xss%27)%3C%2Fscript%3E&rsv_spt=1&rsv_iqid=0xb3f5d3380002c15f&issp=1&f=3&rsv_bp=1&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&oq=%26lt%3Bscript%26gt%3Balert(%26%2339%3Bxss%26%2339%3B)%26lt%3B%2Fscript%26gt%3B&rsv_t=455e8xS9GVGwfM%2BTxjkNH6uUohEOPZHQFWlqocmOh9s1caJr5IHzVrPJJKJ1OwdTglc3&inputT=5478&rsv_sug3=27&rsv_sug1=21&rsv_sug7=100&rsv_pq=cce2beda0002a800&rsv_sug2=0&rsv_sug4=6278
在这里举一个大站腾讯的简单的xss,是乌云上某马甲提交的,作为一个最简单的XSS 挖给大家学习。网站的网址是这样的:
http://app.data.qq.com/?umod=commentsoutlet&act=count&siteid=3&libid=9&dataid=1480&score=1&func=haoping&_=1353475261886
如果我们在这个URL 里尝试修改参数,将score 参数改成
而输出的源码并没有发生变化:
在网易中看到的结果就变成了这样:
这很显然,就是一个xss漏洞了,将经典的xss 代码插入进去即可:
score=
效果如下:
这就是一个最无防御的XSS 存在,很明显的,它简单,暴力,当然也是极容易防御的,所以在一个较高级的攻防对抗,或者是大站漏洞中,基本上不会出现这样的漏洞(然而腾讯还是有这样的问题~~)。
level 2 包装进script
上一等级里,我们的xss 构造格式是在img 中,然后直接通过URL 参数提交,通常反射型的XSS 比较广泛,但是伤害一般来说没有太高,而且比较容易防范。除了img 元素,还有诸如input, iframe,a href, 主要利用的是href 或者 src 可以使用javascript, 或者是使用onerror,表示当前图片无法显示时候可以调用的脚本。更多的内容,接下来详析。
接下来,我们针对的还是反射型的XSS,仍然是在参数中,作为目标文件中的参数,通过URL 传递给它,但是没有对该参数进行详细的过滤,造成了有机可趁,继续放出腾讯家以前的一个例子,也是乌云上的,网址如下:
http://activity.soso.com/common/setParentsInfo.php?callback=aaaaaaaaa
此处的callback 参数,如果没有过滤的话,得到的网页源码里,我们就会看出来,如下:
拿出这一块的上下文代码,大约构造是这样的:
aaaaaa如果我们替换成
当然,我们注意到,上边的script 还没有闭合,为了让代码提前跳出前一个script ,我们应该在前边吧sciprt 闭合,这样:
这样,很明显,就会继续发起了XSS 弹窗。但是,如果我们不允许输入破折号呢,上边所说的就没有办法了,但是,这并不代表毫无办法,还有一些具有威胁的函数,比如eval, String.fromCharCode, execute,这些都会造成XSS,也要过滤。如下,我们使用eval() 来构造攻击:
http://activity.soso.com/common/setParentsInfo.php?callback=eval('alert(1)');void
callback=eval('alert(1)');void 仍然令我们的源代码语法正确,能够正确执行。
但是像这样构造出来的情况,其实非常的少见,因为正常传第一个参数进去,开发者都会将 " 过滤掉,这样构造就失败了。
我们知道,XSSer 和 防御者之间的斗争从来就是道高一尺,魔高一丈的过程,防御者绞尽脑汁去过滤所有可能出现的情况,去处理所有可能的奇葩诡异编码情况,而XSSer 又会绞尽脑汁的去挖掘茫茫网络中漏洞,努力用各种奇技淫巧构造出五花八门的形态,看起来诡异无比,然而偏偏又能让javascript 语法正确,正常运行。
然而xss 却又一直是热门,但并不是很受重视的攻击手法,原因大概是这样的:
- 挖洞太麻烦,很耗时间,看上边两个漏洞,其中一个甚至是在某个获取QQ 应用宝上某个app 数据的URL 里发现的,而这种页面甚至很难被发现,所以他的伤害比较低,找到它却又要花费大量时间,而且还有很多构造方法不能成功,需要尝试各种模式。
- 这种伤害不是很大的反射型攻击,尚且还有机会通过爬虫自动化的挖掘到漏洞存在的可能,有很多复杂的存储型和DOM 型漏洞,更难通过爬虫挖到。
- 需要有良好的HTML,JS 功底,但是呢,如果功底好的话,直接就跑去做前端了,前端业务现在那么缺高级工程师。更多的,还需要有PHP,JSP 功底。
- 而Website 设置http-only,crossdomain.xml 时候,很多模式化的xss就失去力量了。
- 然而为什么热门呢,因为HTTP 世界的混乱,之前在写Web之困读书笔记的时候,作者也是强力吐槽了这个混乱的HTTP 世界,所以造成了XSS 几乎无处不在,而如果一个利用好的XSS,或者CSRF漏洞,会在某些情况下,造成难以弥补的伤害。
- 本质上将,SQL注入和XSS 都是由于代码上相似的漏洞造成的,而SQL 注入的危害要比XSS 看起来危险很多,很多人在挖SQL 注入漏洞的时候,顺手就挖几个XSS,也是很正常的。
- XSS 虽然看起来比较温柔,但是配上社工手段,可造成的影响仍然是不可小觑的,所以XSS 会火下去。
level 3 HTML 中的野怪
当然XSS 的漏洞不仅仅只出现在script 代码块中,还可以包含在丰富的HTML 的标签属性中。比如img,input 等一系列标签,基本格式是 < HTML标签 onXXXX="在这里" > 或者是放在伪URL 里,比如< a href = "javascript:在这里"> xxxx 。
一般这样地方的参数,很少是直接通过输入就直接放进去的,不过有时候常常是接受了用户的输入,最后输出的时候,会出现在这些位置,但如果对用户的输入没有做详尽的处理和过滤的话,就会出现明显的XSS 漏洞。来个栗子:
比如某网站是这样的:
http://example.com/search.php?word=helloworld
对应在HTML 代码中,他出现在了这样的区域里:
开发者没有对helloworld进行过滤的话,我们直接构造
word=helloworld" onclick="alert(/xss/)
然后在对引号括号等,使用URL 编码,直接变成如下结构:
helloworld%22+onclick%3d%22alert(%2fxss%2f)
也就完成了xss过程,不过这种漏洞现在已经非常稀少,因为它太容易过滤了,只需要将双引号过滤即可,一般做法就是将双引号过滤成HTML 实体编码,也就是quot; 对于HTML 解析器,它能够识别在文本节点和参数值里边的实体编码,并且在内存中创建文档树的表现形式时,透明的对这些编码进行解码。所以,在创建DOM 树结构的时候,"(有个分号,但是markdown会直接转了); 还没有被解码成引号,而且创建文档树的内容的时,才会考虑解码,而这时,其XSS 功效已经不能发挥作用了。
于是,对于有过滤规则的情况下,该标签将变成:
但是,仅仅是这样的过滤,显然是不够用的,还有其他的注入点可以进,继续在乌云上来看腾讯的例子,考虑这样一个网址:
http://follow.v.t.qq.com/index.php?c=follow&a=index&appkey=801004516&bg=FFFFFF&hsize=80&name=Zhanglifenft,chengyizhong,xiangyang20112007,linchufang,leonardoit,linchufang,qingfengxu6685,zhouzhichen001,yuguoming-ruc,luomingtitan,bjwbgq,kezuozongbianji,weibotalk,lee007,jxzhongweizhi,lihaipengtx
我们查看输出的HTML 源码,发现bg 那里对应的是background-color,我们尝试那里用不同的字符尝试,观察其过滤情况。在这里,我让bg = "<>() 就是希望观察一下它的过滤情况,基本上所有的字符都被过滤了,但是只有\ 没有被过滤
如何只用 \ 构造利用语句呢,我们可以想到CSS 中的字符编码,CSS 提供了一套转义处理策略,一个反斜杠后边跟1~6位十六进制数字。然后利用CSS 的expression 来调用JavaScript 代码。也就是试图构造出
expression(eval(alert(/xss/))
这样的代码,完整来说,就是这样的:
用分号来结束backgroud-color,然后 w: 后边跟上expression,如果expression 要被过滤,那就加上转义,把expression 随意变下形就可以,于是,在下边这样的代码构造下,漏洞又被利用了。
http://follow.v.t.qq.com/index.php?c=follow&a=index&appkey=801004516&bg=;w:expr\65ssion\28%20eval\28\27\69\66\28\21\77\69\6e\64\6f\77\2e\78\29\7b\61\6c\65\72\74\28\64\6f\63\75\6d\65\6e\74\2e\63\6f\6f\6b\69\65\29\3b\77\69\6e\64\6f\77\2e\78\3d\31\7d\27\29\29&hsize=80&name=Zhanglifenft,chengyizhong,xiangyang20112007,linchufang,leonardoit,linchufang,qingfengxu6685,zhouzhichen001,yuguoming-ruc,luomingtitan,bjwbgq,kezuozongbianji,weibotalk,lee007,jxzhongweizhi,lihaipengtx
不过很遗憾的,expression 当年是微软搞出来的技术,但是一直没被其他浏览器接受,同时,甚至微软自己如今也抛弃了这种特性,它出现在IE6,IE7,和IE8的一些早期版本,因为微软官方也认为该属性不具有通用性,而且它处理的事务,如今已经能够在CSS 中正常的完成,如min-width,max-width, 这些都已经在IE8之后得到很好的支持,所以expression 也只能在这两个古老版本上起效。
那么,继续考虑一些别的情况,考虑下面这个网站:
http://stock.finance.qq.com/report/search.php?searchtype_yjbg=yjjg&searchvalue_yjbg=aaaaaaaaaa
其输出的HTML 代码中,我们可以找到它:
对于放在javascript: 中的伪URL,其效果和放在script 代码块中没有区别。在这里 aaaaaa我们可以考虑对其做点什么,很自然的,我们想到用单引号闭合,然后后边加上alert(/xss/) 这样的构造,看起来比较绕,其构造步骤是这样的:
location.href='...&searchvalue=aaaaaa'
location.href='...&searchvalue=aaaa'+alert(1)+''
location.href='...&searchvalue=aaaa'+alert(1)+''
如果单引号,被过滤,就要改成HTML 编码,这样,就能在源代码中javascript 伪URL那里添加了alert(1) 这样的XSS。这步骤改造完毕之后,我们将可能被过滤的&-> %26,#->%23 转换成URL 编码,构造成这样的URL:
http://stock.finance.qq.com/report/search.php?searchtype_yjbg=yjjg&searchvalue_yjbg=aaaaaaa%26%23x27;%2balert(1)%2b%26%23x27;
至此,又完成了一次XSS 注入,但到此处,是否有一个疑问呢,还是关于编码解析的问题。在上一个栗子中,我们说,将双引号,改成" ; 这样的形式,就不会出现异常的解析了,但是这里,我们主动的将单引号改成了 ; 这样的形式,反而成功的完成了XSS 呢。
其实,这是一个解析顺序的原因,正常的解析顺序是这样的,先对URL解码,那些用URL 编码的字符都变成解码后的参数传出去,然后是HTML 解析,HTML 解析,此时 ,是先构建DOM文档结构,然后才会对每一个文本节点,属性值内容进行解析,这时候,HTML 实体编码的部分,才会还原回来,这个时候已经不会对DOM 结构造成影响了。然后是JS 解析,此时才会执行JS 代码的内容。而此时,HTML 已经完成了解码。
对应上边的栗子,在JS 解析之前,HTML 已经对那些编码完成了解码,对于JS 来说,一切都写的清清楚楚的了。
回到那个栗子,我们利用的代码,原样是这样的:
当我们构造完成利用代码之后,对于页面上来说,就是要点击按钮,也就是onkeydown。 不仅要将URL 传出去,还需要用户点击按钮,这样造成的威胁小很多,不如img 标签里的onerror ,onload那样可以自动触发。
最后我们再考虑一下如何防守吧,上上栗子的问题,在于漏掉了斜杠的过滤,那么\ 该过滤还是要过滤的。对于上边这个栗子,可以考虑二次过滤,也就是将&都过滤为 & ;,这样不仅过滤了无编码的单引号等格式,又可以过滤掉利用实体编码想要逃过的实体编码格式。而如果只是用正则去片段NN..等形式,实际上是不一定搞定所有的HTML 编码形式的。
level 4 离奇的宽字节
搞过SQL 注入的,应该是比较了解宽字节注入的,由于某些SQL 注入的核心是提前出线单引号来闭合前边的输入,然后在后边可以插入别的语句,联合查询等等。所以比较一般的过滤方式是将单引号转义,加一个斜杠。但此时忽略了编码的神奇。如果开发者在设置编码支持的时候,如果选择了GBK,gb18030,utf-8 等方式,实际上是支持十六位编码的。
最常见的方式,也就是在url里,在引号%27 或者是 %22 之前,加入%df, 由于0xdf 对应的大于128,所以,解析器会认为他和后边的组成了16位的编码,就会吃掉后边的字符,而后边跟着的字符,又恰恰是我们给引号添加的斜杠,%5c,于是%df 就会吃掉%5c 合并成一个字,引号重新暴露。
这种方法在XSS 不常见,但是如果某些XSS 在写过滤规则的时候,如果处理不当,还是有可能出现宽字节注入的情况,考虑如下url:
http://open.mail.qq.com/cgi-bin/qm_help_mailme?sid=,2,zh_CN&t=%22;alert(1);//aaaaaa
此处双引号被过滤了,变成了" ;,如下:
如果我们尝试一下采用宽字节注入,考虑构造成如图所示:
zh_CN&t=%c0%22;alert(1);
令人惊奇的是,这次注入成功了,观察代码如图:
当然,此处所遇到的问题,应该并不是前边提到的传统的形式,%c0 吃掉%5c ,因为很明显,此处没有使用斜杠转义,而是转成了" ; 只能把原因归咎于正则表达式处理的问题。
我们看到,即使当以注意到了问题所在的时候,仍然可能犯错误,而且是以意想不到的方式犯错,黑客渗透的方式,可能会以所有意想不到的形式进行。
我们将防御性代码比做成安全的城墙,那么正则过滤引擎,应该是这座安全长城的第一站,而在《Web 之困》 一书中,作者也说过,要想试图过滤掉所有的危险的编码,这几乎是不可能完成的任务。但作为开发者,比黑客再多想一些,这是应该的。
在XSS 界,拥有各种各样的形式去变形构造,在owasp 里,这篇XSS Filter Evasion Cheat Sheet 详细介绍了各种变形,以期能穷尽目前已知的各种变形手段,下次,我会对其中的变性手段,进行总结。但是,你想要过滤这所有的变形手段,几乎是不可能的,即使你过滤了他们,而引擎本身出现的错误,又会创造新的漏洞,上述例子就是这样的。
被忽略的反斜线
通常,过滤XSS 就是要考虑过滤各种特殊的控制字符,比如尖括号,引号等,而如果过滤一旦漏过了某些符号,那就有可能通过各种转义,构造出一个绕过的XSS,下面就是一个例子。
看这样一个网站:
http://mail.qq.com/cgi-bin/login?vt=passport&ss=aaa&from=bbb&delegate_url=%2Fcgi-bin%2Fframe_html%3Furl%3D%25252Fcgi-bin%25252Fsetting10%25253Faction%25253Dlist%252526t%25253Dsetting10%252526ss%25253Dindex%252526Mtype%25253D1%252526clickpos%25253D20%252526loc%25253Ddelegate%25252Cwebmap%25252C%25252C1
杂乱无章,我们对照网页的源码,逐个尝试看能够注入,首先是先定位这些变量对应的位置,主要关注的还是前三个,vt=pass, ss=aaa, form=bbb, 构造完成之后我们在源码中寻找他们的位置如图:
定位到位置之后,我们把这一堆能使用的符号都拉进去尝试,包括引号,破折号,反斜杠等,这里如果能直接利用,最好是有双引号,它可以直接闭合前边的语法,从而构造新的语法,但是,很遗憾双引号这种头号仇恨还是第一时间被过滤了,但是漏过了反斜杠。
我们详细分析一下这一部分,考虑一下,看怎么注入:
核心部分,就是下边那小部分:
如果我们使用了反斜杠,那么双引号就被转义了,语法就变化了:
有一点点机会突破,但是后边的语法就太奇怪了,有语法错误了。肿么办,我们在试试正斜杠,发现也没有被屏蔽,perfect,我们用正斜杠来讲后边直接注释掉,让语法正常。
location.href="........."+"&ss=aaaa\"+"&from=1//"+"¶m=";
但是还有一个问题,& 在这里,被考虑成了一个与操作,优先级是高于 =号的,变成了("字符串"&from)=1 的语法,这仍然是错误的。但是,如果我们再测试一下,= 号会不会被屏蔽呢,=号也可以用,那么我们改变一下语法,添加一个等号,变成 ==:
location.href="........."+"&ss=aaaa\"+"&from==1//"+"¶m=";
于是语法编程了("string")&(from==1)的样式,from 变成了一个bool操作,但现在又面临了新的问题,如果你在URL 里本来该是一个定义的操作,却变成了一个判断的操作,from 就变成了未定义的状态了,语法仍然会报错,这我们就要进一步理解JavaScript的语法了,如果我们把from 当做一个变量或者是方法,如果是方法,无论在何处定义,都会被拉到最简便,所以我们在from 的部分再添加一个步骤:
location.href="........."+"&ss=aaaa\"+"&from==1;function from(){}//"+"¶m=";
这样,from 就不会被当成是未定义的了,但问题又来了,我们现在添加了许多东西,而添加的这些东西,包含了许多特殊字符,会不会通过呢,经过实际测试,还真是悲剧了,空格符被转义了:
空格符被转义了怎么办呢,我们找到新的替换品,那就是/**/, 这是一个注释符,之前我们也测试过了,斜杠不会被过滤,那么这个注释符,成功的顶替了空格,形成了正常的语法。
location.href="........."+"&ss=aaaa\"+"&from==1;function/**/from(){}//"+"¶m=";
从语法上看,这样就OK 了,我们的攻击代码可以放function 的前边,直接用alert(/xss/);测试,最终代码:
http://mail.qq.com/cgi-bin/login?vt=passport&ss=&from==0;alert(1);function/**/from(){};//&delegate_url=%2Fcgi-bin%2Fframe_html%3Furl%3D%25252Fcgi-bin%25252Fsetting10%25253Faction%25253Dlist%252526t%25253Dsetting10%252526ss%25253Dindex%252526Mtype%25253D1%252526clickpos%25253D20%252526loc%25253Ddelegate%25252Cwebmap%25252C%25252C1
结果毫无疑问弹了窗。
那么回到源头去搜索整个注入的过程,我们发现,注入的过程,颇有几分SQL 的风采,都是利用各种语法上的技巧,在我们的SQL注入中,一些常见的技巧,比如基于重言式,这和XSS 的试图闭合语法相似,比如联合查询法,试图借助未转义的字符,来完成注入。
这个漏洞的挖掘过程,就是从一个狭小的入口进入,借助了字符过滤不完整的漏洞,挖开了深层的内容。所以,在实际编程开发中,对特殊字符的控制,是需要慎之又慎的,一旦有一个小小的漏洞,就会被随时攻破。
换行符的偷袭
上一次是反斜杠发挥的妙用,它默默地转义了一个双引号,还有一些其他有意思的符号,比如换行符也能发挥妙用,这次是来自换行符的一发偷袭。
看这样一个地址:
http://datalib.games.qq.com/cgi-bin/search?libid=178&FilterAttrAND=3602&FilterValueAND=aaaaaaaaaa
逐个测试注入点,我们发现最后的FilterValueAND 的输入点在源码中找到了输出点:
它出现在JS 语句里,一上来就感觉有戏。接下来尝试写入特殊字符,测试过滤情况。正常的情况下,尖括号,双引号:
但是令人奇怪的是,最后一个输出点竟然是在一大段注释里,这应该是开发的一个失误:
看到注释想到了什么呢?如果这里插进来一个换行符,那么应该被注释的部分就不是注释了。那后边再跟注入语句,就能够执行了。然后我们在用一个双斜杠来注释后边的无用部分。利用代码如下:
http://datalib.games.qq.com/cgi-bin/search?libid=178&FilterAttrAND=3602&FilterValueAND=%0aalert(/xss/);//
直接就弹窗了。
这一次利用的太过简单,看起来应该是开发的一时疏忽,将一大段内容注释了,而注释里原本好包含了输出,那就有可能出问题了。
那么下面再看一个更综合的例子,地址如下:
http://cgi.data.tech.qq.com/index.php?mod=search&type=data&site=digi&libid=2&curpage=1&pagenum=30&filterattr=138,138|16|4,5,4,5&filtervalue=3500-4000,%B4%F3%D3%DA4000|%D0%FD%D7%AA|WCDMA,WCDMA,HSDPA,HSDPA&tplname=centersearch.shtml&orderby=aaaaaaaaaaaa
看一下源码,先测试双引号,妥妥的被过滤,HTML标签里的东西没希望了。往后边看,第二个又出现在了注释里,看来开发还是很希望遗留这些漏洞的,我们直接用一个换行符。
但问题是注释那里被注释掉了,但是接下来的var searchOrder="....";这一句就麻烦了。
//document.getElementById("order_select").value="aaa
alert(/xss/); //";
var searchOrder="aaa
alert(1);//";
第一个是OK 了,第二个语法错误了。那么又想到什么了呢,在JavaScript 语法里,一个反斜杠可以让语法让换行的内容接起来,形成多行写法。
var sarchOrder="aaa\
alert(/xss/);//";
于是,语法上又恢复了正常,而这一部分内容我们不用管它,只要上一个有效就可以了。但问题是,反斜杠被过滤了,过滤的方法是被转义了。
两个反斜杠就没法让JavaScript成立了,怎么办呢?记得之前采用的宽字符的战术,看一眼网页的编码格式,gb2312,说明宽字节是有效的。那我们就用128以上的字符,去吃掉一个反斜杠:
http://cgi.data.tech.qq.com/index.php?mod=search&type=data&site=digi&libid=2&curpage=1&pagenum=30&filterattr=138,138|16|4,5,4,5&filtervalue=3500-4000,%B4%F3%D3%DA4000|%D0%FD%D7%AA|WCDMA,WCDMA,HSDPA,HSDPA&tplname=centersearch.shtml&orderby=aaaa%c0%5c%0aalert(1);//
从结果上看,%c0吃掉了一个%5c,留下了一个反斜杠。
语法完全ok, 于是弹窗。
至此,这种反射型的XSS 基本上就这么些内容了。想要挖XSS 的洞,非常的耗费功夫,因为即使是没有安全编码尝试的开发者,也基本知道一些必须过滤的字符一定要过滤,另外在PHP 这些语言中,也有专门的函数诸如魔术引号来过滤处理。
不过学习这种XSS 类型,将扩宽思路,不仅是从注入的角度来看,能想到各种有意思的注入和XSS 利用,更重要的是从安全编码的角度看待开发,如何保证代码的安全实际上是比效率更加重要的点。
DOM XSS
之前提到的漏洞内容,都是反射型XSS,攻击性一般来说比较低,即用即消,难以持久,而且一般来说,如果cookie 设置成httponly,你就不能通过document.cookie 的方式获取cookie了,在做其他一些事情,反射型xss就显得乏力了。不过,如果没有设置成httponly,还是有方法获取到海量的用户cookie,简单的利用方法就是在一个自己可控的站点,控制一个iframe,然后链接到主站可xss利用的站点,在URL 里写好脚本,做好接受,就能源源不断的接受来自用户的信息了。
比如说新浪微博或者是腾讯微博存在XSS反射漏洞,我们在自己的站点中写好利用的iframe,然后在自己的微博上写一个吸引人的标题,然后附一个经过短链接转义过得链接。如果别人点进去,就会自动触发我们的XSS 脚本。以前Twitter 上也有这样的漏洞,短时间让黑客的粉丝暴涨百万,实际上只是自动执行了关注黑客的脚本。
下面我们进入下一个XSS类型,DOM XSS。所谓DOM 操作,就是利用JavaScript 的DOM 操作来进行利用。关于DOM树,DOM操作的基础,可以参见wikipedia ,可以查看更多信息。
DOM 常见的方法有:
- 获取节点
- getElementsById()
- getElementsByTagName()
- getElementsByClassName()
- 新增结点
- document.createElement() 创建节点对象,参数是字符串也就是html标签
- createTextNode 创建文本节点,配合上一个使用
- appendChild(element) 把新的结点添加到指定节点下,参数是一个节点对象
- insertChild() 在指定结点钱插入新的节点
- 修改节点
- replaceChild() 节点交换
- setAttribute() 设置属性
- 删除节点
- removeChild(element) 删除节点,要先获得父节点然后再删除子节点
- 一些属性
- innerHTML 节点内容,可以获取或者设置
- parentNode 当前节点的父节点
- childNode 子节点
- attributes 节点属性
- style 修改样式
下面我们回到XSS 上,如何利用一个显式的DOM XSS。
这样一个URL:
http://datalib.ent.qq.com/cgi-bin/search?libid=1&keyvalue=aaaaaaa&attr=133&stype=2&tname=star_second.shtml
我们在代码中寻找其输出:
发现了很多个,将其代码格式化之后如下,我们会实际上,被执行的只有一个:
按职业1检索:aaaaaaa