安全事件自动化响应框架设计

百家 作者:顺丰安全应急响应中心 2021-06-29 21:16:26

前言

       在日常网络安全运营中,调查服务器主机是否被入侵是绕不开的工作。常见的调查动作就是在主机上执行脚本,批量执行命令将基础数据拉取出来,并做一些简单的规则判断,以便快速确认主机是否已被入侵成功。

       在实际工作中,被调查主机通常是生产正在运行的服务器,在调查过程中就会发现存在以下几个问题:

  1. 安全运营人员具有主机的权限不高,无法获取全面的基础信息,往往需要主机运维人员介入;

  2. 检测规则不能太复杂否则可能会因为性能问题影响正常业务;

  3. 固定的检测脚本很难应对不同的调查场景,遇到存疑入侵点而脚本又不能覆盖的,需要反复在主机执行命令;

  4. 受限于生产环境是最小化部署,意味着平常用的趁手的非内置模块无法加载,限制脚本能力;

  5. 缺乏统一平台对采集的基础数据进行二次处理、归档、展示,影响调查效率及证据收集;

     上述这些问题直接影响安全事件调查和响应的效率,影响平均检测时间(MTTD)、平均响应时间(MTTR)指标,尤其在是在重保期间,需要调查事件太多,留给每个事件调查的时间就不多了。

       为了应对在上述不足,应该构建一套应急响应系统框架,这个框架纳入整个安全技术检测体系中,是安全运营建设中一部分,具备自动化检测、友好展示、方便回溯、快速查看、灵活定制等特点。

        为此需要设计一套技术框架,通过更优雅的方式来实现应急响应能力。

框架设计

       在应急响应系统设计,有几个关键步骤:

  1. 数据采集:需要脚本在被调查主机上执行脚本,获取系统状态快照;

  2. 脚本执行:脚本能够推送到目标,完成执行动作,并将执行结果返回到统一服务器;

  3. 数据解析:后台服务器接收返回的数据,这些数据只是字符串,还需要对字符串解析成结构化数据,才能进行存储和分析;

  4. 数据分析与归档:对获取到数据,以友好的方式展示,并能够进行字段关联,实现分析能力;能够对结果统一归档保存;

       每个步骤都应该要有相应的模块做能力支撑,最终实现统一平台。因此可以有如下的框架图:

脚本设计

       在被调查主机上执行脚本是整个调查分析关键的第一步,所以在脚本需求上,需要仔细斟酌。

       考虑到应急响应场景,更多的是在确认主机是否沦陷,这是一个人工排查过程,需要主机上操作系统和应用服务的基础数据供分析人员判断和决策,好比“专家模式”肯定会比“简单模式”显示更多的信息,所以脚本采集的最终数据应该以基础数据为主。

       其次,考虑到应急响应千差万别,可以不同的响应处理类型需要不同类型的数据,这就要求脚本是能够灵活定义的,能够适应不同的情况,也可以尽可能降低脚本开发和维护难度;

       最后,被调查的主机通常的是生产的主机,是在生产环境中执行命令,要保证采集内容是可靠的、安全的。这就要求在采集执行动作是系统能够执行的,例如采集命令是标准模块,保证最小化部署的主机也具备相应的执行能力,其次,执行命令多多少少都会对系统产生一定影响,就要求所有执行都应该简单高效,降低对主机性能的影响。

       综上,脚本设计应该考虑:

  1. 能够采集原始基础数据,最少应该包括进程、网络、文件、账号等基础信息;

  2. 脚本代码和采集规则分离,以规则文件形式定义采集内容,并对常见的采集方式规则化处理;

  3. 主机执行的脚本仅做数据采集,不在逻辑检测。

代码与规则分离

       目前所看到大部分的应急响应工具都是强耦合,一条命令对应一条检测规则,检测多条规则需要执行多条命令,脚本代码不能重用,随着累计应急响应不同场景的增加,只能不断累加代码,最终导致代码臃肿,后期维护难度巨大;

       采用代码与规则分离后,采集内容和采集执行命令分开,将每个采集的具体动作“原子化”,这样就可以在约定规则内重用代码,应对不同响应场景,只需要调整采集规则即可。更为重要的是,规则化的脚本,还可以针对不同的SOP场景执行不同的采集数据要求,可以更好的贴近自动化处置理念,相比之前的一坨坨代码和检测逻辑混合的脚本,以规则方式定义能够更直观查看数据采集方式、采集方式;

       要做到代码和规则,需要做以下几步:

  1. 定义采集方式:使用什么方式获取数据,以及执行的具体内容

  2. 定义输出方式:在前者采集完成后,是否需要下一步的再处理,例如获取到的文件列表,是否要继续获取文件内容;

  3. 定义解析方式:解析方式与采集方式或格式输出有关,具体的解析方式需要在后端单独实现

       例如,可以设计这样一个采集规则:

 1- id: C0031
2  name: 获取执行文件状态/usr/bin
3  description: 获取执行文件状态/usr/bin
4  category: sysenv
5  source:
6    action:
7      method: stdout
8      from: "find /usr/bin/* | xargs stat"
9  parser:
10    method: command_stat

       这条规则是yaml格式,关键的内容在sourceparser两个字段内,source定义了采集数据的方式,action表示这条规则采集的动作,比如例子中的stdout表示的是执行命令,具体是什么命令是由后面的from字段来定义的,例子中的find /usr/bin/* | xargs stat表示执行shell命令获取/usr/bin/*目录下所有文件的状态。parser定义的是对采集的数据解析的处理方法,这个方法是在服务端定义并执行的,不同数据采集方式需要不同的解析方法来对应,解析方法目的就是把字符串内容解析成结构化的数据,以便能够完成检索、存储功能。

     为了便于后续的维护和分析处理,还设计了namedescriptioncategory几个字段,可以一目了然规则作用。

      以上例子只是列出其中一部分“原子化”的操作,例如还有遍历目录、读取文件、条件过滤等操作,也是可以一块被定义的。

       在实际运行中,脚本会先加载数据采集的规则文件,解析规则文件内容,最终按照规则来采集数据。当把常见的采集动作都“原子化”后,基础的脚本就不需要变更了,后续维护只需要维护对应的规则即可。

执行平台

       脚本方案有了,接着要解决的是执行的问题。

       对于主机数量非常大的组织,应该统一运维管理平台,再不济也应该有批量运维工具,安全运营人员应该借助组织内已有的运维基础能力,去执行检测方案。如果组织内没有,那可以考虑使用ssh远程执行的方式实现。

      执行方式:

  1. 组织内自研的统一运维平台,这个平台可以统一推送并执行脚本;

  2. 开源的自动化运维工具,例如 ansible、saltstack、puppet;

  3. 使用ssh远程命令执行;

       上述3种执行方式视实际生产环境而定,最佳实践方式是依托组织内运维部门所提供的工具或平台来执行,最大降低安全部门的运维管理成本。

数据解析

       被调查主机按照预定的规则执行完脚本后,需要上传数据,由于在采集步骤不对数据处理,就需要在后端根据parser所指定的方法解析成结构化数据。

       

        举个例子:

        在主机上执行脚本会包含ps -ef命令,这个命令可以输出当前系统状态,就像下面这样子的:

 1root@DESKTOP-R11URQV:~# ps -efwww
2UID        PID  PPID  C STIME TTY          TIME CMD
3root      1181     1  0 10:54 ?        00:00:00 /usr/sbin/sshd -D
4root      1183     1  0 10:54 ?        00:00:02 /usr/bin/python2 -Es /usr/sbin/tuned -l -P
5root      1187     1  0 10:54 ?        00:00:01 /usr/sbin/rsyslogd -n
6root      1205     1  0 10:54 ?        00:00:00 /usr/sbin/libvirtd
7root      1218     1  0 10:54 ?        00:00:00 /usr/sbin/atd -f
8root      1224     1  0 10:54 ?        00:00:00 /usr/sbin/crond -n
9root      1355     1  0 10:54 ?        00:00:00 /usr/libexec/postfix/master -w
10postfix   1357  1355  0 10:54 ?        00:00:00 qmgr -l -t unix -u
11mongod    1702     1  0 10:54 ?        00:02:27 /usr/bin/mongod -f /etc/mongod.conf
12nobody    1777     1  0 10:54 ?        00:00:00 /usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf --leasefile-ro --dhcp-script=/usr/libexec/libvirt_leaseshelper
13root      1779  1777  0 10:54 ?        00:00:00 /usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf --leasefile-ro --dhcp-script=/usr/libexec/libvirt_leaseshelper
14root      1929     1  0 10:54 ?        00:00:00 /usr/sbin/gdm
15root      1940     1  0 10:54 ?        00:00:04 /usr/sbin/VBoxService --pidfile /var/run/vboxadd-service.sh
16root      1957  1929  1 10:54 tty1     00:04:00 /usr/bin/X :0 -background none -noreset -audit 4 -verbose -auth /run/gdm/auth-for-gdm-oIi6o5/database -seat seat0 -nolisten tcp vt1
17root      2017     1  0 10:54 ?        00:00:00 /usr/libexec/upowerd
18root      2071     1  0 10:54 ?        00:00:00 /usr/libexec/boltd
19root      2075     1  0 10:54 ?        00:00:00 /usr/libexec/packagekitd
20root      2086     1  0 10:54 ?        00:00:00 /usr/sbin/wpa_supplicant -u -f /var/log/wpa_supplicant.log -c /etc/wpa_supplicant/wpa_supplicant.conf -P /var/run/wpa_supplicant.pid
21colord    2168     1  0 10:54 ?        00:00:00 /usr/libexec/colord
22root      2249  1929  0 10:55 ?        00:00:00 gdm-session-worker [pam/gdm-password]
23root      2260     1  0 10:55 ?        00:00:00 /usr/bin/gnome-keyring-daemon --daemonize --login

        这个命令输出UID、PID、PPID、CMD等信息,这些字符串信息仅限于命令行中看,很难被检索或二次利用。例如此时想看mongod这个进程对应网络连接,就需要再执行一次类似netstat -tlunpa | grep mongod这样的命令。如果要查看几个进程,就得进行几次这样的操作,就会导致效率低下。    

        因此,就需要对输出的信息结构化,转化成可检索可查看的数据,例如:

 1{'user''root''pid''1183''ppid''1''c''0''stime''10:54''tty''?''time''00:00:02''cmd''/usr/bin/python2 -Es /usr/sbin/tuned -l -P'}
2{'user''root''pid''1187''ppid''1''c''0''stime''10:54''tty''?''time''00:00:01''cmd''/usr/sbin/rsyslogd -n'}
3{'user''root''pid''1205''ppid''1''c''0''stime''10:54''tty''?''time''00:00:00''cmd''/usr/sbin/libvirtd'}
4{'user''root''pid''1218''ppid''1''c''0''stime''10:54''tty''?''time''00:00:00''cmd''/usr/sbin/atd -f'}
5{'user''root''pid''1224''ppid''1''c''0''stime''10:54''tty''?''time''00:00:00''cmd''/usr/sbin/crond -n'}
6{'user''root''pid''1355''ppid''1''c''0''stime''10:54''tty''?''time''00:00:00''cmd''/usr/libexec/postfix/master -w'}
7{'user''postfix''pid''1357''ppid''1355''c''0''stime''10:54''tty''?''time''00:00:00''cmd''qmgr -l -t unix -u'}
8{'user''mongod''pid''1702''ppid''1''c''0''stime''10:54''tty''?''time''00:02:27''cmd''/usr/bin/mongod -f /etc/mongod.conf'}
9{'user''nobody''pid''1777''ppid''1''c''0''stime''10:54''tty''?''time''00:00:00''cmd''/usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf --leasefile-ro --dhcp-script=/usr/libexec/libvirt_leaseshelper'}
10{'user''root''pid''1779''ppid''1777''c''0''stime''10:54''tty''?''time''00:00:00''cmd''/usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf --leasefile-ro --dhcp-script=/usr/libexec/libvirt_leaseshelper'}
11{'user''root''pid''1929''ppid''1''c''0''stime''10:54''tty''?''time''00:00:00''cmd''/usr/sbin/gdm'}
12{'user''root''pid''1940''ppid''1''c''0''stime''10:54''tty''?''time''00:00:04''cmd''/usr/sbin/VBoxService --pidfile /var/run/vboxadd-service.sh'}
13{'user''root''pid''1957''ppid''1929''c''1''stime''10:54''tty''tty1''time''00:04:00''cmd''/usr/bin/X :0 -background none -noreset -audit 4 -verbose -auth /run/gdm/auth-for-gdm-oIi6o5/database -seat seat0 -nolisten tcp vt1'}
14{'user''root''pid''2017''ppid''1''c''0''stime''10:54''tty''?''time''00:00:00''cmd''/usr/libexec/upowerd'}
15{'user''root''pid''2071''ppid''1''c''0''stime''10:54''tty''?''time''00:00:00''cmd''/usr/libexec/boltd'}
16{'user''root''pid''2075''ppid''1''c''0''stime''10:54''tty''?''time''00:00:00''cmd''/usr/libexec/packagekitd'}
17{'user''root''pid''2086''ppid''1''c''0''stime''10:54''tty''?''time''00:00:00''cmd''/usr/sbin/wpa_supplicant -u -f /var/log/wpa_supplicant.log -c /etc/wpa_supplicant/wpa_supplicant.conf -P /var/run/wpa_supplicant.pid'}
18{'user''colord''pid''2168''ppid''1''c''0''stime''10:54''tty''?''time''00:00:00''cmd''/usr/libexec/colord'}
19{'user''root''pid''2249''ppid''1929''c''0''stime''10:55''tty''?''time''00:00:00''cmd''gdm-session-worker [pam/gdm-password]'}
20{'user''root''pid''2260''ppid''1''c''0''stime''10:55''tty''?''time''00:00:00''cmd''/usr/bin/gnome-keyring-daemon --daemonize --login'}

       这里解析后的数据是JSON格式的,这些结构化好的数据再传到后台存储,也只有这样的数据才能被检索、被处理。

       需要注意的是,对原始数据解析时应该尽可能做到“无损”解析,因为在调查分析中任何细微的信息都有可能是分析的关键因素。

展示与分析

       采集的内容解析了,接下来就是要怎么展示这些数据了。

       一般来说,要做数据展示都是需要前端界面开发的,如果还需要数据关联或者信息下探,这个界面逻辑会更加复杂;另外,还需要维护一个数据库,做后台存储。这些工作对于没有专业开发能力的安全运营团队来说不是一件简单的事情。

       那是否可以有一款应用可以很好的解决这个问题呢?使用已有的SIEM系统,通过界面定制,可以快速解决这个问题。

小结

       本文旨在借助SIEM的数据收集和分析能力,探索一种可标准化可自动化实现的应急响应机制,以完善在安全运营中更高效完成事件调查闭环。

       或许有人会说,“我一个脚本可以解决的事情,何必整那么复杂”。的确是存在这种情况的。但在组织内,体系和标准化是一件更需要考虑的事情。基于平台化的运营建设才是可持续运营的根本,更重要的是基于平台化建设后,才有条件去实现更细粒度自动化响应场景,从根本上解决耗时耗力的问题。

       本文还有一部分尚未探讨,就是如何将运营人员的调查分析经验直接展示在“调查面板”上,这个内容就需要进一步借助SIEM分析能力,汇总管理风险发现逻辑,在面板上直接将风险内容展示出来。本文权当抛砖引玉,有兴趣的读者可以继续进一步探索。



关注公众号:拾黑(shiheibook)了解更多

[广告]赞助链接:

四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

公众号 关注网络尖刀微信公众号
随时掌握互联网精彩
赞助链接