2013-12-17: 细节已通知厂商并且等待厂商处理中 2013-12-19: 厂商已经确认,细节仅向厂商公开 2013-12-22: 细节向第三方安全合作伙伴开放 2014-02-12: 细节向核心白帽子及相关领域专家公开 2014-02-22: 细节向普通白帽子公开 2014-03-04: 细节向实习白帽子公开 2014-03-17: 细节向公众公开
还有一个类似的点在特定的环境里触发,还没测试,明天测试了再说。
common.inc.php 0x00
if(!empty($_SERVER['REQUEST_URI'])) strip_uri($_SERVER['REQUEST_URI']); //跟进0x01if($_POST) { $_POST = strip_sql($_POST); strip_key($_POST); }//跟进0x01if($_GET) { $_GET = strip_sql($_GET); strip_key($_GET); }if($_COOKIE) { $_COOKIE = strip_sql($_COOKIE); strip_key($_COOKIE); }if(!IN_ADMIN) { $BANIP = cache_read('banip.php'); if($BANIP) banip($BANIP); $destoon_task = '';}if($_POST) extract($_POST, EXTR_SKIP);if($_GET) extract($_GET, EXTR_SKIP);......$forward = isset($forward) ? urldecode($forward) : $DT_REF;//用这里的urldecode来绕过。......
include/global.func.php 0x01
function strip_uri($uri) { //检查了REQUEST_URI,里面有%就解码,解到最后检查敏感字符,我们要引入',即使我们双编码过后,最终还是会被还原成',这里检查了',所以GET提交无解,但是我们POST提交的话,REQUEST_URI就不会接受任何数据,从而绕过了检查。 if(strpos($uri, '%') !== false) { while($uri != urldecode($uri)) { $uri = urldecode($uri); } } if(strpos($uri, '<') !== false || strpos($uri, "'") !== false || strpos($uri, '"') !== false || strpos($uri, '0x') !== false) { dhttp(403, 0); dalert('HTTP 403 Forbidden', DT_PATH); }}function strip_sql($string) {//一长串过滤。我们绕过了上面,下面的话可以采用URL双编码绕过。比如union就可以写成unoin%256E来绕过,前提是要有urldecode或者rawurldecode。 $search = array("/union/i","/0x([a-z0-9]{2,})/i","/select([[:space:]\*\/\-])/i","/update([[:space:]\*\/])/i","/replace([[:space:]\*\/])/i","/delete([[:space:]\*\/])/i","/drop([[:space:]\*\/])/i","/outfile([[:space:]\*\/])/i","/dumpfile([[:space:]\*\/])/i","/load_file\(/i","/substring\(/i","/substr\(/i","/concat\(/i","/concat_ws\(/i","/ascii\(/i","/hex\(/i","/ord\(/i","/char\(/i"); $replace = array('union','0x\\1','select\\1','update\\1','replace\\1','delete\\1','drop\\1','outfile\\1','dumpfile\\1','load_file(','substring(','substr(','concat(','concat_ws(','ascii(','hex(','ord(','char('); return is_array($string) ? array_map('strip_sql', $string) : preg_replace($search, $replace, $string);}
绕过了上面就简单了。module/member/chat.inc.php
switch($action) {......default: if(isset($touser) && check_name($touser)) { if($touser == $_username) dalert('不能与自己对话', 'chat.php'); if(!$MG['chat']) { login(); //当然要登陆咯。 dalert('您所在的会员组没有权限发起对话', 'grade.php'); } $user = userinfo($touser); $user or dalert('会员不存在', 'chat.php'); if($user['black']) { $black = explode(' ', $user['black']); if(in_array($chatuser, $black)) dalert('对方拒绝与您对话', 'chat.php'); if(!$_username && in_array('Guest', $black)) dalert('对方拒绝与您对话', 'chat.php'); } $chat_fromuser = $chatuser; $chat_touser = $touser; $chat_id = $chatid = get_chat_id($chat_fromuser, $chat_touser); $online = online($user['userid']); $user['type'] = 'member'; $type = 1; if(!$_userid && !is_file(get_chat_file($chatid))) $type = 4; $head_title = '与【'.$user['company'].'】对话中'; $chat = $db->get_one("SELECT * FROM {$table} WHERE chatid='$chatid'"); $chat_status = 3; if($chat) { //第一次创建会话的时候执行下面的else,创建过后执行if下面的。 //对话已经存在 if($chat['touser'] == $_username) {//当前为接收人 if($DT_TIME - $chat['freadtime'] > $MOD['chat_poll']*3) {//发起对话人已经断开 $db->query("UPDATE {$table} SET fromuser='$chat_fromuser',touser='$chat_touser',tgettime=0 WHERE chatid='$chatid'"); } else {//发起人在线 dheader('?chatid='.$chatid); } // } else {//当前为发起人 if($DT_TIME - $chat['treadtime'] > $MOD['chat_poll']*3) {//接收人已经断开 $db->query("UPDATE {$table} SET tgettime=0 WHERE chatid='$chatid'"); } else {//接收人在线 // } } } else {//第一次执行这里。 $forward = dsafe($forward);//过滤某些敏感字符的函数,不跟了。累死懒得贴,反正还是双编码绕过就行了。 if(strpos($forward, $MOD['linkurl']) !== false) $forward = ''; //创建一个新对话 $db->query("INSERT INTO {$table} (chatid,fromuser,touser,tgettime,forward) VALUES ('$chat_id','$chat_fromuser','$chat_touser','0','$forward')"); //关键点!0x00已经贴出来了$forward是urldecode所解码而得到的,所以我们能引入'来进行注射。记得$chat_touser要等于当前用户,这样做是为了下面的可显查询。不然就只能盲注。 } } else if(isset($chatid) && is_md5($chatid)) { $chat = $db->get_one("SELECT * FROM {$table} WHERE chatid='$chatid'"); //这里构造我们刚刚插入的$chatid的值就可以查询出来了。 if($chat && $chat['touser'] == $_username) {//等于当前用户。 $chat_id = $chatid; $chat_status = 3; if(check_name($chat['fromuser'])) { if($DT_TIME - $chat['freadtime'] > $MOD['chat_poll']*3) {//发起对话人已经断开 $db->query("UPDATE {$table} SET tgettime=0 WHERE chatid='$chatid'"); dheader('chat.php?touser='.$chat['fromuser']); } $user = userinfo($chat['fromuser']); $online = online($user['userid']); $user['type'] = 'member'; } else { $user = array(); $user['type'] = 'guest'; $user['ip'] = $chat['fromuser']; $user['area'] = ip2area($chat['fromuser']); if($DT_TIME - $chat['freadtime'] > $MOD['chat_poll']*3) {//发起人是游客,并且已经断开,只能查看记录 $time = $DT_TIME - $MOD['chat_poll']*4; $db->query("UPDATE {$table} SET freadtime='$time' WHERE chatid='$chatid'"); } } $head_title = '与'.($user['type'] == 'guest' ? '【游客】' : $chat['fromuser']).'对话中';
是root权限又能引入单引号的话各显神通吧。
休息。。。
危害等级:高
漏洞Rank:20
确认时间:2013-12-19 16:06
已确认存在,我们会尽快修复
2013-12-20:感谢Chora,已修复,详见:http://bbs.destoon.com/thread-55559-1-1.html