上篇文章讲解了xss的一些基础知识,这篇文章继续研究学习。上篇文章提到了一些理论性的东西,看完估计感觉很快也忘了。简单回顾一下,讲了xss分类:存储型XSS,反射型XSS,DOM XSS。讲了几个简单的payload,也只是理论性的东西。这篇先不继续看理论了,先来尝试尝试如何使用payload~ 玩起~~
理论的东西看了也很快就忘记了,于是我决定找个东西实际玩一玩~ 就从身边的东西,imweb博客入手好了。
仔细看了一下博客,最容易xss的似乎是文章里面的评论框,这个评论框是支持富文本的,当富文本一进来就意味着风险也一并进来了。
评论框的过滤规则一般有两类,第1类我们称为白名单,即:只允许使用白名单内的合法HTML标签,例如IMG。其它均剔除。 第2类我们称为黑名单,即:厂商会构建一个有危害的HTML标签、属性列表,然后通过分析用户提交的HTML代码,剔除其中有害的部分。
我们博客的评论框我测试了一下,应该是黑名单过滤的。
对评论框还完全不了解,看看代码也是压缩了的,懒得去看压缩后的代码= = 直接用富文本试探好了~~
首先我提交了非常简单的一个payload
<img/src=@ onerror=alert(1) />
查看DOM如图所示:
有好消息有坏消息,坏消息是我们发现onerror以及它的属性值都被过滤了,但是也有好消息,我们发现直接提交html代码是不会被过滤的,这就为我们之后的xss提供了可能。Ok,继续试试一些常用的:
<script>alert(1)</script> <a href="javascirpt: alert(1)”></a>
script毫无疑问是会被过滤的,这个我也只是随便试试。a标签当然不会被过滤,但是问题在于我们发现结果是这样的:
整个href及其之后的属性值都被过滤了,这个也在预料之中,我们可以简单的猜测一下原因,也许是:
href
就被过滤了(这个想法后来想想基本不可能, href
要被过滤了正常链接怎么发?当然markdown可以) href
里面的值,发现里面有
这样的东西然后把这个href后面所有东西都过滤了,这个可能性无疑是最大的。 好吧,既然要过滤 ,那我找一些不用
的语法不就完了。继续试试,这回不用
:
<button onclick="alert(1);">xss</button>
结果我们惊喜的发现, button
居然没有做任何过滤的展示了:
然而点击并没有任何反应,看了一下dom:
有点失落,发现 onclick
以及后面的属性值都被过滤了。这时候我突然想到之前我测试的 <img/src=@ onerror=alert(1) />
这个payload的 onerror
也被过滤了,几乎是一样的情形。于是我们又得到了一个线索,可以推测过滤代码有这样一段逻辑,判断提交的评论里有没有on起始的属性,如果有的话,会把它过滤了。
梳理一下上面多次测试得到的线索:
script
被过滤了。 on
开始的属性被过滤了,比如 onerror
, onclick
, onmouseover
等等,这个过滤规则直接废了很多payload。
被过滤了,这个也让很多payload失去了可能。 继续尝试payload吗,还是思考一下上面的线索能给我们带来什么?发现线索3过滤 on
还是比较致命的,好像并没有办法绕开这个过滤。但是线索4似乎有机会啊!
这里先说一个简单的小知识,是我们后面成功xss重要的一步:
在html标签属性的值里字符实体是会被转换成相对的字符的。这意味着下面这两个是等价的: <button onclick="javascipt:alert(1);">xss</button> <button onclick="javascipt:alert(1);">xss</button>
有没有可能代码里面只是简单的判断了 ,对于字符实体并没有处理呢?
我重新构造了一个payload提交了一下:
<button test="javascipt:alert(1);">xss</button>
提交之后查看dom,果然没有过滤!而且正确的解析出来了啊!
但是新的问题来了,只有一个 javascipt
有什么用,代码有了,但是这部分代码不会触发执行啊,因为所有 on
开始的属性都被过 滤了。这时候首先想到的是不用 onclick
类似的带 on
的属性一样能触发JS呢?
这时候,想到了@sogili 大神总结的这样一个构造,这个构造完美的避开了 on
!利用 formaction
进行表单劫持!
<form id="test"></form><button form="test" formaction="alert(1)">X</button>
结果评论展示成了这样:
我前面已经试过,button是不会被过滤的。不幸的是, form
在黑名单里面,查看DOM,变成了这样:
ok,到这一步的时候,有一个思路是怎么绕过 form
被过滤成字符串的代码。纠结了一下,我没有想到好的办法可行。但是页面中会不会本来就有现成的 form
可以用呢!直接把页面中现成的 form
用 formaction
进行劫持是不是就可以了!
兴奋之余,我赶紧搜索了一下关键词 form
,果然找到一个 form
表单!
遗憾的是。。这个 form
表单没有 id
属性,原来有没有 id
也能影响到 hack
成不成功,只能说这里 form
表单没带 id
是运气太好了,因为 button
的 form
属性是需要带上一个 id
的,没有 id
就做不了劫持了。
好吧,这个思路想下去我也没有想到太好的办法。。
重新整理一下思路,我们现在的进展是:
script
被过滤了。 on
开始的属性被过滤了,比如 onerror
, onclick
, onmouseover
等等,这个过滤规则直接废了很多payload。
被过滤了,这个也让很多payload失去了可能。但是在button里用字符实体替换
里的字符可以绕过! button
没有被列入黑名单 iframe
, form
等在黑名单里,会被过滤成字符串。 我们最大的进展就是线索4,这时候可能大家已经想到了,有 javascript
还不好办,直接上 a
标签不就完了!我当时也是这么想的,轻松用一个字符实体就可以顺利xss吗?情况没有预想的那么顺利,我直接用下面的payload:
<a href="javascript:alert(1);">test xss</a>
不出意外,失败了。 href
一样被过滤光了啊。这时候得出下面两个推断:
a
标签里似乎这个字符实体的问题并不存在,目测是对一些无伤大局的标签像button(因为on被处理了),才有字符实体的问题呢。 href
整个过滤了。 情况2非常容易验证,直接提交一个正常的a链接就完了~测试发现推断1是正确的,推断2是错的。但是当时推断2给了一个nice的新想法。直接提交a标签不行,但是在svg里一样可以嵌套a标签啊!于是,尝试如下构造:
<svg width="140" height="30" xmlns="http://www.w3.org/2000/svg"> <a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="javascript:alert(1)"> <rect height="30" width="120" y="0" x="0" rx="10"/> <text fill="white" text-anchor="middle" y="20" x="60">test</text> </a> </svg>
在 svg
里尝试使用 a
标签,遗憾的是 xlink:href
里面的东西也被过滤光了。。如图:
好不容易发现的字符实体的问题在 href
相似的属性里并不存在。怎么办?
有没有办法在提交字符串的时候让 xlink:href
没有敏感的东西,后续再把它设置回去呢。答案是有的!
还是@sogili大神总结的, svg
里可以用 animate
去改变某个属性值,用到这里也一样,先看payload:
<svg width="140" height="30" xmlns="http://www.w3.org/2000/svg"> <a xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href=""> <rect height="30" width="120" y="0" x="0" rx="10"/> <text fill="white" text-anchor="middle" y="20" x="60">hack</text> <animate attributeName="xlink:href" begin="0" from="" to="javascript:alert(1)" /> </animate> </a> </svg>
href
, xlink:href
里面不存在字符实体的问题,我们先让 xlink:href
留空防止被过滤。但是其他大部分标签的属性都存在字符实体的问题, animate
也不例外!在 animate
里通过 to="javascript:alert(1)"
改变 xlink:href
的属性值,成功绕过了评论框的过滤!!成功XSS!见图:
尝试的时候确实了解了很多的东西,开发的时候很多东西可能确实自己也没有注意到,很大程度都是因为安全意识不足。这次简单的hack让我尝试了不少好玩的东西~~
下期继续学习web安全~ 继续向@sogili 乌云@心伤的瘦子 学习~ 继续xss~