【漏洞分析】WordPress 4.6 远程代码执行漏洞分析
传送门
【漏洞预警】WordPress <4.7.1 远程代码执行漏洞(非插件无需认证,附Poc,演示视频)
0x00 漏洞概述
WordPress 4.6 版本远程代码执行漏洞是一个非常严重的漏洞,未经授权的攻击者利用该漏洞就能实现远程代码执行,针对目标服务器实现即时访问,最终导致目标应用服务器的完全陷落。无需插件或者非标准设置,就能利用该漏洞。Dawid Golunski (@dawid_golunski) 还在poc中为我们展示了精彩的替换 / 和 “ ”(表示空格)的技巧。
0x01 漏洞分析
整个过程利用了 WordPress 未对请求的 Host 字段进行校验和 PHPMailer 在 小于 5.2.20 版本存在的代码执行漏洞。对以上两个不安全点进行利用,导致远程代码执行。
POC地址为: WordPress-Exploit-4-6-RCE-CODE-EXEC-CVE-2016-10033
我们测试的命令为
/usr/bin/touch /tmp/manning.test
我们看下POC发出的请求
Host 字段构造如下
Host: target(any -froot@localhost -be ${run{${substr{0}{1}{$spool_directory}}usr${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}}manning.test}} null)
这点跟我们认知中的Host完全不一样。
接下来的流程非常简单。
在 wp-login.php 中,首先根据请求中的 action 进行路由
接着进入函数 retrieve_password
接着进入 wp_mail 函数,位于文件 pluggable.php
在 wp_mail 中,WordPress 会把 _SERVER['SERVER_NAME'] 变量拼接到 from_email 变量中。
经过一系列的邮件内容拼接,把类对象 phpmailer 的类变量都进行了赋值,之后进入调用了 Send 函数
这里把最关键的 mailSend 函数贴出来,mailSend 函数负责最终调用,关键在 mailPassthru 函数,该函数会把带有恶意的 params 变量交给 PHPMailer。
protected function mailSend($header, $body){ $toArr = array(); foreach ($this->to as $toaddr) { $toArr[] = $this->addrFormat($toaddr); } $to = implode(', ', $toArr); if (empty($this->Sender)) { $params = ' '; } else { $params = sprintf('-f%s', $this->Sender); } if ($this->Sender != '' and !ini_get('safe_mode')) { $old_from = ini_get('sendmail_from'); ini_set('sendmail_from', $this->Sender); } $result = false; if ($this->SingleTo && count($toArr) > 1) { foreach ($toArr as $toAddr) { $result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params); $this->doCallback($result, array($toAddr), $this->cc, $this->bcc, $this->Subject, $body, $this->From); } } else { $result = $this->mailPassthru($to, $this->Subject, $body, $header, $params); $this->doCallback($result, $this->to, $this->cc, $this->bcc, $this->Subject, $body, $this->From); } if (isset($old_from)) { ini_set('sendmail_from', $old_from); } if (!$result) { throw new phpmailerException($this->lang('instantiate'), self::STOP_CRITICAL); } return true;}
动态调试,在 mailPassthru 调用时,整个变量如图所示。
最终在 mailPassthru 内调用了 @mail。
最终我们在 tmp 目录看到了 manning.test 文件
0x02 补丁分析
WordPress 4.7.1 版本
1,升级phpmailer的版本到5.2.22
2,在 mailSend 修改,对变量 params 进行了过滤。
protected function mailSend($header, $body){ $toArr = array(); foreach ($this->to as $toaddr) { $toArr[] = $this->addrFormat($toaddr); } $to = implode(', ', $toArr); $params = null; //This sets the SMTP envelope sender which gets turned into a return-path header by the receiver if (!empty($this->Sender) and $this->validateAddress($this->Sender)) { // CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped. if (self::isShellSafe($this->Sender)) { $params = sprintf('-f%s', $this->Sender); } } if (!empty($this->Sender) and !ini_get('safe_mode') and $this->validateAddress($this->Sender)) { $old_from = ini_get('sendmail_from'); ini_set('sendmail_from', $this->Sender); } $result = false; if ($this->SingleTo and count($toArr) > 1) { foreach ($toArr as $toAddr) { $result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params); $this->doCallback($result, array($toAddr), $this->cc, $this->bcc, $this->Subject, $body, $this->From); } } else { $result = $this->mailPassthru($to, $this->Subject, $body, $header, $params); $this->doCallback($result, $this->to, $this->cc, $this->bcc, $this->Subject, $body, $this->From); } if (isset($old_from)) { ini_set('sendmail_from', $old_from); } if (!$result) { throw new phpmailerException($this->lang('instantiate'), self::STOP_CRITICAL); } return true;}
0x03 防护建议
升级 WordPress 至最新版本。
0x04 调试总结
调试过程中需要注意:
sendmail 需要装 exim4扩展
需要更改poc中的账户,poc中填写的是admin
poc运行环境需要有python环境
本次调试环境是:
Server version: Apache/2.4.18 (Ubuntu)
PHP 7.0.15-0ubuntu0.16.04.4 (cli) ( NTS )
sendmail 和 exim4扩展
其他注意事项可以参考 @Tomato菜的要死 和 @廖新喜1 的微博。
0x05 参考文章
https://exploitbox.io/vuln/WordPress-Exploit-4-6-RCE-CODE-EXEC-CVE-2016-10033.html
传送门
【漏洞预警】WordPress <4.7.1 远程代码执行漏洞(非插件无需认证,附Poc,演示视频)