
直接其原因
事的直接其原因很有原意,前两天我正上方笔记本电脑整天的这时候,忽然有位安全可靠沟通交流群的团友来找我沟通交流两个难题。

约莫的原意是,他在挖SRC的这时候,辨认出两处金融资产存有产品目录结点安全可靠漏洞,它透过那个安全可靠漏洞,找出最终目标金融资产采用了两个名叫phpmailer的开发工具(如果近似于开发工具吧),问我是不是配套措施借助,我查了呵呵那个模块的安全可靠漏洞重要信息。新一代的洞或许止到6.5.0版从前。

很意外,团友那个版是6.5.1,正好就无法借助了

找不出符合版的洞说实话,抱着自学的态度,我却是看了呵呵它的发展史安全可靠漏洞其其原因,Q1518A不晓得,看了后就教给许多有趣的新科学知识了,这也是为何会有这首诗的其原因。

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()的第五个参数。
① 网安自学成长路径思维导图② 60+网安经典常用工具包③ 100+SRC安全可靠漏洞预测报告④ 150+网安攻防实战技术电子书⑤ 最权威CISSP 认证考试指南+题库⑥ 超1800页CTF实战技巧手册⑦ 新一代网安大厂面试题合集(含答案)⑧ APP客户端安全可靠检测指南(安卓+IOS)
因此,我们再查看是不是别的地方采用了mailPassthru(),可以找出那个maillSend()方法中采用了mailPassthru()方法,并且第五个参数$params是来自于当前类中的Sender属性

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

这里可以看到,setFrom方法当中,就可以对Sender属性进行赋值
当然,那个安全可靠漏洞还有两个重点是对validateAddress()这一方法的绕过,这也是CVE-2016-10033的精彩部分。

但是它和本文的重点不符,所以我们就不深入预测这块。
既然晓得了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进行测试:

比如我在自己的服务器上运行如下代码,我们假设网站根产品目录是/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{<command><args>}{<string1>}{<string2>}}
//执行命令<command><args>,成功返回string1,失败返回string2
-be ${substr{<string1>}{<string2>}{<string3>}}
//字符串的截取,在string3中从string1开始截取string2个字符
-be ${readfile{<file name>}{<eol string>}}
//读文件file name,以eol string分割
-be ${readsocket{<name>}{<request>}{<timeout>}{<eolstring>}{ <fail string>}}
//发送socket消息,消息内容为request
没错,你可以辨认出,这玩意除了可以进行直接的命令执行(不需要写日志文件getshell了),虽然无法回显,但是弹个shell是简简单单。并且却是可以任意文件读取。并且最骚的是可以用substr来进行字符串截取,这样的话就支持我们进行很多绕过WAF的操作。
借助mail()来造两个简单的侧门
上文提到了各种mail()的骚操作,我在自学复现的过程中除了感到NB无话可说。它的种种特性不禁让我思考,它是否有成为侧门的潜质,它在正常的linux环境就可以实现日志getshell以及任意文件读取。在其它特定情况下它也可以无回显进行命令执行。并且它是两个再正常不过的函数,一般的开发和安全可靠人员可能都不会觉得这样两个人畜无害的邮件发送函数能造成什么危害。抱着这样的态度,我先简单的实现了这么两个功能:

其中$e的明文内容为:-f La2uR1te@1 -OQueueDirectory=/tmp/-X/root/mailshell.php
而$a/$b/$c/$d的内容均为phpshell。我们拿它到实际环境去试试看能无法成功实现我们刚刚演示的效果。如果运行成功,那么如果会在root产品目录下生成mailshell.php

如图,mailshell.php成功生成

其内容即为php一句话

所以我们继续改造呵呵那个侧门,让其变得更加可控。根据上面的总结我们可以晓得只要控制第五个参数就行,所以我们的改造也十分简单:

那个侧门最后能实现的效果包括但不限于:①linux环境下的任意文件写入(可getshell)②linux环境下的任意文件读取③特定环境(比如mail()底层采用exim4或软连接到exim4)下的无回显命令执行、代码执行
截至本文发表,那个结构极其简单的侧门依然具有不错的免杀能力:




后记
之所以说本文是炒冷饭,是因为安全可靠圈至少在2016年之前就已经晓得mail()函数造成的危害。而更多深入借助姿势在17年和18年都有师傅总结。对于我那个萌新来说,确实是大开眼界叹为观止,果然安全可靠漏洞的复现一定要及时搞,不然容易错过很多有原意的科学知识。