概述
理解审计
审计(audit)这个概念最初来自于会计领域,意为对一个组织或个体的账户和财务状态进行正式评估:
An audit is an “independent examination of financial information of any entity, whether profit oriented or not, irrespective of its size or legal form when such an examination is conducted with a view to express an opinion thereon”.
投资者无法判断企业的财务报表有没有水分,因此雇佣专业的第三方(会计事务所)作为裁判来鉴别财务报表的真实性,以防作弊。
审计有两个关键词:
- 独立的第三方
- 正式
在信息安全领域,被审计的对象就是信息系统,审计的维度不再局限于真实性,还包括机密性、完整性、可用性等多个维度,
具体到 Linux 系统中,审计过程的第三方就是内核,“正式”意味着在内核中根据设定的规则生成审计消息。
日志和审计常常被一起提及,因为它们都记录了系统的行为,区别在于:
- 日志的主体是应用程序,每个进程都可以发送消息给日志服务,相当于“主动向组织交代情况”,严格说来日志是不可靠的,因为进程可以多发、少发、不发甚至错发日志消息。
- 审计的主体是内核,无论进程是否发送消息,内核都能记录进程的足迹(例如访问了什么文件,走了什么系统调用),相当于“Big brother is watching you”(误),至于在哪些位置放摄像头,则是由审计规则决定的。
日志属于调测领域,审计属于安全领域,这是两者本质的区别。
内核中的审计
整个审计子系统的各部分构成如下:
内核中的 audit 子系统是审计系统的核心,
除此以外,审计子系统也提供了一系列用户态组件方便用户使用:
- auditd 服务进程是 Linux 审计子系统的用户态组件,负责将审计结果写到日志。
/etc/audit/auditd.conf
文件用于配置 auditd 服务进程的行为。
- audispd 负责给其他应用发送事件通知。
- audit.log 文件记录了度量日志
- aureport 用于生成个性化的报告。
- ausearch 用于检索信息。
- auditctl 命令负责配置审计规则
/etc/audit/audit.rules
/etc/audit/rules.d/*
- autrace 通过与 strace 类似的方式对系统调用进行跟踪
用户视角:使用审计机制
开启审计服务
首先查看内核审计子系统的状态:
1 | auditctl -s |
enabled 参数表示系统审计开关,可通过 -e
选项设置,取值包括 0|1|2
三种:
0
表示禁用审计;1
表示启用审计(默认);2
表示启用审计并锁定配置,锁定后所有配置无法更改,直到重新启动。
注:如果出现
audit support not in kernel
字样,表示审计模块未加载进内核,可能是内核启动参数中加了aduit=0
的限制,需要删除该字段或将其修改为audit=1
。
内核审计系统启用的情况下,能够正常获取审计信息,但还需要启动用户态的 auditd 服务收集和记录日志:
1 | service auditd status # 查看auditd服务状态 |
可通过 /etc/audit/auditd.conf
文件配置 auditd 服务,常见配置包括:
配置项 | 含义 | 推荐设置 |
---|---|---|
write_logs | 是否写日志 | yes |
log_file | 日志路径 | /var/log/audit/audit.log |
max_log_file | 日志文件大小上限(以 MB 为单位) | 8 |
max_log_file_action | 日志文件到达上限后的动作 | keep_logs |
space_left | 磁盘剩余空间下限 | 75 |
space_left_action | 磁盘剩余空间不足下限后的动作 | email 或 exec(执行脚本) |
flush | 日志文件更新后磁盘的同步策略 | sync 或 data |
更多参数和解释可以在 auditd.conf(5) 手册页中找到。
更新此配置文件后需要重启 auditd 服务才能生效:
1 | service auditd restart |
配置审计规则
auditctl 命令可被用于配置审计规则,例如审计对 /etc/ssh/sshd_config
文件的所有访问
-w
选项指定要审计的文件路径。-p
选项描述系统调用对文件的访问动作:- rwx 分别表示读文件、写文件、执行文件;
- a 表示文件属性修改。
-k
选项指定过滤关键词,生成的审计日志消息会包含这个关键词,后续可用于日志过滤。-a
选项-S
选项-F
选项
更多选项和解释可以在 audit.rules(7) 手册页中找到。
如果需要每次启动都生效,可以通过配置 /etc/audit/audit.rules
文件或在 /etc/audit/rules.d
目录新增配置文件实现,配置文件的内容就是加在 auditctl 命令后的选项和参数。
常见配置如下:
不配置审计规则:
1
2-D
-e 0审计登录事件,添加如下规则行:
1
2-w /var/log/faillog -p wa -k logins
-w /var/log/lastlog -p wa -k logins审计内核模块加载、卸载事件,添加如下规则行:
1
2
3
4-w /sbin/insmod -p x -k modules
-w /sbin/rmmod -p x -k modules
-w /sbin/modprobe -p x -k modules
-a always,exit -F arch=b64 -S init_module -S delete_module -k modules在所有配置项后增加
-e 2
可
配置完成后,可以使用 -l
选项查看系统当前审计规则:
1 | auditctl -l # 查看所有生效的审计规则 |
使用 -D
选项删除审计规则(通常会配置 -k
选项使用,不加的话就是删除所有规则):
1 | auditctl -D # 删除所有审计规则 |
一方面,配置的审计规则越多,监控的事件就越多,系统会更加安全,另一方面,大量审计规则也会带来性能影响,所以用户需要根据实际情况设置规则。
阅读审计日志
审计日志记录了审计活动的结果,通常位于 /var/log/audit/audit.log
路径下,通过阅读审计日志,我们能得到许多关于系统状态的信息。
理解日志
以一个典型的审计事件为例:
1 | type=SYSCALL msg=audit(1434371271.277:135496): arch=c000003e syscall=2 success=yes exit=3 a0=7fff0054e929 a1=0 a2=1fffffffffff0000 a3=7fff0054c390 items=1 ppid=6265 pid=6266 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=113 comm="cat" exe="/usr/bin/cat" key="sshconfigchange" |
type
:表示审计事件的类型,type=SYSCALL
表示日志由系统调用所触发;msg
:表示时间戳和事件 ID(同一审计事件可能有多条记录,但都有相同的事件 ID);arch
:表示 CPU 体系结构(c000003e
对应 x86,c00000b7
对应 arm);syscall
:表示触发事件的系统调用号,可通过 ausyscall 命令查询:1
2
3
4
5
6ausyscall 189 # 查询189号系统调用
lsetxattr
ausyscall --dump # 列出所有支持审计的系统调用
0 read
1 write
...success
:表示系统调用返回成功与否;exit
:表示系统调用的返回值;a0-a3
:传递给系统调用的前四个参数;ppid
:表示父进程 ID;pid
:表示触发系统调用的进程 ID;auid
uid
comm
:表示触发审计的命令;exe
:表示触发审计的命令的文件路径;key
:表示审计规则中定义的标签;
检索有效信息
audit 日志文件的信息很多,日志很不方便,
生成审计报告
生成有关可执行文件的审计事件的报告:
1 | aureport -x |
也可以结合 ausearch 命令生成报告:
1 | ausearch --start today --loginuid 500 --raw | aureport -f --summary |
更多选项及使用方法,请参考 aureport(8) 手册页。
开发者视角:调用审计接口
函数接口
首先调用 audit_log_start
函数申请一个缓冲区:
1 | struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type); |
- 【入参1】audit_context:审计上下文
- 【入参2】gfp_mask:缓冲区类型,通常是 GFP_KERNEL
- 【入参3】type:审计日志类型
- 【返回值】audit_buffer:缓冲区指针
然后调用 audit_log_format
往缓冲区中写日志:
1 | void audit_log_format(struct audit_buffer *ab, const char *fmt, ...); |
- 【入参1】audit_buffer:审计缓冲区
- 【入参2】fmt:格式化字符串
- 【入参3】可变参数
- 【返回值】空
最后调用 audit_log_end
结束写日志:
1 | void audit_log_end(struct audit_buffer *ab); |
- 【入参1】audit_buffer:审计缓冲区
- 【返回值】空
例程
1 |
|
内核源码剖析
审计机制属于内核最核心的部分,因此代码都在 kernel
目录下,首先对文件有个大致的了解:
audit.h
:头文件,定义审计机制使用的通用结构体和函数;audit.c
:提供核心审计机制;auditsc.c
:实际了对系统调用的审计;auditfilter.c
:包含了过滤审计事件的机制;audit_fsnotify.c
audit_tree.c
audit_watch.c
其中,audit.c
、auditsc.c
和 auditfilter.c
是最核心的
数据结构
audit_context
审计过程
开始审计
本质上 audit_log_start
的工作是建立一个 audit_buffer 实例并将其返回给调用者,但在此之前需要考虑积压队列的长度限制和发送数据的速率限制。
如果积压队列长度和数据速率限制的检查能够通过,则使用 audit_buffer_alloc
分配一个 audit_buffer
实例。
写入记录消息
结束审计记录
在所有必要的记录消息都已经写入到审计缓冲区之后,需要调用 audit_log_end
确保将审计记录发送给用户空间守护进程。
系统调用审计
参考资料
- man 手册页
- 开发者官网:https://linux-audit.com
- CentOS 7 审计系统使用指南:https://www.digitalocean.com/community/tutorials/how-to-use-the-linux-auditing-system-on-centos-7
- SUSE 提供的资料:https://documentation.suse.com/sles/11-SP4/html/SLES-all/cha-audit-comp.html
变更记录
- 2020.11.20:添加“函数接口”。
- 2020.11.18:完成“使用审计机制-开启审计服务”。
- 2020.11.17:完成目录框架。
- Post title:深入 Linux 审计机制
- Post author:Anakin
- Create time:2020-11-17 22:41:37
- Post link:https://nettingsisyphus.tech/2020/11/17/linux-audit-guide/
- Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.