第一百七十三章:审计之道
渡劫期涉及内核源码:
一
离开密钥宝库,林小源走进一条漫长的回廊。回廊的墙壁上密密麻麻地刻满了文字——时间戳、进程号、用户 ID、操作类型——每一条都是一次系统事件的记录。
一个手持竹简的灰袍修士站在回廊中央,目光如鹰,不放过任何一行文字。
"审计,"灰袍修士头也不抬,"我记录系统中发生的一切。谁在什么时候做了什么,我都记得清清楚楚。"
林小源走近墙壁,看到一行行结构化的日志:type=SYSCALL timestamp=2024-01-15 10:30:00 pid=1234 uid=0 comm=sudo——一个 root 用户执行了 sudo 命令。下一行是 type=PATH name=/etc/shadow——他访问了密码文件。
"每一条系统调用,每一次文件访问,每一次认证尝试,"审计修士翻动竹简,"都被记录下来。不是为了阻止——那是 SELinux 和 seccomp 的事。我只负责记住。"
"记住有什么用?"
审计修士终于抬起头,目光锐利:"事后调查。如果系统被入侵了,你需要知道攻击者做了什么、访问了哪些文件、安装了什么后门。时间线重建——这就是审计的价值。"
/*
* Linux 审计框架:
*
* 审计事件:
* SYSCALL — 系统调用
* PATH — 文件路径
* CWD — 当前目录
* EXECVE — 执行程序
* USER_AUTH — 用户认证
* USER_CMD — 用户命令
*
* 审计规则:
* -w path -p permissions — 监控文件
* -a always,exit -S syscall — 监控系统调用
* -w /etc/passwd -p wa — 监控密码文件
*
* 审计日志:
* /var/log/audit/audit.log
* 结构化日志
*
* 工具:
* auditctl — 控制审计规则
* ausearch — 搜索审计日志
* aureport — 生成审计报告
*
* 用途:
* 安全合规 — PCI DSS, HIPAA
* 事件调查 — 入侵分析
* 策略监控 — SELinux 拒绝
*/
/* 模拟审计事件 */
struct audit_event {
int type;
char timestamp[32];
int pid;
int uid;
char comm[16];
char msg[256];
};
const char *event_type_name(int type) {
switch (type) {
case 1: return "SYSCALL";
case 2: return "PATH";
case 3: return "EXECVE";
case 4: return "USER_AUTH";
case 5: return "USER_CMD";
default: return "UNKNOWN";
}
}
void print_event(struct audit_event *e) {
printf("type=%s timestamp=%s pid=%d uid=%d comm=%s\n",
event_type_name(e->type), e->timestamp,
e->pid, e->uid, e->comm);
if (e->msg[0])
printf(" msg=%s\n", e->msg);
}
printf("=== 审计之道 — 记录一切 ===\n\n");
printf("审计记录系统中发生的一切:\n\n");
/* 模拟审计事件 */
struct audit_event events[] = {
{1, "2024-01-15 10:30:00", 1234, 0, "sudo",
"execve /usr/bin/cat /etc/shadow"},
{2, "2024-01-15 10:30:00", 1234, 0, "cat",
"name=/etc/shadow"},
{4, "2024-01-15 10:31:00", 5678, 1000, "sshd",
"PAM:authentication"},
{5, "2024-01-15 10:32:00", 1234, 0, "sudo",
"user=root command=/bin/bash"},
{1, "2024-01-15 10:33:00", 9012, 1000, "rm",
"execve /usr/bin/rm /tmp/file"},
};
int n = sizeof(events) / sizeof(events[0]);
printf("--- 审计日志示例 ---\n");
for (int i = 0; i < n; i++) {
print_event(&events[i]);
}
printf("\n--- 审计规则 ---\n");
printf("监控文件:\n");
printf(" auditctl -w /etc/passwd -p wa\n");
printf(" 监控写入和属性修改\n\n");
printf("监控系统调用:\n");
printf(" auditctl -a always,exit -F arch=b64 -S open\n");
printf(" 监控所有 open 调用\n\n");
printf("监控用户:\n");
printf(" auditctl -a always,exit -F uid=0\n");
printf(" 监控 root 操作\n\n");
printf("--- 搜索日志 ---\n");
printf("按时间:\n");
printf(" ausearch -ts today\n\n");
printf("按用户:\n");
printf(" ausearch -ui 0\n\n");
printf("按事件:\n");
printf(" ausearch -m USER_AUTH\n\n");
printf("按文件:\n");
printf(" ausearch -f /etc/passwd\n\n");
printf("--- 审计报告 ---\n");
printf("aureport:\n");
printf(" --auth — 认证报告\n");
printf(" --login — 登录报告\n");
printf(" --file — 文件报告\n");
printf(" --syscall — 系统调用报告\n\n");
printf("--- 用途 ---\n");
printf("安全合规:\n");
printf(" PCI DSS — 支付卡行业\n");
printf(" HIPAA — 医疗行业\n\n");
printf("事件调查:\n");
printf(" 入侵分析\n");
printf(" 时间线重建\n\n");
printf("策略监控:\n");
printf(" SELinux 拒绝\n");
printf(" 违规行为\n");#include <stdio.h>
#include <string.h>
#include <time.h>
/*
* Linux 审计框架:
*
* 审计事件:
* SYSCALL — 系统调用
* PATH — 文件路径
* CWD — 当前目录
* EXECVE — 执行程序
* USER_AUTH — 用户认证
* USER_CMD — 用户命令
*
* 审计规则:
* -w path -p permissions — 监控文件
* -a always,exit -S syscall — 监控系统调用
* -w /etc/passwd -p wa — 监控密码文件
*
* 审计日志:
* /var/log/audit/audit.log
* 结构化日志
*
* 工具:
* auditctl — 控制审计规则
* ausearch — 搜索审计日志
* aureport — 生成审计报告
*
* 用途:
* 安全合规 — PCI DSS, HIPAA
* 事件调查 — 入侵分析
* 策略监控 — SELinux 拒绝
*/
/* 模拟审计事件 */
struct audit_event {
int type;
char timestamp[32];
int pid;
int uid;
char comm[16];
char msg[256];
};
const char *event_type_name(int type) {
switch (type) {
case 1: return "SYSCALL";
case 2: return "PATH";
case 3: return "EXECVE";
case 4: return "USER_AUTH";
case 5: return "USER_CMD";
default: return "UNKNOWN";
}
}
void print_event(struct audit_event *e) {
printf("type=%s timestamp=%s pid=%d uid=%d comm=%s\n",
event_type_name(e->type), e->timestamp,
e->pid, e->uid, e->comm);
if (e->msg[0])
printf(" msg=%s\n", e->msg);
}
int main() {
printf("=== 审计之道 — 记录一切 ===\n\n");
printf("审计记录系统中发生的一切:\n\n");
/* 模拟审计事件 */
struct audit_event events[] = {
{1, "2024-01-15 10:30:00", 1234, 0, "sudo",
"execve /usr/bin/cat /etc/shadow"},
{2, "2024-01-15 10:30:00", 1234, 0, "cat",
"name=/etc/shadow"},
{4, "2024-01-15 10:31:00", 5678, 1000, "sshd",
"PAM:authentication"},
{5, "2024-01-15 10:32:00", 1234, 0, "sudo",
"user=root command=/bin/bash"},
{1, "2024-01-15 10:33:00", 9012, 1000, "rm",
"execve /usr/bin/rm /tmp/file"},
};
int n = sizeof(events) / sizeof(events[0]);
printf("--- 审计日志示例 ---\n");
for (int i = 0; i < n; i++) {
print_event(&events[i]);
}
printf("\n--- 审计规则 ---\n");
printf("监控文件:\n");
printf(" auditctl -w /etc/passwd -p wa\n");
printf(" 监控写入和属性修改\n\n");
printf("监控系统调用:\n");
printf(" auditctl -a always,exit -F arch=b64 -S open\n");
printf(" 监控所有 open 调用\n\n");
printf("监控用户:\n");
printf(" auditctl -a always,exit -F uid=0\n");
printf(" 监控 root 操作\n\n");
printf("--- 搜索日志 ---\n");
printf("按时间:\n");
printf(" ausearch -ts today\n\n");
printf("按用户:\n");
printf(" ausearch -ui 0\n\n");
printf("按事件:\n");
printf(" ausearch -m USER_AUTH\n\n");
printf("按文件:\n");
printf(" ausearch -f /etc/passwd\n\n");
printf("--- 审计报告 ---\n");
printf("aureport:\n");
printf(" --auth — 认证报告\n");
printf(" --login — 登录报告\n");
printf(" --file — 文件报告\n");
printf(" --syscall — 系统调用报告\n\n");
printf("--- 用途 ---\n");
printf("安全合规:\n");
printf(" PCI DSS — 支付卡行业\n");
printf(" HIPAA — 医疗行业\n\n");
printf("事件调查:\n");
printf(" 入侵分析\n");
printf(" 时间线重建\n\n");
printf("策略监控:\n");
printf(" SELinux 拒绝\n");
printf(" 违规行为\n");
return 0;
}二
林小源沿着回廊继续前行,审计修士跟在他身旁。
"你的规则太多了,"林小源看着墙上密密麻麻的日志,"如果每个系统调用都记录,日志会爆掉吧?"
审计修士停下脚步,神情变得严肃:"这就是规则设计的艺术。规则太宽,日志淹没真正重要的事件。规则太窄,可能遗漏关键线索。"
他从竹简中抽出一页,上面写着三条规则:
"-w /etc/passwd -p wa——只监控密码文件的写入和属性修改。-a always,exit -F uid=0——只监控 root 用户的操作。规则要精确,像筛子一样过滤噪音。"
"所以 ausearch 和 aureport 是你的搜索工具?"
"对。ausearch -ts today 按时间搜索,ausearch -ui 0 按用户搜索,ausearch -f /etc/passwd 按文件搜索。aureport 生成汇总报告——认证报告、登录报告、文件报告。调查入侵时,这些工具就是你的眼睛。"
三
回廊的尽头是一扇通往外部的门。门上刻着两行大字:PCI DSS、HIPAA。
"合规,"审计修士站在门前,"很多安全标准要求审计日志。支付卡行业要求记录所有数据访问,医疗行业要求记录所有患者数据的操作。没有审计日志,就拿不到合规认证。"
林小源推开门,外面是一片广阔的平原。远处有几座城池,城墙上飘着不同的旗帜——支付、医疗、政府。
"审计不只是技术问题,"他说,"它是法律和信任的基础。"
审计修士点了点头:"记住:审计不阻止攻击,它只记录攻击。但没有审计,你甚至不知道自己被攻击了。日志是安全事件调查的第一现场——时间线、证据链、归因分析,全都建立在审计日志之上。"
林小源回头看了一眼那条回廊。墙壁上的文字仍在不断增长——每一秒都有新的事件被记录。审计是一双不知疲倦的眼睛,从不眨眼,从不遗忘。
道藏笔记
内核启示
审计不阻止攻击,它只记录——谁在什么时候做了什么。SYSCALL 记系统调用,PATH 记文件路径,EXECVE 记程序执行,USER_AUTH 记认证尝试。规则设计是门艺术:太宽日志爆炸,太窄遗漏关键线索。auditctl -w /etc/passwd -p wa 只监控密码文件的写入和属性修改,-a always,exit -F uid=0 只监控 root 操作。
出事了怎么查?ausearch -ts today 按时间搜,ausearch -ui 0 按用户搜,ausearch -f /etc/passwd 按文件搜。aureport 生成汇总报告。PCI DSS、HIPAA 这些合规标准都要求审计日志——没有日志就拿不到认证,更别说入侵后的时间线重建了。
审计是眼睛——记录一切,无所遗漏。
审计之试
审计日志中记录系统调用行为时,本章出现的审计事件类型是什么?