<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 =...
<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>