使用OSSEC构建主机层入侵检测

0xFFFF FFFF

reload一篇之前(2018年)写的文档,并更新了部分内容,记录下以前都写了些什么辣鸡。

0x00 前言

FW、WAF、NIDS、HIDS都是企业构建自己的安全防御体系的基础,整合的好就成了ATA(Advanced Threat Analytics高级威胁分析)。

这篇文章记录了前段时间在公司搞基础安全建过程中,基于ossec搞hids的一些记录和总结,供大家参考。

@ayazero有篇文章里面有一段大概是这样说的:你特么就只会玩玩ossec?对不起,这只是个数千规模量级的解决方案,无论是架构,还是检测深度乃至场景覆盖率都无法解决更大规模下的问题。

所以,这里的主要适用范围是在中小型互联网企业,尤其是安全人员较少,然后又不怎么重视安全(不愿意花钱)的那种,土豪公司可以直接忽略。

0x01 OSSEC相关介绍

OSSEC是一款开源的基于主机的入侵检测系统。它具备日志分析,文件完整性检查,策略监控,rootkit检测,实时报警以及联动响应等功能。它支持多种操作系统:Linux、Windows、MacOS、Solaris、HP-UX、AIX。

image

0x02 选择OSSEC的原因

主机安全监控之前已经开始在做,大佬走了我来接盘。要搞hids,首先想到的是ossec,同时也去调研了一下相关的开源产品。

开源产品 简介 项目地址
ossec 在众多互联网企业中广泛运用 https://www.ossec.net/
wazuh 基于ossec扩展出来的,结合了Elastic Stack https://wazuh.com/
osquery facebook开源的osquery,通过集成osquery来实现快速监控系统安全 https://osquery.io/
yulong-hids 同程安全团队开源的HIDS https://github.com/ysrc/yulong-hids
AgentSmith HIDS 点融安全团队开源的HIDS https://github.com/DianrongSecurity/AgentSmith-HIDS

考虑到ossec稳定性稳定性稳定性、案例资料也较多、容易上手,而且前期已经在边缘业务部署测试,所以继续选择ossec。yulong、AgentSmith也相当不错,但刚准备搞hids的时候它还没开源出来呐。

在正式动工之前,就想着有很多坑需要填,这里列举了一些,这是一个小白的绝望:

  • [x] 大规模的机器,如何初始化部署ossec的?

  • [x] 大规模的agent如何管理?如何管理、下发规则?

  • [x] 集群化的部署,如何统一管理?

  • [x] 海量日志怎样存储,怎样做数据分析?上来这么多报警,如何提取有效信息?如何闭环?

  • [x] 如何做一些关键的安全监控策略:基线扫描、webshell扫描、反弹shell监控等?

  • [x] 文件系统复杂、业务量大,性能瓶颈该如何解决?

0x03 HIDS架构构思

对于企业来说,主机数量多,机房遍布各地,业务环境不同,日志量较大较分散,如果只是简单的部署ossec估计也没多大意义。所以在初期就在思考借助这个检测框架,我们可以实现那些功能和检测能力。

HIDS核心功能:

image

HIDS数据处理流程:

image

ossec-agent :用于收集服务器信息、计划任务、监听端口、服务、系统日志、用户列表,实时监控文件操作行为、网络连接,系统安全配置核查(基线扫描)、webshell扫描、反弹shell监控等,初步筛选整理后传输到Server节点。

ossec-server:集群化部署,用于解析用户定义的规则,对从各Agent接收到的信息和行为进行分析检测和保存,对文件变化、异常登录、异常网络连接行为等进行分析并告警,从而实现对入侵行为实时预警。

Elasticsearch:日至存储、聚合、分析

Mysql:存储配置信息、cmdb资产信息、告警信息、监控组信息

Redis:任务队列、告警队列、消息推送队列

Web后台,搜集展示来至es的日志,提供给安全人员或运维人员;包括监控日志、告警消息查询,数据统计、监控组管理、主机管理、告警过滤、规则查看、配置下发等功能。

0x04 实践并优化

我们把HIDS数据流抽象为采集层、入侵检测层、存储层、分析决策层,架构解析如下:

image

同时也列出了我们需要解决的核心问题:

  • Agent部署步骤繁琐,大规模部署存在难点

  • Agent管理问题

  • 默认入侵检测能力有限

  • 告警多,入侵事件误判多

  • 事件处置流程欠佳

1.部署优化,提升覆盖率

image

优化前:

  • 默认只支持源码安装、安装步骤繁琐、编译安装还容易出错

  • agent与server端签名认证匹配过程繁琐

  • 需要人工介入部署,工作量特别大

优化后:

  • 我把源码包定制化修改之后,打成rpm包,yum源方式部署;支持centos6.,centos7.系列

  • 定制化编写部署脚本及部署流程,减轻了部署工作带来的压力

  • 多区域的主机,server多区域分布式部署,最终数据汇总到一处即可

需要注意:每一台ossec-server默认支持256个agent,最大支持2048个agent。要想支持2048个agent,需要在安装之前设置一下。

1
2
3
4
5
6
7
[root@ossec-server ~]# cd ossec-hids/src/
[root@ossec-server src]# make setmaxagents
Specify maximum number of agents: 2048
Maximum number of agents set to 2048.
[root@ossec-server src]# cd ..
[root@ossec-server ossec-hids]# ./install.sh
...

2.8版本的ossec,比较麻烦的是批量添加agent,因为其通信认证特别麻烦。需要想办法批量生产agent的key文件,然后交换给agent。当时我们借助了已有的ops平台,写了一些脚本,自动化的完成了以上的认证过程。

可以参考drops:OSSEC服务端配置客户端批量部署方案,然后根据自己情况调整。

较新版本(比如v3.2.0)完美解决了以上问题:

1
2
3
4
5
1、IPv6支持,满足未来业务IPv6需求
2、ossec-authd认证机制更加完善,安全系数提高,解决当前部署流程复杂易出错的问题
3、Configuration options更加完善,可以配置更灵活的监控项
4、更新检测规则/解码器
5、修复若干bug

添加agent可能有两种情况:

  • 已经线上运行的服务器(手动部署或批量部署)

运维人员到运维平台,选择指定机器执行部署模版命令即可完成部署,部署成功率>90%

  • 新上线的服务器

自动装机,执行系统初始化脚本时,针对平台业务路径的主机,自动部署安全监控agent,部署成功率>95%

2.主机及规则管理优化

image

优化前:

  • Agent仅有ip信息,这ip是属于什么业务、谁负责,告警出来应该找谁去处理
  • 怎样去查看agent状态?只能通过上server机器通过命令去查看
  • 怎样去管理他的入侵检测规则?不知道目前有哪些规在跑?

优化后:

  • 针对这样的问题,我们拉取了cmdb数据,同步CMDB关联业务信息,将这些分散的信息关联起来,成为一个完成的信息链条
  • 联动CMDB,安全agent监控覆盖到所有业务,滴水不漏
  • 在ossec server机器编写了相应的查询接口,自动化的去同步各个server下的agent信息
  • 编写一整套接口并结合active-response机制去更新agent端的规则(后期换成了其它方式,被动更新规则)

效果:

  • 监控组管理

image

  • 主机管理

image

  • 规则管理

image

3.丰富检测能力,提升安全事件感知效率

image

ossec默认拥有日志分析,文件完整性检查,rootkit检测,这些默认的规则,覆盖得比较多、比较泛,没有针对性;比如,我监控敏感文件变化,它检测出来的告警只会告诉你文件发生了变化,文件路径是什么什么;

对此我针对性的优化、把一些关键的文件、配置监控单独做成一条规则,

  • 比如说监控到定时任务变化了,单独告警说定时任务变化了、监控到iptables改变单独提示告警、监控到iptables关闭了,就会产生对应的告警。
  • 不同告警可以设置不同的level,以区别重要程度。

另一方面,改写了agent,加入一些自定义的检测脚本,用ossec检测框架去定时脚本执行,反馈结果到我的server端并进行分析。

  • 系统安全配置核查,比如说ssh配置,是否修改了默认的22端口,是否启用了ssh key认证,是否禁用了密码登录、redis是否未设置密码、php.ini文件是否配置合理等。

  • 另外一项就是针对webshell的监控

  • 反弹shell检查等

如下,是ossec目录结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/ossec/
├── active-response #主动响应脚本
├── agentless
├── bin #二进制文件,主程序logcollector、syscheck等
│ ├── agent-auth
│ ├── manage_agents
│ ├── ossec-agentd #agent守护进程
│ ├── ossec-control #agent操作入口
│ ├── ossec-execd #agent主动响应进程,用于执行server端预定的操作
│ ├── ossec-logcollector #agent日志搜集进程
│ ├── ossec-lua
│ ├── ossec-luac
│ ├── ossec-syscheckd #agent文件监控进程
│ └── util.sh
├── etc #配置文件
│ ├── client.keys #通信密钥
│ ├── ossec.conf
│ ├── ossec-init.conf
│ ├── ossec_monitor #配合ops的性能监控
│ └── shared
├── logs #日志文件
│ ├── active-responses.log
│ └── ossec.log
├── queue   #监控任务队列
│ ├── alerts
│ ├── diff
│ ├── ossec
│ ├── rids
│ └── syscheck
├── shell #自定义的安全检测脚本
│ ├── systemCheck.sh #系统基线扫描
│ ├── webshellScan.py #websehll扫描
│ ├── ReverseshellScan.py #反弹shell监控
│ ├──......
├── tmp
└── var

例如,自定义安全检查脚本‘systemCheck.sh’,用于检查系统安全基线配置情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
check_ssh(){

ssh_config_path='/etc/ssh/sshd_config'

result=`cat $ssh_config_path | grep '^PasswordAuthentication *yes'`

if [ -n "$result" ];then

echo 'Notice: ssh can login with password'

fi

result=`cat $ssh_config_path | grep '^Port *2222$'`

if [ ! -n "$result" ];then

echo 'Notice: ssh listen port not 2222'
fi

result=`cat $ssh_config_path | grep '^PermitEmptyPasswords *yes'`

if [ -n "$result" ];then

echo 'Notice: ssh allow login with empty password'
fi

}

check_system(){


result=`awk -F: '($3 == "0") { print $1 }' /etc/passwd | grep '[^root]' `

if [ -n "$result" ];then

echo 'Notice:Other root account:'$result

fi


result=`awk -F: '($2 == "") { print $1 }' /etc/shadow | grep [a-zA-Z]`

if [ -n "$result" ];then

echo 'Notice: account has empty passwd'$result

fi

}

check_ssh
check_system

ossec 配置文件中添加如下内容,每隔10小时进行一次扫描:

1
2
3
4
5
6
7
8
9
10
<localfile>
<log_format>command</log_format>
<command>/bin/bash /var/ossec/shell/systemCheck.sh</command>
<frequency>36000</frequency>
</localfile>
<localfile>
<log_format>command</log_format>
<command>python /var/ossec/shell/webshellScan.py</command>
<frequency>36000</frequency>
</localfile>

类似的,监控系统iptables变化、authorized_keys变化。

1
2
3
4
5
6
7
8
9
10
11
<localfile>
<log_format>command</log_format>
<command>iptables -L -n|md5sum|awk '{print $1}'</command>
</localfile>

<localfile>

<localfile>
<log_format>command</log_format>
<command>cat /root/.ssh/authorized_keys|md5sum|awk '{print $1}'</command>
</localfile>

这里特别说下针对webshell扫描的优化:

webshell的监控,这里我只是做了简单的文件静态特征检测,手段还有很多需要拔高的地方。

1
2
3
4
5
6
7
8
9
10
1.扫描性能优化

2.webshell规则库优化

@过程中参考了以下文章,具有一定的借鉴意义:

https://mp.weixin.qq.com/s/oZ7Jmo_rIblGYArHecn7lQ
https://mp.weixin.qq.com/s/3Zx2FTXXxpTiqe56b8hJQg
https://mp.weixin.qq.com/s/8PauKA6KU3TXp2FEmcoqeQ
https://mp.weixin.qq.com/s/yh_uX8jPfbn-_wzGOkugaA
  • 性能优化

最初,扫描性能这块没有经过严谨的测试,只是做了一些粗略的控制。当webshell检测脚本部署到一些web目录深度较大、文件数量较多、业务比较多的机器上的时候,性能出现了瓶颈,磁盘io一度飙高到90%以上且持续时间较长,没法完了,赶紧下线了webshell扫描的功能。影响到业务,锅非常大!

webshell检测主要靠遍历目录/文件的方式,正则批评特征函数进行检测,当时优化的思路是引入cgroup来控制,同时在代码中引入一些特征变量来做控制:

1
2
3
4
5
6
7
1.最大目录深度;(避免目录过深导致的内存消耗)max_directory_depth 

2.最大扫描文件大小;(避免大文件都会消耗过多的资源)max_file_size 

3.目录遍历时间间隔;(避免大文件都会消耗过多的IO资源)walkdir_time_span 

4.文件检查间隔;(避免CPU利用率会爬升到100%)regex_time_span

image

设置不同regex_time_span值,生成不同时间间隔下的系统资源损耗的实验结果,取200s中的平均值(实验数据):

image

实验后关键参数取值如下:

1
2
3
4
max_directory_depth = 10
max_file_size = 100000
walkdir_time_span = 0.005
regex_time_span = 0.05

优化前后webshell扫描性能(IO)对比:

image

  • webshell规则优化

webshell监控效果展示:

image

添加互联网收集的一些webshell规则特征(php、java):

image

收集了175个webshell文件和500个正常文件进行实验:

1
2
3
4
查杀率(优化前):111/175    63%
查杀率(优化后):147/175    84%
误检率(优化前):0/500      0%
误检率(优化后):2/500      0.4%
对比 查杀率 误检率
优化前 63% 0.0%
优化后 84% 0.4%

牺牲了误报率,提升了查杀率,可以接受的。

4.快速分析&流程闭环,提升事件处置效率

数据分析与展示:

image

前面解决了部署问题、一定程度上优化了入侵检测规则,获取到的检测数据如何进行分析,得到的入侵事件如何有效的反馈处置,只是一个值得思考的问题。

ossec自己也推出了一个免费的webui界面,对告警内容做展示,但是没有做任何的统计分析,不能满足我们对时机需求,我从两方面最改良了这个问题:

  • 自写hids web管理后台,入侵事件告警记录、处置情况记录、agent管理、监控组管理、规则管理等;
  • 结合elk做数据分析,快速的解决数据查询、统计的问题;
  • 结合其它安全基础设施日志进行关联分析。

image

image

告警闭环:

ossec跑了一段时间,筛选出了一份常规的监控告警项加入邮件告警,其它的事件只纪录不告警。

1
2
3
4
5
6
7
8
9
10
风险级别定义:
高:疑似入侵事件或不符合安全配置的检测项,高度关注;
中:非正常业务运维操作,可疑;
低:某些正常的操作,可提供给后续安全事件调查溯源。

将监控事件划分为(1-12)Level;Level越高,事件风险程度越高,Level>=7时,触发邮件告警。
1-6 Level:一般事件(低)
7-9 Level:可疑事件(中)
10-12 Level:高度关注事件(高)
注:目前采用单一事件告警,后期将关联多个事件计算风险权重后进行组合告警,将降低误报率。

我们直接把一些风险值较高、且较容易判断的监控告警项同步推送給业务机器负责人,让他们第一事件了解安全状况。
接收到告警信息后,运维人员可进行告警反馈(数据同步到安全中心),安全人员可根据反馈情况,进行应急处置及数据分析:

若告警事件为正常操作,可点击“忽略告警”按钮,

若该事件确实存在可疑,可点击“确认异常”按钮,事件升级。

  • iptables变化或关闭
  • crontab变化
  • 关键配置文件发生变化
  • 网卡模式发生变化
  • SSH登陆失败
  • SSH爆破
  • ……

通常,这几类告警,运维人员更加清楚是否异常,方便确认是否为安全问题,同时还可以协助做一些异常排查。

image

0x05 收益

image

todo

  • 数据积累,稳定运行
  • 组合告警,提升告警准确率
  • 入侵检测功能持续优化