0x01 概述


企业安全建设中非常重要的一项工作就是入侵感知体系建设,不同于网络层的安全防护检测如WAF、IPS、IDS等,入侵感知体系更偏向于被入侵后的异常行为发现,即你的机器已经被黑掉的,你能否第一时间发现并且定位到哪里出了问题。Web中间件的系统命令调用监控是我认为入侵感知中性价比较高的一项监控措施,当然你也可以算作HIDS的一项功能。

举个例子,记得S2-045爆出来的时候,公司的不少站点都受到了影响,即便当时安全、运维和开发的响应速度够快,排查受影响的项目替换Jar包,但是还是有部分机器受到了影响,通过这项监控我可以清楚的定位到哪些机器已经被黑了,攻击者执行了什么,心里有底,不至于盲目的去查找。

我目前在用的是通过Linux系统自带的Auditd服务来监控的系统的EXECVE调用,联动OSSEC报警。另外使用开源工具Snoopy可以,我们之前也提到过Bash命令审计,也见到过有的公司运维就是直接用的Snoopy来做的审计,不过我看了下老外的评论有说到可能会影响到系统的稳定性,暂时没有在生产环境测试。

下面我们就详细说一下Auditd和Snoopy这两项监控方式。

 

0x02 Auditd


auditd服务是Linux自带的审计系统,用来记录审计信息,从安全的角度可以用于对系统安全事件的监控。

auditd服务的配置文件位于/etc/audit/audit.rules,其中每个规则和观察器必须单独在一行中。语法如下:

-a <list>,<action> <options>

<list>配置如下:

task

每个任务的列表。只有当创建任务时才使用。只有在创建时就已知的字段(比如UID)才可以用在这个列表中。

entry

系统调用条目列表。当进入系统调用确定是否应创建审计时使用。

exit

系统调用退出列表。当退出系统调用以确定是否应创建审计时使用。

user

用户消息过滤器列表。内核在将用户空间事件传递给审计守护进程之前使用这个列表过滤用户空间事件。有效的字段只有uid、auid、gid和pid。

exclude

事件类型排除过滤器列表。用于过滤管理员不想看到的事件。用msgtype字段指定您不想记录到日志中的消息。

<action>配置如下:

never

不生成审计记录。

always

分配审计上下文,总是把它填充在系统调用条目中,总是在系统调用退出时写一个审计记录。如果程序使用了这个系统调用,则开始一个审计记录。

<options>配置如下:

-S <syscall>

根据名称或数字指定一个系统。要指定所有系统调用,可使用all作为系统调用名称。

-F <name[=,!=,<,>,<=]value>

指定一个规则字段。如果为一个规则指定了多个字段,则只有所有字段都为真才能启动一个审计记录。每个规则都必须用-F启动,最多可以指定64个规则。

常用的字段如下:

pid

进程ID。

ppid

父进程的进程ID。

uid

用户ID。

gid

组ID。

msgtype

消息类型号。只应用在排除过滤器列表上。

arch

系统调用的处理器体系结构。指定精确的体系结构,比如i686(可以通过uname -m命令检索)或者指定b32来使用32位系统调用表,或指定b64来使用64位系统调用表。

...

下面我们编写测试Java命令监控规则

Jboss的启动账户为nobody,添加审计规则

# grep '\-a' /etc/audit/audit.rules

-a exclude,always -F msgtype=CONFIG_CHANGE

-a exit,always -F arch=b32 -F uid=99 -S execve -k webshell

重启服务

# service auditd restart

Stopping auditd:                                           [  OK  ]

Starting auditd:                                           [  OK  ]

使用菜刀马测试:

菜刀马传递的参数为

tom=M&z0=GB2312&z1=-c/bin/sh&z2=cd /;whoami;echo [S];pwd;echo [E]

所执行的程序如下:

else if(Z.equals("M")){String[] c={z1.substring(2),z1.substring(0,2),z2};Process p=Runtime.getRuntime().exec(c);

审计日志如下:

type=EXECVE msg=audit(1500273887.809:7496): argc=3 a0="/bin/sh" a1="-c" a2=6364202F7765622F7072.....

然后对照着日志时间戳去找对应的Nginx Access Log中的请求