网络安全法规定,日志留存必须大于6个月,这个我们之前也讨论过,除了采购部署专门的日志记录设备之外,还可以尝试自己建设日志集中统一管理的日志服务器:网络安全日志收集甲方基础实践
笔者:国际认证信息系统审计师、软考系统分析师
但是,不能忽略一个问题是,只是留存还不够,日志内容得有意义才行啊。存下来如果只是一堆没用的信息,那跟没存其实是没啥区别。
所以我们来看看在Linux环境下面如何深度配置日志审计。本文以Rocky Linux 8为操作环境。
首先,我们应该清晰地理解日志审计的意义:
日志审计,是让系统管理员能够通过操作系统的审计功能,发现安全违规行为和跟踪系统上的安全相关信息。
Linux操作系统(发行版)一般都包含有审计守护进程(auditd),对系统中产生的安全事件生成日志记录。管理员使用这些信息可以分析安全策略的问题,并通过采取处理措施解决这些问题。
对于Rocky Linux 8,最小配置模式下就已经默认安装audit审计功能软件包。万一没有安装,可以通过运行如下命令补充安装:
# dnf install audit
auditd的主配置文件是
/etc/audit/auditd.conf
辅助配置文件,比如插件功能的配置文件和规则文件,目录位置是:
/etc/audit/plugins.d
/etc/audit/rules.d
auditd是审计功能的守护进程,但这个守护进程的管理操作和其它服务有所不同。在启用或停用服务时,使用
systemctl enable auditd
systemctl disable auditd
即可实现。但如果需要启动或停止服务,则需要用旧式的service命令去启停,比如:
# service auditd start
# service auditd reload
# service auditd stop
之所以要使用service命令而不是systemctl命令的原因是为了能正确地记录用户ID(UID)值。
接下来是定义审计规则。系统本身默认定义了一些审计规则,但如果获得更丰富和深入的日志痕迹,我们就需要能自己设置审计规则。
通过auditctl命令,可以对任何系统调用添加监视规则。
监视规则的用途是可以通过定义规则去跟踪某些类型的访问,比如读、写、执行和属性更改等,并且是对指定的文件或目录进行时,触发产生审计记录。
监视规则的定义顺序非常重要,因为是基于先匹配先执行的逻辑,所以规则的顺序决定了监视规则是否能按预期地执行。
定义监视规则的语法为:
auditctl -w 完整路径的文件名 -p 许可定义 -k 关键字名称
“关键字名称”可以在需要过滤日志信息时发挥作用。比如,如果要监视创建用户的操作,可以按如下逻辑设置监视规则:
“对/etc/passwd文件,监视文件的写操作和属性修改操作,并对监视规则设置关键字名称”,即:
# auditctl -w /etc/passwd -p wa -k wavecn-modify-user
然后来测试一下,比如添加一个用户:
# useradd wavecn-dummy-user
马上检查审计日志:
# cat /var/log/audit/audit.log | grep wavecn-modify-user
输出内容如下,包括有具体触发了什么系统调用,什么用户触发,修改了什么,等等。
type=CONFIG_CHANGE msg=audit(1667293018.659:92): auid=0 ses=3 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 op=add_rule key="wavecn-modify-user" list=4 res=1AUID="root"
type=SYSCALL msg=audit(1667293026.250:95): arch=c000003e syscall=257 success=yes exit=8 a0=ffffff9c a1=558b28a4cda0 a2=20902 a3=0 items=1 ppid=5656 pid=5715 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=tty2 ses=3 comm="useradd" exe="/usr/sbin/useradd" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key="wavecn-modify-user"ARCH=x86_64 SYSCALL=openat AUID="root" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root"
type=SYSCALL msg=audit(1667293026.260:98): arch=c000003e syscall=82 success=yes exit=0 a0=7ffd5126f8e0 a1=558b28a4cda0 a2=7ffd5126f850 a3=0 items=5 ppid=5656 pid=5715 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=tty2 ses=3 comm="useradd" exe="/usr/sbin/useradd" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key="wavecn-modify-user"ARCH=x86_64 SYSCALL=rename AUID="root" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root"
审计规则需要被保存固化下来,才能在系统重启后依然有效。通过修改:
/etc/audit/rules.d/audit.rules
规则文件,在其中按行添加auditctl的执行参数作为规则定义即可。比如刚才的测试例子,应该在文件中添加这么一行:
-w /etc/passwd -p wa -k wavecn-modify-user
添加后保存文件,然后执行:
# service auditd reload
重新加载配置信息后规则就生效。可以通过auditctl命令观察当前配置信息,如下操作的结果:
# auditctl -l
-w /etc/passwd -p wa -k wavecn-modify-user
对于记录下来的日志,如果要在其中进行内容搜索,可以通过ausearch命令,结合自己定义的关键字名称实现精准过滤,比如这样的搜索输出结果:
# ausearch -i -k wavecn-modify-user
----
type=PROCTITLE msg=audit(2022年11月01日 16:56:58.659:92) : proctitle=auditctl -w /etc/passwd -p wa -k wavecn-modify-user
type=SYSCALL msg=audit(2022年11月01日 16:56:58.659:92) : arch=x86_64 syscall=sendto success=yes exit=1088 a0=0x4 a1=0x7ffeed1acb60 a2=0x440 a3=0x0 items=0 ppid=5656 pid=5713 auid=root uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=tty2 ses=3 comm=auditctl exe=/usr/sbin/auditctl subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=(null)
type=CONFIG_CHANGE msg=audit(2022年11月01日 16:56:58.659:92) : auid=root ses=3 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 op=add_rule key=wavecn-modify-user list=exit res=yes
----
type=PROCTITLE msg=audit(2022年11月01日 16:57:06.250:95) : proctitle=useradd wavecn-dummy-user
type=PATH msg=audit(2022年11月01日 16:57:06.250:95) : item=0 name=/etc/passwd inode=34117457 dev=fd:00 mode=file,644 ouid=root ogid=root rdev=00:00 obj=system_u:object_r:passwd_file_t:s0 nametype=NORMAL cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 cap_frootid=0
type=CWD msg=audit(2022年11月01日 16:57:06.250:95) : cwd=/root
type=SYSCALL msg=audit(2022年11月01日 16:57:06.250:95) : arch=x86_64 syscall=openat success=yes exit=8 a0=AT_FDCWD a1=0x558b28a4cda0 a2=O_RDWR|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW a3=0x0 items=1 ppid=5656 pid=5715 auid=root uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=tty2 ses=3 comm=useradd exe=/usr/sbin/useradd subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=wavecn-modify-user
----
type=PROCTITLE msg=audit(2022年11月01日 16:57:06.260:98) : proctitle=useradd wavecn-dummy-user
type=PATH msg=audit(2022年11月01日 16:57:06.260:98) : item=4 name=/etc/passwd inode=34117482 dev=fd:00 mode=file,644 ouid=root ogid=root rdev=00:00 obj=system_u:object_r:passwd_file_t:s0 nametype=CREATE cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 cap_frootid=0
type=PATH msg=audit(2022年11月01日 16:57:06.260:98) : item=3 name=/etc/passwd inode=34117457 dev=fd:00 mode=file,644 ouid=root ogid=root rdev=00:00 obj=system_u:object_r:passwd_file_t:s0 nametype=DELETE cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 cap_frootid=0
type=PATH msg=audit(2022年11月01日 16:57:06.260:98) : item=2 name=/etc/passwd+ inode=34117482 dev=fd:00 mode=file,644 ouid=root ogid=root rdev=00:00 obj=system_u:object_r:passwd_file_t:s0 nametype=DELETE cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 cap_frootid=0
type=PATH msg=audit(2022年11月01日 16:57:06.260:98) : item=1 name=/etc/ inode=33554561 dev=fd:00 mode=dir,755 ouid=root ogid=root rdev=00:00 obj=system_u:object_r:etc_t:s0 nametype=PARENT cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 cap_frootid=0
type=PATH msg=audit(2022年11月01日 16:57:06.260:98) : item=0 name=/etc/ inode=33554561 dev=fd:00 mode=dir,755 ouid=root ogid=root rdev=00:00 obj=system_u:object_r:etc_t:s0 nametype=PARENT cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 cap_frootid=0
type=CWD msg=audit(2022年11月01日 16:57:06.260:98) : cwd=/root
type=SYSCALL msg=audit(2022年11月01日 16:57:06.260:98) : arch=x86_64 syscall=rename success=yes exit=0 a0=0x7ffd5126f8e0 a1=0x558b28a4cda0 a2=0x7ffd5126f850 a3=0x0 items=5 ppid=5656 pid=5715 auid=root uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=tty2 ses=3 comm=useradd exe=/usr/sbin/useradd subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=wavecn-modify-user
还有一个aureport命令,可以用于输出汇总报表,也即如下的输出:
# aureport -x
Executable Report
====================================
# date time exe term host auid event
====================================
1. 2022年11月01日 16:39:34 /usr/lib/systemd/systemd ? ? -1 5
2. 2022年11月01日 16:39:34 /usr/sbin/auditctl (none) ? -1 6
3. 2022年11月01日 16:39:34 /usr/sbin/auditctl (none) ? -1 7
4. 2022年11月01日 16:39:34 /usr/sbin/auditctl (none) ? -1 8
5. 2022年11月01日 16:39:34 /usr/lib/systemd/systemd ? ? -1 9
6. 2022年11月01日 16:39:34 /usr/lib/systemd/systemd ? ? -1 10
7. 2022年11月01日 16:39:34 /usr/lib/systemd/systemd-update-utmp ? ? -1 11
8. 2022年11月01日 16:39:34 /usr/lib/systemd/systemd ? ? -1 12
9. 2022年11月01日 16:39:34 /usr/lib/systemd/systemd ? ? -1 13
...
从该报表可以获得日期、时间、运行程序、终端、主机、用户登录ID(auid)和事件编号等信息。
需要注意的是,审计规则越多,对系统的性能就越构成拖累。因此,我们需要对审计服务进行优化。优化的规则有以下2条:
1、由于审计规则是顺序检查匹配的,所以,规则顺序的作用不仅体现在审计触发条件,还体现在规则被执行的次数上。越有可能频繁触发的规则就越应该放在最前面。
2、精简审计内容,只审计有意义的事件,不审计无意义的事件。这个应该不用解释了。
具体优化时,首先要区分找出最频繁出现的事件,比如按运行的命令筛选汇总:
# aureport -ts today -i -x --summary
Executable Summary Report
=================================
total file
=================================
62 /usr/lib/systemd/systemd
46 /usr/sbin/xtables-nft-multi
19 /usr/sbin/sshd
8 /usr/bin/login
6 /usr/sbin/auditctl
6 /usr/libexec/platform-python3.6
4 /usr/lib/systemd/systemd-update-utmp
又如按最频繁的系统调用(syscall)筛选汇总:
# aureport -ts today -i -s --summary
Syscall Summary Report
==========================
total syscall
==========================
52 sendmsg
6 sendto
3 write
以上的汇总,可以使管理员知道是什么可执行文件或者系统调用的事件在充塞着审计日志。通过定义“-ts today”参数,可以只统计今天发生的事件。
很显然,基于aureport统计的结果,然后选择性地禁用某些事件(或者对某些特定的文件、特定的类别等),这就可以减少日志记录的数量,从而降低审计日志对系统的压力。
因为这些事件并不是通过自定义事件产生的,是系统预设的,所以要忽略事件就要制定排除事件的规则,在匹配到要排除的事件时,使用exit或exclude声明。其中,exit声明适用于syscall,其它的使用exclude。
-a exclude,always -F msgtype=CWD
如上的例子,禁用所有的“CWD”(当前工作目录)消息类型。由于是基于消息类型进行筛选,所以使用exclude声明。
必须牢记规则的先匹配先执行的规律,因此,排除规则必须放在规则列表的最前面。
在需要时,还可以通过组合条件实现按多个规则筛选。
方法是通过给出多个-F参数,将多个规则组合在一起。规则定义最多允许使用64个判定条件。
当使用-F参数时,每个表达式都将使用逻辑与的连接符进行检查。这意味着所有条件都必须是“真”才能触发审计规则。
如下的例子是对虚拟机中运行的vmware-tools相关的事件进行筛选,可以自己尝试理解一下组合起来的判断逻辑:
-a exit,never -F arch=b32 -S fork -F success=0 -F path=/usr/lib/vmware-tools -F subj_type=initrc_t -F exit=-2
-a exit,never -F arch=b64 -S fork -F success=0 -F path=/usr/lib/vmware-tools -F subj_type=initrc_t -F exit=-2
必须说明的是,任何规则都需要经过实际运行测试,以确定是否有效。尤其是不同的Linux发行版之间很可能会存在差异,不测试就无法确定规则是否有效,无效的规则不仅不起作用,还有可能对系统性能产生负面影响。
即使进行了以上调整后,审计事件还存在一种情况是短时间内大量产生,缓冲区不够容量导致记录不下来。此时,我们需要调整缓冲区设置。
允许更大的缓冲区必然意味着对内存资源的需求更高,但为了确保审计事件能被完整记录,这点资源是必须要满足的。
首先我们通过auditctl检查一下状态,使用-s(状态)参数时获得统计信息。
如下的例子,显示了包括:auditd启用状态、失败控制标志、进程ID、速率限制、积压限制、丢失数量、积压数量、积压等待时间、实际积压等待时间、登录UID是否锁定。
# auditctl -s
enabled 1
failure 1
pid 941
rate_limit 0
backlog_limit 8192
lost 0
backlog 0
backlog_wait_time 60000
backlog_wait_time_actual 0
loginuid_immutable 0 unlocked
以上数值中,主要关注的是积压数量backlog的值。
要确定最好的缓冲区大小,要监视backlog的值。它不应该超过积压限制backlog_limt选项的值(在我们的例子中是8192)。
另一个有用的统计信息是监视丢失数量lost的值,丢失数量也就是有多少事件无法被正确处理。在一个正常的系统中,这个值应该等于或接近于零。
如果backlog大于等于backlog_limit,或者lost的值大于0,则需要调整backlog_limit的值,方法是通过给出-b参数和要设置的值,例如:
# auditctl -b 16384
enabled 1
failure 1
pid 941
rate_limit 0
backlog_limit 16384
lost 0
backlog 0
backlog_wait_time 60000
backlog_wait_time_actual 0
最后一个比较特殊的优化策略是如果要监控目录,应先确定只是监控该目录本级还是需要监控从该目录开始的整个目录树。我们把监控目录本级称为路径(path),把监控整个目录树称为目录(dir)。这是在通过-F参数设定判定逻辑时,以声明path还是dir来指向目录的区别。
如果不需要监控目录树,则务必只设置为监控目录本级。这样就可以避免产生大量不需要的审计日志记录。
注:本期封面图也是通过AI生成,来自Algolet小算法:
本站微信订阅号:
本页网址二维码: