通用的基于 bpftrace 的 RCE/webshell 预防技术,适用于关键的 Linux 网络服务。如果出于某种原因您无法持续运行它,它也可以用作系统范围的临时“虚拟修补”方法。
bpftrace 是一种基于 eBPF 的 Linux 高级跟踪语言和运行时。它支持内核和用户空间的静态和动态跟踪。
该 bpftrace 脚本专注于在进程调用 execve()(用于执行新程序的系统调用)时根据进程的父进程名称来监视和终止某些进程。
我已经针对不同类型的 webshell(weevly、p0wny-shell、popen)、httpd CVE-2021-41773、MySQL UDF 命令执行、httpd/nginx 后门、不同的漏洞 webapps(PHP/Java)、Kafka、Zimbra、Solr 等进行了测试。看看吧,这只是几行代码,而魔法就在 bpftrace 背后完成的:
#!/usr/bin/env bpftrace
tracepoint:syscalls:sys_enter_execve
{
@ parent = comm;
}
tracepoint:syscalls:sys_exit_execve
/ @ parent == "httpd" || @ parent == "php-fpm" || @ parent == "mysqld" || @ parent == "java" || @ parent == "postjournal" /
{
printf("Killing execve() process spawned from %s: PID %dn", @ parent, pid);
signal(9);
}
要点链接在这里 https://gist.github.com/cr0nx/e972aac974e1b5c7703ff6de39c07ca8
简短描述:
-
tracepoint:syscalls:sys_enter_execve块:每当进程调用 execve() 系统调用时就会触发此部分,用于执行新程序。
-
tracepoint:syscalls:sys_enter_execve:此跟踪点挂接到内核以跟踪 execve() 系统调用何时被调用。
-
@parent = comm ;:这将调用 execve() 的进程名称保存到变量@parent中。comm 是 bpftrace 中一个特殊的内置变量,用于保存当前进程的名称(即调用 execve() 的父进程)
-
tracepoint:syscalls:sys_exit_execve块:此部分在 execve() 调用完成并发送终止信号 (SIGKILL) 后检查特定的父进程
-
tracepoint:syscalls:sys_exit_execve:当 execve() 系统调用完成时,此跟踪点触发。
-
/ @ parent == ... /:此条件检查调用 execve() 的进程是否具有以下名称之一:httpd、php-fpm、mysqld、java 或 postjournal。这些是 Web 服务器、PHP 引擎、数据库系统、Java 服务等的常见进程名称。
-
signal(9):向由 execve() 调用产生的进程发送 SIGKILL(信号编号 9),立即终止它。
一些截图:
长话短说,该脚本旨在监控特定高权限或敏感进程(例如 httpd(Apache)、php-fpm(PHP FastCGI 进程管理器)、mysqld(MySQL 服务器)、java 或 postjournal)发出的任何 execve() 调用。如果这些进程尝试使用 execve() 生成新进程,则该脚本会立即终止新进程。如果出于 某种原因您无法持续运行它,它也可以用作系统范围的临时“虚拟修补”方法。它绝对可以在所有不同类型的 CTF 比赛中发挥作用。
这是正在进行的 POC/研究一些额外的想法:
-
添加对 authorized_keys、id.rsa 以及与 $HOME/.ssh 相关的所有内容的访问阻止
-
添加对从目标到本地网络地址的传出连接的横向移动阻止功能
-----
原文始发于微信公众号(Ots安全):针对关键 Linux 网络服务的通用基于 bpftrace 的 RCE/webshell 预防技术
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论