刘志龙

2016-02-08 19:06

从零开始学web安全(2)

本文作者:IMWeb 刘志龙 原文出处:IMWeb社区 未经同意,禁止转载

上篇文章讲解了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及其之后的属性值都被过滤了,这个也在预料之中,我们可以简单的猜测一下原因,也许是:

  1. href就被过滤了(这个想法后来想想基本不可能,href要被过滤了正常链接怎么发?当然markdown可以)
  2. 代码里面去判断了href里面的值,发现里面有这样的东西然后把这个href后面所有东西都过滤了,这个可能性无疑是最大的。

好吧,既然要过滤,那我找一些不用的语法不就完了。继续试试,这回不用

<button onclick="alert(1);">xss</button>

结果我们惊喜的发现,button居然没有做任何过滤的展示了:

然而点击并没有任何反应,看了一下dom:

有点失落,发现onclick以及后面的属性值都被过滤了。这时候我突然想到之前我测试的<img/src=@ onerror=alert(1) /> 这个payload的onerror也被过滤了,几乎是一样的情形。于是我们又得到了一个线索,可以推测过滤代码有这样一段逻辑,判断提交的评论里有没有on起始的属性,如果有的话,会把它过滤了。

梳理一下上面多次测试得到的线索:

  1. 富文本标签允许直接提交.
  2. script被过滤了。
  3. on开始的属性被过滤了,比如onerroronclickonmouseover等等,这个过滤规则直接废了很多payload。
  4. 被过滤了,这个也让很多payload失去了可能。

字符实体问题

继续尝试payload吗,还是思考一下上面的线索能给我们带来什么?发现线索3过滤on还是比较致命的,好像并没有办法绕开这个过滤。但是线索4似乎有机会啊!

这里先说一个简单的小知识,是我们后面成功xss重要的一步:

 在html标签属性的值里字符实体是会被转换成相对的字符的。这意味着下面这两个是等价的:
<button onclick="javascipt:alert(1);">xss</button>
<button onclick="j&#x61;vascipt:alert(1);">xss</button>

有没有可能代码里面只是简单的判断了,对于字符实体并没有处理呢?

我重新构造了一个payload提交了一下:

<button test="j&#x61;vascipt: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可以用呢!直接把页面中现成的formformaction进行劫持是不是就可以了!

兴奋之余,我赶紧搜索了一下关键词form,果然找到一个form表单!

遗憾的是。。这个form表单没有id属性,原来有没有id也能影响到hack成不成功,只能说这里form表单没带id是运气太好了,因为buttonform属性是需要带上一个id的,没有id就做不了劫持了。

好吧,这个思路想下去我也没有想到太好的办法。。

重新整理一下思路,我们现在的进展是:

  1. 富文本标签允许直接提交.
  2. script被过滤了。
  3. on开始的属性被过滤了,比如onerroronclickonmouseover等等,这个过滤规则直接废了很多payload。
  4. 被过滤了,这个也让很多payload失去了可能。但是在button里用字符实体替换里的字符可以绕过!
  5. button没有被列入黑名单
  6. iframeform等在黑名单里,会被过滤成字符串。

animate绕过

我们最大的进展就是线索4,这时候可能大家已经想到了,有javascript还不好办,直接上a标签不就完了!我当时也是这么想的,轻松用一个字符实体就可以顺利xss吗?情况没有预想的那么顺利,我直接用下面的payload:

<a href="j&#x61;vascript:alert(1);">test xss</a>

不出意外,失败了。href一样被过滤光了啊。这时候得出下面两个推断:

  1. a标签里似乎这个字符实体的问题并不存在,目测是对一些无伤大局的标签像button(因为on被处理了),才有字符实体的问题呢。
  2. 也许就真的把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="j&#x61;va&#x73;cript&#x3a;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="j&#x61;vascript:alert(1)" /> </animate>
        </a>
</svg>

hrefxlink:href里面不存在字符实体的问题,我们先让xlink:href留空防止被过滤。但是其他大部分标签的属性都存在字符实体的问题,animate也不例外!在animate里通过to="j&#x61;vascript:alert(1)"改变xlink:href的属性值,成功绕过了评论框的过滤!!成功XSS!见图:

总结

尝试的时候确实了解了很多的东西,开发的时候很多东西可能确实自己也没有注意到,很大程度都是因为安全意识不足。这次简单的hack让我尝试了不少好玩的东西~~

下期继续学习web安全~ 继续向@sogili 乌云@心伤的瘦子 学习~ 继续xss~

27条评论

    您需要 注册 一个IMWeb账号或者 才能进行评论。