4、Linux内核的IMA机制:IMA概述、IMA策略配置、IMA日志收集与解析
好,咱们进入可信启动实战的第四个模块——IMA。说实话,IMA 这玩意儿,我第一次接触的时候也觉得有点绕。但搞明白了之后,你会发现它其实是内核给你的一把「审计放大镜」。它能盯着每一个文件,看它到底被谁执行了、内容有没有被改过。
我当年在做一个等保三级项目时,客户要求「所有可执行文件必须被度量」。当时第一反应就是上 IMA。嗯,今天我就把 IMA 的底裤给你扒干净。
4.1 IMA 概述:它到底在度量什么?
IMA,全称 Integrity Measurement Architecture,中文叫「完整性度量架构」。说白了,它就是在文件被访问(比如执行、mmap)之前,先算个哈希,然后把这个哈希记录下来。
你想想看,如果某个恶意程序替换了 /bin/ls,你肉眼根本看不出来。但 IMA 会记录下这个文件的度量值。你只要对比一下就知道——嗯,这个 ls 已经不是原来的 ls 了。
核心要点:IMA 度量的是文件的「内容完整性」,不是「权限完整性」。它只关心文件内容有没有变,不关心谁改了它。
IMA 的工作流程其实很简单:
- 触发点:文件被打开执行(
BPRM_CHECK)、文件被 mmap 到内存(FILE_MMAP)、文件被读取(FILE_READ)。 - 动作:内核计算文件的 SHA1/SHA256 哈希值。
- 记录:将哈希值、文件路径、元数据写入内核度量列表(
IMA_MEASURE)。 - 扩展:将度量值扩展到 TPM PCR 10 中(如果配置了 TPM)。
我记得有一次,客户说「为什么我改了配置文件,IMA 没报警?」我一看,原来他改的是 /etc/ssh/sshd_config,但这个文件不是可执行文件,默认策略不度量它。所以,IMA 不是什么都管的,它只度量你策略里指定的文件类型。
4.2 IMA 策略配置:怎么让它听你的?
IMA 的策略,说白了就是一组规则。规则写在 /etc/ima/ima-policy 或者内核启动参数里。我个人习惯把策略放在 /etc/ima/ima-policy,然后在 /etc/default/grub 里加上 ima_policy=tcb 来加载。
策略的语法长这样:
# 度量所有可执行文件
measure func=BPRM_CHECK
# 度量所有 mmap 的可执行文件
measure func=FILE_MMAP mask=MAY_EXEC
# 度量所有 root 用户读取的文件
measure func=FILE_READ uid=0
# 不度量 /tmp 目录下的文件
dont_measure func=FILE_READ fsmagic=0x01021994
这里有几个关键字段,我列个表给你看:
| 字段 | 含义 | 常用值 |
|---|---|---|
func |
触发函数 | BPRM_CHECK, FILE_MMAP, FILE_READ |
mask |
访问权限掩码 | MAY_EXEC, MAY_READ, MAY_WRITE |
uid |
用户 ID | 0(root), 1000(普通用户) |
fsmagic |
文件系统魔数 | 0x01021994(tmpfs), 0xEF53(ext4) |
appraise |
是否校验 | appraise, dont_appraise |
小技巧:如果你不想度量 /proc、/sys 这些伪文件系统,一定要加 dont_measure 规则。否则 IMA 日志会被刷爆。我曾经在一个生产环境上忘了加,结果一天之内日志涨了 2GB……嗯,教训深刻。
配置好策略后,用这个命令加载:
# 加载策略
echo "measure func=BPRM_CHECK" > /sys/kernel/security/ima/policy
# 查看当前策略
cat /sys/kernel/security/ima/policy
注意,/sys/kernel/security/ima/policy 这个文件只能写一次。如果你想重新加载,得重启系统。所以,我建议你在测试环境里先调好策略,再部署到生产。
4.3 IMA 日志收集与解析:怎么从日志里挖出真相?
IMA 的日志,主要存在两个地方:
- 内核度量列表:在
/sys/kernel/security/ima/ascii_runtime_measurements里,这是人类可读的格式。 - 审计日志:如果开启了 auditd,IMA 事件会记录到
/var/log/audit/audit.log里。
我们先看看 ascii_runtime_measurements 长什么样:
10 1a2b3c4d5e6f7890 ima-ng sha1:abcdef1234567890abcdef1234567890abcdef12 /usr/bin/bash
10 2b3c4d5e6f78901a ima-ng sha1:1234567890abcdef1234567890abcdef12345678 /usr/bin/ls
10 3c4d5e6f78901a2b ima-ng sha1:abcdefabcdefabcdefabcdefabcdefabcdefabcd /etc/passwd
每一行的格式是:
- PCR 编号:通常是 10,表示这个度量扩展到了 TPM PCR 10。
- 哈希值:模板哈希,用于校验完整性。
- 模板名称:一般是
ima-ng或ima-sig。 - 文件哈希:文件的 SHA1/SHA256 值。
- 文件路径:被度量文件的绝对路径。
那审计日志里的 IMA 事件呢?我 grep 给你看:
# 从 audit.log 中提取 IMA 事件
ausearch -m INTEGRITY_RULE -ts today
# 或者直接 grep
grep "ima" /var/log/audit/audit.log | head -5
输出大概是这样:
type=INTEGRITY_RULE msg=audit(1700000000.123:456): action=measure func=BPRM_CHECK
type=INTEGRITY_MEASURE msg=audit(1700000001.456:789): pid=1234 uid=0 auid=1000 ses=1 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 comm="bash" exe="/usr/bin/bash" hash="sha1:abcdef1234567890abcdef1234567890abcdef12"
这里的关键字段:
action:度量动作,measure表示度量,appraise表示校验。comm:进程名。exe:可执行文件路径。hash:文件的哈希值。
注意:审计日志里的 IMA 事件默认可能不开启。你需要在 /etc/audit/rules.d/ima.rules 里加一条规则:-w /sys/kernel/security/ima/ascii_runtime_measurements -p wa -k ima_log。否则,你只能从 ascii_runtime_measurements 里看。
解析 IMA 日志,我一般用这个脚本:
#!/bin/bash
# 解析 IMA 度量列表,提取文件路径和哈希值
cat /sys/kernel/security/ima/ascii_runtime_measurements | while read line; do
pcr=$(echo $line | awk '{print $1}')
file_hash=$(echo $line | awk '{print $4}')
file_path=$(echo $line | awk '{print $5}')
echo "PCR: $pcr | Hash: $file_hash | File: $file_path"
done
当然,你也可以用 evmctl 工具来验证:
# 验证文件的 IMA 度量值
evmctl ima_verify /usr/bin/bash
# 查看文件的 IMA 扩展属性
getfattr -d -m "security.ima" /usr/bin/bash
这里有个坑——evmctl ima_verify 需要文件有 security.ima 扩展属性。如果文件没有这个属性,它会报错。我曾经在 CentOS 7 上遇到过,后来发现是内核没开启 CONFIG_IMA_APPRAISE。所以,编译内核时一定要确认这个选项。
4.4 IMA 知识体系总览
下面这张图,是我梳理的 IMA 核心逻辑。你可以把它当作一个「地图」,以后遇到 IMA 相关的问题,先看这张图定位问题。
从这张图你可以看到,IMA 的整个链路是:文件操作 → 策略匹配 → 度量/扩展 → 日志记录 → 解析验证 → 结果判定。任何一个环节出问题,都会导致度量失败。
我个人建议,在生产环境部署 IMA 之前,先在测试环境里跑一遍这个流程。特别是策略配置,一定要确认你度量了「该度量的」,排除了「不该度量的」。否则,要么漏报,要么日志爆炸。