从一次有趣的漏洞分析到一个有趣的PHP后门

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

起因

事情的起因很有趣前几天我正对着电脑发呆的时候突然有个安全交流群的群友来找我交流一个问题

大概的意思就是他在挖SRC的时候发现一处资产存在目录遍历漏洞它通过这个漏洞找到目标资产使用了一个名为phpmailer的中间件应该类似于中间件吧问我有没有办法利用我查了一下这个组件的漏洞信息。最新的洞似乎截止到6.5.0版本以前

很不幸群友这个版本是6.5.1刚好就不能利用了

找不到符合版本的洞没关系抱着学习的心态我还是看了一下它的历史漏洞成因不看不知道看了之后就学到一些好玩的新知识了这也就是为什么会有这篇文章的原因。

CVE-2016-10033的简单分析

CVE-2016-10033是Phpmailer出现过的最经典的的漏洞在本文正式开始之前我们先来简单分析一下这个漏洞。读者可以到

https://github.com/opsxcq/exploit-CVE-2016-10033/blob/master/src/class.phpmailer.php

看到phpmailer的代码。这里先开门见山地说漏洞的成因其实就在mail()函数的第五个参数只要控制了第五个参数我们就能进行RCE、文件读取等操作。因此我们先追溯mail()函数

因此我们可以先定位到mailPassthru()这一方法可以看到这个方法内部就使用了mail()maill的第五个参数也就是mailPassthru()的第五个参数。

【----帮助网安学习以下所有学习资料免费领加@v~yj009991备注“ csdn ”获取】
① 网安学习成长路径思维导图
② 60+网安经典常用工具包
③ 100+SRC漏洞分析报告
④ 150+网安攻防实战技术电子书
⑤ 最权威CISSP 认证考试指南+题库
⑥ 超1800页CTF实战技巧手册
⑦ 最新网安大厂面试题合集含答案
⑧ APP客户端安全检测指南安卓+IOS

因此我们再查看有没有别的地方使用了mailPassthru()可以找到这个maillSend()方法中使用了mailPassthru()方法并且第五个参数$params是来自于当前类中的Sender属性

那我们回溯Sender属性看看有什么地方可以控制Sender属性。

这里可以看到setFrom方法当中就可以对Sender属性进行赋值

当然这个漏洞还有一个重点就是对validateAddress()这一方法的绕过这也是CVE-2016-10033的精彩部分。

但是它和本文的重点不符所以我们就不深入分析这块感兴趣的读者可以拓展阅读

https://paper.seebug.org/161/

既然知道了Sender这个关键属性是怎么赋值的接下来我们继续分析mailSend()方法的调用链可以找到postSend()方法

继续看postSend()最终可以找到send()方法

自此整个漏洞的传参流程我们就已经分析完了。大体上来说只要我们用setFrom()方法对Sender属性赋值再调用send()方法。那么Sender属性的值就会进入到mail()函数的第五个参数中从而实现RCE。看到这想必很多读者已经对开篇提到的这个mail()函数的第五个参数提起兴趣了为什么控制了它就能实现RCE呢这就要提到php
中 mail()函数的实现原理了。

有趣的mail()

mail()函数是php定义的用来发送邮件的函数其支持的参数如下


为什么一个发送邮件的函数能造成RCE前人的安研经验已经告诉了我们答案。Php的mail()函数其底层其实是调用了linux下的sendmail命令。由于sendmail支持一些有趣的参数这就会造成更大的危害。

①日志写入导致的RCE

接着上面提到的内容来说我们首先要介绍的是sendmaill的X和O参数其效果分别为

-X logfile 指定一个文件来记录邮件发送的详细日志

-O option=value 临时设置一个邮件储存的临时位置。

看到这大部分读者应该马上能反应过来我们能指定文件来储存邮件发送的日志那不就可以写日志getshell了吗事实也的确如此。了解这个信息之后我们再回过头看mail()函数支持的第五个参数

没错我们可以用这个第五个参数来控制sendmail的额外参数那我们控制X的参数值不就拿下了我们可以使用如下demo进行测试

<?php

$to = 'La2uR1te@b.c';

$subject = '<?php system("whoami"); ?>'; //你想执行的任意php代码

$message = '<?php system("ls ./"); ?>';//同上

$headers = '';

$addtionparam = '-f La2uR1te@1 -OQueueDirectory=/tmp/
-X/var/www/html/1.php';

//假设我们已知目标站点绝对路径

mail($to, $subject, $message, $headers, $param);

?>

比如我在自己的服务器上运行如下代码我们假设网站根目录是/root/我们运行一下上述代码看看会发生什么。在复现的时候确保你已经安装过sendmail不然没用。

运行完之后我们在root目录下确实发现了一个名为testmail.php的文件。

我们看看它的内容是什么

其实他的内容很多就是日志文件。但是看箭头指的地方毫无疑问我们的代码已经被成功写入了。这时候如果我们再用php来执行这个testmail.php注意看前后的区别

当前用户就是root当前目录下只有testmail.php和test.php毫无疑问我们的恶意代码已经被成功执行了。

综上如果我们知道目标网站的绝对路径、目标网站是linux环境并且php底层使用sendmail进行发送邮件默认那么就可以使用mail()函数来执行写入日志文件的GETSHELL。

②读取配置文件导致的任意文件读取

这个函数好玩的地方不止于此它还可以用于任意文件读取。我们修改一下上面的demo

注意看这里我们使用了-C参数后面跟着我们想读取的文件。这样就能直接实现任意文件读取了

如下图直接读文件一把梭

③进阶技巧之利用配置文件执行代码

设想这么一个变态的情况整个网站假设我们只有一个可供文件写入的点并且还有很严格的过滤。这个时候有没有能够用mail()来操作的可能呢再说回sendmail命令的特性默认会使用sendmail-mta来解析待发送的邮件内容我们其实有办法覆盖sendmail的解析配置让它用php来解析我们要发送的邮件内容从而直接完成命令执行。

我们首先到/etc/mail/sendmail.cg复制其内容。然后在其内容结尾加上如下配置

Mlocal, P=/usr/bin/php, F=lsDFMAw5:/|@qPn9S, S=EnvFromL/HdrFromL,

R=EnvToL/HdrToL,

T=DNS/RFC822/X-Unix,

A=php – $u $h ${client_addr}

把这个新文件命名为sendmail_cf

接着我们执行如下命令因为这玩意不能回显所以我们还是让它新创建几个文件

各位师傅恭喜发财新年快乐哈

执行上面的代码之后。可以看到tmp目录下多出一个xnklgxfc提前祝师傅们新年快乐恭喜发财哈

④进阶技巧之Exim4情况下mail()函数操作

这里因为环境没配置好所以没有演示成功我就借助别的师傅的结果了

mail()函数的底层虽然是sendmail命令但有时它也有可能是exim4命令。比方说在ubuntu/debain中sendmail实际上软连接到了exim4。也就是说我们有新姿势了exim4的各种参数和能打出的操作都是不同的

这里我们介绍一个-be参数这个参数事exim4中的运行扩展模式参数这个参数支持我们打出大量操作例如

-be ${run{ }{}{}}

//执行命令 成功返回string1失败返回string2

-be ${substr{}{}{}}

//字符串的截取在string3中从string1开始截取string2个字符

-be ${readfile{}{}}

//读文件file name以eol string分割

-be ${readsocket{}{}{}{}{}}

//发送socket消息消息内容为request

没错你可以发现这玩意除了可以进行直接的命令执行不需要写日志文件getshell了虽然不能回显但是弹个shell就是简简单单。并且还是可以任意文件读取。并且最骚的是可以用substr来进行字符串截取这样的话就支持我们进行很多绕过WAF的操作。

利用mail()来造一个简单的后门

上文提到了各种mail()的骚操作我在学习复现的过程中除了感到NB无话可说。它的种种特性不禁让我思考它是否有成为后门的潜质它在正常的linux环境就可以实现日志getshell以及任意文件读取。在其它特定情况下它也可以无回显进行命令执行。并且它是一个再正常不过的函数一般的开发和安全人员可能都不会觉得这样一个人畜无害的邮件发送函数能造成什么危害。抱着这样的心态我先简单的实现了这么一个功能

其中$e的明文内容为-f La2uR1te@1 -OQueueDirectory=/tmp/
-X/root/mailshell.php

a / a/ a/b/ c / c/ c/d的内容均为phpshell。我们拿它到实际环境去试试看能不能成功实现我们刚刚演示的效果。如果运行成功那么应该会在root目录下生成mailshell.php

如图mailshell.php成功生成

其内容即为php一句话

所以我们继续改造一下这个后门让其变得更加可控。根据上面的总结我们可以知道只要控制第五个参数就行所以我们的改造也十分简单

这个后门最后能实现的效果包括但不限于①linux环境下的任意文件写入可getshell②linux环境下的任意文件读取
③特定环境比如mail()底层使用exim4或软连接到exim4下的无回显命令执行、代码执行

截至本文发表这个结构极其简单的后门依然具有不错的免杀能力

1674118324840

后记

之所以说本文是炒冷饭是因为安全圈至少在2016年之前就已经知道mail()函数造成的危害。而更多深入利用姿势在17年和18年都有师傅总结绿盟的师傅以及安恒的师傅。对于我这个萌新来说确实是大开眼界叹为观止果然漏洞的复现一定要及时搞不然容易错过很多有趣的知识。

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: php

“从一次有趣的漏洞分析到一个有趣的PHP后门” 的相关文章