CVE-2017-5223-PHPMailer任意文件读取漏洞复现
2022/2/6 20:22:46
本文主要是介绍CVE-2017-5223-PHPMailer任意文件读取漏洞复现,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
CVE-2017-5223-PHPMailer任意文件读取漏洞复现
影响版本: PHPMailer <= 5.2.21
漏洞原理
文件读取的函数主要是 encodeFile函数。(贴关键代码)
protected function encodeFile($path, $encoding = 'base64') { ...... $file_buffer = file_get_contents($path); $file_buffer = $this->encodeString($file_buffer, $encoding); ....... return $file_buffer; } catch (Exception $exc) { $this->setError($exc->getMessage()); return ''; } }
该函数中接收了一个$path变量,最后该$path变量的值带入到了file_get_contents函数中执行。如果该$path变量可控即可任意文件读取.
$path
参数回溯
在attachAll函数中:
// Add all attachments foreach ($this->attachment as $attachment) { // Check if it is a valid disposition_filter if ($attachment[6] == $disposition_type) { // Check for string attachment $string = ''; $path = ''; $bString = $attachment[5]; if ($bString) { $string = $attachment[0]; } else { $path = $attachment[0]; }
可以看到$path的赋值过程,只要是$this->attachment数组中每一个attachment的第六个元素为False,就将$attachment[0] 赋值给 $path.
跟进attachment数组
public function addAttachment($path, $name = '', $encoding = 'base64', $type = '', $disposition = 'attachment') { ... $this->attachment[] = array( 0 => $path, 1 => $filename, 2 => $name, 3 => $encoding, 4 => $type, 5 => false, // isStringAttachment 6 => $disposition, 7 => 0 ); public function addStringAttachment( $string, $filename, $encoding = 'base64', $type = '', $disposition = 'attachment' ) { // If a MIME type is not specified, try to work it out from the file name if ($type == '') { $type = self::filenameToType($filename); } // Append to $attachment array $this->attachment[] = array( 0 => $string, 1 => $filename, 2 => basename($filename), 3 => $encoding, 4 => $type, 5 => true, // isStringAttachment 6 => $disposition, 7 => 0 ); } public function addEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = '', $disposition = 'inline') { if (!@is_file($path)) { $this->setError($this->lang('file_access') . $path); return false; } // If a MIME type is not specified, try to work it out from the file name if ($type == '') { $type = self::filenameToType($path); } $filename = basename($path); if ($name == '') { $name = $filename; } // Append to $attachment array $this->attachment[] = array( 0 => $path, 1 => $filename, 2 => $name, 3 => $encoding, 4 => $type, 5 => false, // isStringAttachment 6 => $disposition, 7 => $cid ); return true; } public function addStringEmbeddedImage(...){ $this->attachment[] = array( 0 => $string, 1 => $name, 2 => $name, 3 => $encoding, 4 => $type, 5 => true, // isStringAttachment 6 => $disposition, 7 => $cid ); }
只有addAttachment()函数和addEmbeddedImage() 函数可以,其他两个函数$attachment[5] 为true.
主要看AddEmbeddedImage函数,该函数是处理邮件内容中的图片的,回溯该函数发现msgHTML函数调用了该函数,msgHTML 函数是用来发送html格式的邮件。
public function msgHTML($message, $basedir = '', $advanced = false) { preg_match_all('/(src|background)=["\'](.*)["\']/Ui', $message, $images); if (array_key_exists(2, $images)) { foreach ($images[2] as $imgindex => $url) { // Convert data URIs into embedded images if (preg_match('#^data:(image[^;,]*)(;base64)?,#', $url, $match)) { $data = substr($url, strpos($url, ',')); if ($match[2]) { $data = base64_decode($data); } else { $data = rawurldecode($data); } $cid = md5($url) . '@phpmailer.0'; // RFC2392 S 2 if ($this->addStringEmbeddedImage($data, $cid, 'embed' . $imgindex, 'base64', $match[1])) { $message = str_replace( $images[0][$imgindex], $images[1][$imgindex] . '="cid:' . $cid . '"', $message ); } } elseif (substr($url, 0, 4) !== 'cid:' && !preg_match('#^[a-z][a-z0-9+.-]*://#i', $url)) { // Do not change urls for absolute images (thanks to corvuscorax) // Do not change urls that are already inline images $filename = basename($url); $directory = dirname($url); if ($directory == '.') { $directory = ''; } $cid = md5($url) . '@phpmailer.0'; // RFC2392 S 2 if (strlen($basedir) > 1 && substr($basedir, -1) != '/') { $basedir .= '/'; } if (strlen($directory) > 1 && substr($directory, -1) != '/') { $directory .= '/'; } if ($this->addEmbeddedImage( $basedir . $directory . $filename, $cid, $filename, 'base64', self::_mime_types((string)self::mb_pathinfo($filename, PATHINFO_EXTENSION)) )
$url是通过解析$message里src=”xxxxx”而来的,$url最终被解析出来就是xxxxx,而$message就是我们发送邮件的自定义的内容。这样可控点就找到了,即可成功利用该漏洞了
查找所有触发encodeFile 函数的触发链。
我们直接查看一下encodeFile的所有引用,只有class.phpmailer.php中的attachAll函数有调用。
发现也只有同文件的createBody()函数调用了,而且是多次调用。
继续往上回溯,我们发现调用链为;
send()->preSend()->createBody->attachAll()->encodeFile()
我们找到一处触发链,找到两个函数可以添加我们的可控变量$path参数。
复现
使用vulhub环境即可,具体操作详见
https://vulhub.org/#/environments/phpmailer/CVE-2017-5223/
“意见反馈”页面,正常用户填写昵称、邮箱、意见提交,这些信息将被后端储存,同时后端会发送一封邮件提示用户意见填写完成:
该场景在实战中很常见,比如用户注册网站成功后,通常会收到一封包含自己昵称的通知邮件,那么,我们在昵称中插入恶意代码`<img src="/etc/passwd">`,目标服务器上的文件将以附件的形式被读取出来。
总结
代码审计步骤仍然是找到危险函数,然后变量回溯,寻找可控变量,利用漏洞。
参考
https://github.com/jiangsir404/PHP-code-audit/blob/master/PHPmailer/PHPmailer 任意文件读取漏洞.md
https://vulhub.org/#/environments/phpmailer/CVE-2017-5223/
这篇关于CVE-2017-5223-PHPMailer任意文件读取漏洞复现的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-19php8的协程和hyperf的协程有什么区别?-icode9专业技术文章分享
- 2024-12-19php8 的fiber是什么?-icode9专业技术文章分享
- 2024-12-05怎么在php8,1 里面开启 debug?-icode9专业技术文章分享
- 2024-12-05怎么在php8,1 里面开启 debug?-icode9专业技术文章分享
- 2024-11-29使用PHP 将ETH账户的资产汇集到一个账户
- 2024-11-23怎么实现安卓+php 热更新方案?-icode9专业技术文章分享
- 2024-11-22PHP 中怎么实现判断多个值是否为空、null 或者为 false?-icode9专业技术文章分享
- 2024-11-11开源 PHP 商城项目 CRMEB 二次开发和部署教程
- 2024-11-09怎么使用php在kaufland平台刊登商品?-icode9专业技术文章分享
- 2024-11-05PHP的抽象类和接口是什么,有什么区别-icode9专业技术文章分享