深入 Linux 审计机制
Anakin Lv1

概述

理解审计

审计(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”(误),至于在哪些位置放摄像头,则是由审计规则决定的。

日志属于调测领域,审计属于安全领域,这是两者本质的区别。

内核中的审计

整个审计子系统的各部分构成如下:

Introducing the Components of Linux Audit

内核中的 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
2
3
$ auditctl -s
enabled 1
...

enabled 参数表示系统审计开关,可通过 -e 选项设置,取值包括 0|1|2 三种:

  • 0 表示禁用审计;
  • 1 表示启用审计(默认);
  • 2 表示启用审计并锁定配置,锁定后所有配置无法更改,直到重新启动。

注:如果出现 audit support not in kernel 字样,表示审计模块未加载进内核,可能是内核启动参数中加了 aduit=0 的限制,需要删除该字段或将其修改为 audit=1

内核审计系统启用的情况下,能够正常获取审计信息,但还需要启动用户态的 auditd 服务收集和记录日志:

1
2
$ service auditd status    # 查看auditd服务状态
$ service auditd start # 启用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
2
$ auditctl -l              # 查看所有生效的审计规则
$ auditctl -l -k logins # 查看所有包含logins关键词的审计规则

使用 -D 选项删除审计规则(通常会配置 -k 选项使用,不加的话就是删除所有规则):

1
2
$ auditctl -D              # 删除所有审计规则
$ auditctl -D -k logins # 删除所有包含logins关键词的审计规则

一方面,配置的审计规则越多,监控的事件就越多,系统会更加安全,另一方面,大量审计规则也会带来性能影响,所以用户需要根据实际情况设置规则。

阅读审计日志

审计日志记录了审计活动的结果,通常位于 /var/log/audit/audit.log 路径下,通过阅读审计日志,我们能得到许多关于系统状态的信息。

理解日志

以一个典型的审计事件为例:

1
2
3
4
5
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=CWD msg=audit(1434371271.277:135496): cwd="/home/sammy"

type=PATH msg=audit(1434371271.277:135496): item=0 name="/etc/ssh/sshd_config" inode=392210 dev=fd:01 mode=0100600 ouid=0 ogid=0 rdev=00:00 objtype=NORMAL
  • type:表示审计事件的类型,type=SYSCALL 表示日志由系统调用所触发;

  • msg:表示时间戳和事件 ID(同一审计事件可能有多条记录,但都有相同的事件 ID);

  • arch:表示 CPU 体系结构(c000003e 对应 x86,c00000b7 对应 arm);

  • syscall:表示触发事件的系统调用号,可通过 ausyscall 命令查询:

    1
    2
    3
    4
    5
    6
    $ ausyscall 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <linux/audit.h>

void test_audit_msg(int audit_msgno)
{
struct audit_buffer *ab;

ab = audit_log_start(audit_context(), GFP_KERNEL, audit_msgno);

audit_log_format();

audit_log_end(ab);
}

int main()
{
return 0;
}

内核源码剖析

审计机制属于内核最核心的部分,因此代码都在 kernel 目录下,首先对文件有个大致的了解:

  • audit.h:头文件,定义审计机制使用的通用结构体和函数;
  • audit.c:提供核心审计机制;
  • auditsc.c:实际了对系统调用的审计;
  • auditfilter.c:包含了过滤审计事件的机制;
  • audit_fsnotify.c
  • audit_tree.c
  • audit_watch.c

其中,audit.cauditsc.cauditfilter.c 是最核心的

数据结构

audit_context

审计过程

开始审计

本质上 audit_log_start 的工作是建立一个 audit_buffer 实例并将其返回给调用者,但在此之前需要考虑积压队列的长度限制和发送数据的速率限制。

如果积压队列长度和数据速率限制的检查能够通过,则使用 audit_buffer_alloc 分配一个 audit_buffer 实例。

写入记录消息

结束审计记录

在所有必要的记录消息都已经写入到审计缓冲区之后,需要调用 audit_log_end 确保将审计记录发送给用户空间守护进程。

系统调用审计

参考资料

变更记录

  • 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.