<p>下面是对版本号为3.0.3的分析和测试结果。<br></p><p>任意文件上传漏洞源于该插件自带的 “插件更新”” 功能,在启用该插件的同时会将一系列的action操作都注册到WordPress的ajax请求里。并且插件在接受更新请求后并没有判断用户权限,导致恶意者可利用该点进行攻击。<br></p><p>所涉及文件:/revslider_admin.php<br></p><pre class="lang-php" data-lang="php"> //add common scripts there
//self::addAction(self::ACTION_ADMIN_INIT, "onAdminInit");
//ajax response to save slider options.
self::addActionAjax("ajax_action", "onAjaxAction");
}
</pre><p>该插件在启用时,会将 ajax_action 参数与函数 onAjaxAction() 进行绑定,当通过 /wp-admin/admin-ajax.php 向插件传递参数时会调用 onAjaxAction()。</p><p> onAjaxAction() 函数关键部分如下:</p><pre class="lang-php" data-lang="php"> case "update_plugin":
self::updatePlugin(self::DEFAULT_VIEW);
break;
</pre><p>当post参数 $client_action 为 “update_plugin” 时,会调用 updatePlugin() 开始升级插件。</p><p> updatePlugin() 函数位于 /inc_php/framework/base_admin.class.php 中。</p><p>所涉及文件:/inc_php/framework/base_admin.class.php</p><pre class="lang-php" data-lang="php"> protected static function updatePlugin($viewBack = false){
$linkBack = self::getViewUrl($viewBack);
$htmlLinkBack = UniteFunctionsRev::getHtmlLink($linkBack, "Go Back");
$zip = new UniteZipRev();
try{
if(function_exists("unzip_file") == false){
if( UniteZipRev::isZipExists() == false)
UniteFunctionsRev::throwError("The ZipArchive php extension not exists, can't extract the update file. Please turn it on in php ini.");
}
dmp("Update in progress...");
$arrFiles = UniteFunctionsRev::getVal($_FILES, "update_file");
if(empty($arrFiles))
UniteFunctionsRev::throwError("Update file don't found.");
$filename = UniteFunctionsRev::getVal($arrFiles, "name");
if(empty($filename))
UniteFunctionsRev::throwError("Update filename not found.");
</pre><p>简要分析一下文件上传漏洞形成的过程。首先该函数(updatePlugin())获取了post过来的文件的信息:<br></p><pre class="">$arrFiles = UniteFunctionsRev::getVal($_FILES, "update_file");
</pre><p>随后会获取上传文件的文件名,MIME类型(插件将MIME类型的检测代码注释掉了)。<br></p><pre class="lang-php" data-lang="php">
$arrFiles = UniteFunctionsRev::getVal($_FILES, "update_file");
if(empty($arrFiles))
UniteFunctionsRev::throwError("Update file don't found.");
$filename = UniteFunctionsRev::getVal($arrFiles, "name");
if(empty($filename))
UniteFunctionsRev::throwError("Update filename not found.");
$fileType = UniteFunctionsRev::getVal($arrFiles, "type");
</pre><p>然后获取了上传文件的临时路径和创建了目录 “/temp/update_extract” (目录创建失败会抛出异常并中止处理):<br></p><pre class="lang-php" data-lang="php"> $filepathTemp = UniteFunctionsRev::getVal($arrFiles, "tmp_name");
if(file_exists($filepathTemp) == false)
UniteFunctionsRev::throwError("Can't find the uploaded file.");
//crate temp folder
UniteFunctionsRev::checkCreateDir(self::$path_temp);
//create the update folder
$pathUpdate = self::$path_temp."update_extract/";
UniteFunctionsRev::checkCreateDir($pathUpdate);
//remove all files in the update folder
if(is_dir($pathUpdate)){
$arrNotDeleted = UniteFunctionsRev::deleteDir($pathUpdate,false);
if(!empty($arrNotDeleted)){
$strNotDeleted = print_r($arrNotDeleted,true);
UniteFunctionsRev::throwError("Could not delete those files from the update folder: $strNotDeleted");
}
}
</pre><p>如果 “/temp/update_extract” 创建成功,会清理该目录下的所有文件,然后将上传的文件移动至该目录下:<br></p><pre class="lang-php" data-lang="php"> //copy the zip file.
$filepathZip = $pathUpdate.$filename;
$success = move_uploaded_file($filepathTemp, $filepathZip);
if($success == false)
UniteFunctionsRev::throwError("Can't move the uploaded file here: {$filepathZip}.");
if(function_exists("unzip_file") == true){
WP_Filesystem();
$response = unzip_file($filepathZip, $pathUpdate);
}
</pre><p>这里很明显,没有对上传文件做限制,直接使用 move_uploaded_file() 将上传文件(任意)拷贝到了 “/temp/update_extract/” 目录下,后续的处理都不用再分析。<br></p>
暂无评论