利用 PHP-FPM 做内存马方法( 二 )


我们访问个普通的 phpinfo.php 文件,看看是否能够稳定的固化我们的内存马 。

利用 PHP-FPM 做内存马方法

文章插图
 
果然已经成功的把我们想要的payload植入了进去 。这里我们payload使用的是<?php @eval($_REQUEST[test]); ?>的 base64 。我们访问phpinfo.php?test=echo(aaaaa);看看效果,当然正常使用的时候我们可以更隐蔽 。
利用 PHP-FPM 做内存马方法

文章插图
 
当然,这个方案也有局限性,因为是内存马,所以他实际上是和PHP-FPM的 Worker 进程绑定的,因此,如果服务器上有多个Worker进程,我们就需要多发送刚才的请求几次,才能让我们的payload“感染”每一个进程 。
此外,我们还需要关注一个php-fpm.conf的配置:
pm.max_requests int
设置每个子进程重生之前服务的请求数 。对于可能存在内存泄漏的第三方模块来说是非常有用的 。如果设置为 '0' 则一直接受请求,等同于 PHP_FCGI_MAX_REQUESTS 环境变量 。默认值:0 。
这个配置定义了每一个 worker 进程最大处理多少请求,就会自动重生 。主要作用可能是避免内存泄露,但是一旦重生了,我们的内存马也就失效了 。庆幸的是,默认是不会重生的 。
检测既然是内存马,因此我们无法从代码扫描中发现 。并且由于他只是修改了内存中的 PHP 配置,我们也无法从PHP.ini/.user.ini/php-fpm.conf等文件内容中检测 。真正添加内存马由于只需要对fpm监听的端口发送请求,因此也无法从webserver的accesslog中发现问题 。
但是我们是可以通过rasp之类的工具,通过检查auto_prepend_file/auto_Append_file/allow_url_inclue配置的变化(虽然目前很多 rasp 也不会做这些操作)来做检测 。
另外,由于触发方式可以是任意一个 PHP 文件,所以,我们想从后续的访问行为中做检查也有一定难度,但是可以从网络流量中检查对应的后门 payload,或者从进程的行为中,来做检查 。
扩展关于 PHP-FPM 的内存马,暂时就说这么多 。那么这里还有一些疑问可以扩展:
1. mod_php模式下的内存马是否有可能实现?
2. 触发是否有除了auto_prepend_file/auto_append_file之外的方案?
3. 如何做到持久化,避免重生或者重启之后的?
我就不做一一展开了,有兴趣的朋友,可以延续着问题继续深入,欢迎讨论 。

【利用 PHP-FPM 做内存马方法】


推荐阅读