> For the complete documentation index, see [llms.txt](https://book.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://book.bsdcn.org/di-28-zhang-an-quan-shen-ji/di-28.1-jie-an-quan-shi-jian-shen-ji.md).

# 28.1 安全事件审计

进程记账记录每条命令的执行信息，可用于追踪入侵途径。

## 进程记账

进程记账是安全手段之一，管理员可借此追踪系统资源用量及其在不同用户间的分配，监控系统，并可在最低限度上追踪用户执行的命令。

进程记账有利有弊。优势是可追溯入侵至入侵点；弊端在于产生海量日志，对磁盘空间要求较高。

### 启用和使用进程记账

启用进程记账前，需执行：

```sh
# service accounting enable
# service accounting start
```

记账信息存储于 **/var/account** 目录，首次启动记账服务时按需自动创建。这些文件包含敏感信息，记录了所有用户执行过的每条命令。默认目录权限为 `0750`（`drwxr-x---`，属主 root，属组 wheel），即仅 root 与 wheel 组成员可访问；记账文件默认权限为 `0640`（`rw-r-----`）。如果需进一步限制仅 root 可访问，可将 **/var/account** 目录权限改为 `700`。

启用后，记账即开始跟踪 CPU 信息、已执行命令等。所有记账日志均为二进制格式，须经 `sa` 查看。不加选项执行时，`sa` 打印每位用户的调用次数、总经过时间（分钟）、总 CPU 时间与用户时间（分钟）及平均 I/O 操作次数等信息。

要显示用户执行的命令，使用 `lastcomm`。

例如，此命令打印 `trhodes` 在 `ttyp1` 终端上所有 `ls` 的使用记录：

```sh
# lastcomm ls trhodes ttyp1
```

## 安全事件审计概述

FreeBSD 操作系统支持安全事件审计。事件审计可对各类安全系统事件做可靠、精细、可配置的日志记录，包含登录、配置变更、文件与网络访问。这些日志可用于实时监控、入侵检测及事后分析。FreeBSD 实现了 Sun 发布的 Basic Security Module（BSM）API 及文件格式，与 Solaris 与 macOS 审计实现互通。

```sh
系统事件（登录、文件访问等）
   │
   │  内核审计
   ▼
审计记录（BSM 格式）
   │
   │  auditd 守护进程
   ▼
审计跟踪文件（/var/audit）
   │
   ├── praudit：转换为文本
   ├── auditreduce：筛选精简
   └── auditpipe：实时监控
```

本节重点介绍事件审计的安装与配置，阐释审计策略，并提供一个审计配置示例。

审计设施存在一些已知局限性。并非所有安全系统事件均可审计，且部分登录机制（如基于 Xorg 的显示管理器和第三方守护进程）无法正确为用户登录会话配置审计。

安全事件审计设施可生成极详细的系统活动日志。繁忙系统若配置为高细节级别，跟踪文件数据量可能极其庞大，某些配置下每周可超过数 GB。管理员应考虑高数据量审计配置对磁盘空间的需求。例如，可能需要为 **/var/audit** 分配专用文件系统，避免写满后影响其他文件系统。

### 安全事件审计关键术语

以下术语与安全事件审计相关：

* **事件（event）**：可审计事件即审计子系统能够记录的任何事件。安全事件示例包括创建文件、建立网络连接或用户登录。事件分“有归属”（attributable，可追溯至已认证用户）和“无归属”（non-attributable）两类。无归属事件例如认证前发生的错误密码尝试等。
* **类（class）**：一组命名相关事件，用于选择表达式。常用事件类包括“文件创建”（fc）、“执行”（ex）和“登录\_注销”（lo）。
* **记录（record）**：描述安全事件的审计日志条目。记录包括事件类型、执行主体（用户）信息、日期时间、涉及的对象或参数，以及成功或失败条件。
* **跟踪（trail）**：由一系列描述安全事件的审计记录组成的日志文件。跟踪大致按事件完成时间排列。仅授权进程可向审计跟踪提交记录。
* **选择表达式（selection expression）**：一个字符串，包含前缀列表和审计事件类名称，用于匹配事件。
* **预选择（preselection）**：系统确定管理员关注哪些事件的过程。预选择配置使用一系列选择表达式，确定对哪些用户审计哪些事件类，以及同时适用于已认证和未认证进程的全局设置。
* **精简（reduction）**：从现有审计跟踪中筛选记录以供保存、打印或分析的过程；同样也是从审计跟踪中移除不需要的审计记录的过程。管理员可借助精简实施审计数据保存策略。例如，详细审计跟踪可保留一个月，之后可精简跟踪，仅保留登录信息以供归档。

### 审计配置

事件审计的用户空间支持已随 FreeBSD 基础系统安装。GENERIC 内核默认提供内核支持，启用 auditd：

```sh
# service auditd enable
```

随后启动审计守护进程：

```sh
# service auditd start
```

使用定制内核的用户，必须在其配置文件中加入：

```sh
options	AUDIT
```

#### 事件选择表达式

选择表达式用于审计配置，确定应审计的事件。表达式包含待匹配的事件类列表，从左至右求值，合并两个表达式即前后拼接。

以下汇总了默认审计事件类：

| 类名  | 描述     | 操作                                                                            |
| --- | ------ | ----------------------------------------------------------------------------- |
| all | 全部     | 匹配所有事件类。                                                                      |
| aa  | 认证与授权  |                                                                               |
| ad  | 管理     | 面向系统整体的管理操作。                                                                  |
| ap  | 应用程序   | 应用程序定义的操作。                                                                    |
| cl  | 文件关闭   | 审计对 `close` 系统调用的调用。                                                          |
| ex  | 执行     | 审计程序执行。命令行参数和环境变量的审计通过 audit\_control 中的 `policy` 设置，使用 `argv` 和 `envv` 参数控制。 |
| fa  | 文件属性访问 | 审计对象属性的访问，如 stat(1) 和 pathconf(2)。                                            |
| fc  | 文件创建   | 审计文件创建相关事件。                                                                   |
| fd  | 文件删除   | 审计文件删除相关事件。                                                                   |
| fm  | 文件属性修改 | 审计文件属性修改相关事件，如 chown(8)、chflags(1) 和 flock(2)。                                |
| fr  | 文件读取   | 审计读取数据或为读取而打开文件的事件。                                                           |
| fw  | 文件写入   | 审计写入数据或写入/修改文件的事件。                                                            |
| io  | ioctl  | 审计 `ioctl` 系统调用的使用。                                                           |
| ip  | 进程间通信  | 审计各种形式的进程间通信，包括 POSIX 管道和 System V IPC 操作。                                    |
| lo  | 登录\_注销 | 审计登录和注销事件。                                                                    |
| na  | 无归属    | 审计无归属事件。                                                                      |
| no  | 无效类    | 不匹配任何审计事件。                                                                    |
| nt  | 网络     | 审计与网络操作相关的事件，如 connect(2) 和 accept(2)。                                        |
| ot  | 其他     | 审计其他杂项事件。                                                                     |
| pc  | 进程     | 审计进程操作，如 exec(3) 和 exit(3)。                                                   |

可修改配置文件 **/etc/security/audit\_class** 和 **/etc/security/audit\_event** 自定义上述审计事件类。

每个审计事件类可附带前缀，表示匹配成功或失败的操作，以及该条目为该类及类型增加还是移除匹配。审计事件类前缀汇总如下：

| 前缀 | 操作                  |
| -- | ------------------- |
| +  | 审计该类中成功的事件。         |
| -  | 审计该类中失败的事件。         |
| ^  | 既不审计该类中成功也不审计失败的事件。 |
| ^+ | 不审计该类中成功的事件。        |
| ^- | 不审计该类中失败的事件。        |

如果没有前缀，该事件成功与失败实例均受审计。

以下示例选择字符串选择成功和失败的登录/注销事件，但仅选择成功的执行事件：

```sh
lo,+ex
```

#### 配置文件

安全事件审计的以下配置文件位于路径 **/etc/security** 中：

```sh
/etc/security
			├── audit_control   -> 控制审计子系统
			├── audit_class     -> 审计类定义
			├── audit_event     -> 系统审计事件
			├── audit_user      -> 用户特定的审计要求
			└── audit_warn      -> 警告消息脚本
```

| 文件                               | 说明                                                                 |
| -------------------------------- | ------------------------------------------------------------------ |
| **/etc/security/audit\_control** | 控制审计子系统的各方面，如默认审计类、审计日志卷上保留的最小磁盘空间以及最大审计跟踪大小                       |
| **/etc/security/audit\_class**   | 包含审计类定义                                                            |
| **/etc/security/audit\_event**   | 系统审计事件的文本名称与描述，以及每个事件所属的类列表                                        |
| **/etc/security/audit\_user**    | 用户特定的审计要求，在登录时与全局默认值合并                                             |
| **/etc/security/audit\_warn**    | 由 auditd 使用的可自定义 shell 脚本，用于在异常情况下生成警告消息，例如审计记录空间即将耗尽或审计跟踪文件已完成轮替时 |

审计配置文件应谨慎编辑和维护，配置错误可能造成事件日志记录失当。

多数情况下，管理员仅需修改 **/etc/security/audit\_control** 和 **/etc/security/audit\_user**。前者控制系统级审计属性与策略，后者可按用户精细调整审计。

**audit\_control 文件**

可在 **/etc/security/audit\_control** 文件中指定审计子系统的若干默认值：

```ini
dir:/var/audit
dist:off
flags:lo,aa
minfree:5
naflags:lo,aa
policy:cnt,argv
filesz:2M
expire-after:10M
```

以上是基本系统中 **/etc/security/audit\_control** 文件的默认值，其源代码位于 **contrib/openbsm/etc/audit\_control**。

作用解释：

| 条目             | 作用             | 说明                                                                 |
| -------------- | -------------- | ------------------------------------------------------------------ |
| `dir`          | 审计日志目录         | 设定一个或多个审计日志存储目录；如果有多个，则按顺序依次写满后切换；通常建议使用独立文件系统以避免写满影响其他系统组件。       |
| `dist`         | 分发（硬链接）        | 设为 `on` 或 `yes` 时，在 **/var/audit/dist** 中为所有审计跟踪文件创建硬链接。           |
| `flags`        | 默认预选择掩码（有归属事件） | 定义系统范围内“有归属事件”的默认审计类；例如登录/注销成功与失败、认证与授权等事件。                        |
| `minfree`      | 最小空闲空间         | 指定审计日志所在文件系统允许的最小剩余空间百分比。                                          |
| `naflags`      | 无归属事件掩码        | 指定“无归属事件”应审计的类别，例如登录/注销过程及认证与授权。                                   |
| `policy`       | 审计策略           | 以逗号分隔的策略标志列表；`cnt` 表示审计失败时系统继续运行（推荐），`argv` 表示记录 execve(2) 的命令行参数。 |
| `filesz`       | 跟踪文件大小限制       | 指定单个审计跟踪文件自动终止并轮替前的最大大小；`0` 表示禁用自动轮替；小于 512k 的值会被忽略并记录日志。          |
| `expire-after` | 日志过期策略         | 指定审计日志文件的到期时间，到期后自动删除。                                             |

**audit\_user 文件**

管理员可在 **/etc/security/audit\_user** 文件中为特定用户指定更多审计要求。

每行以两个字段为用户配置审计：

* `alwaysaudit` 字段指定始终对该用户审计的事件集
* `neveraudit` 字段指定始终不对该用户审计的事件集。

**audit\_user** 文件默认值如下：

```ini
root:lo:no
```

以下示例条目为 `root` 用户审计登录/注销事件和成功的命令执行，为 `www` 用户审计文件创建和成功的命令执行。配合默认 audit\_control 时，`root` 的 `lo` 条目多余，`www` 的登录/注销事件也会受审计。

```ini
root:lo,+ex:no
www:fc,+ex:no
```

### 处理审计跟踪

由于审计跟踪以 BSM 二进制格式存储，FreeBSD 提供了若干内置工具用于修改或转换为文本。要将跟踪文件转换为简易文本格式，可使用 `praudit`。

要精简审计跟踪文件以供分析、归档或打印，可使用 `auditreduce`。此工具支持多种选择参数：事件类型、事件类、用户、事件日期或时间，以及操作所涉文件路径或对象。例如，以纯文本形式转储指定审计日志的全部内容：

```sh
# praudit /var/audit/审计日志
```

其中 **审计日志** 为要转储的审计日志。

审计跟踪由一系列审计记录组成，每条记录由若干令牌（token）构成，`praudit` 按顺序每行打印一个。

每个令牌均属特定类型，例如 `header`（审计记录头）或 `path`（名称查找产生的文件路径）。

以下为一条 `execve` 事件的示例：

```ini
header,133,10,execve(2),0,Mon Sep 25 15:58:03 2006, + 384 msec
exec arg,finger,doug
path,/usr/bin/finger
attribute,555,root,wheel,90,24918,104944
subject,robert,root,wheel,root,wheel,38439,38032,42086,128.232.9.100
return,success,0
trailer,133
```

此审计记录表示一次成功的 `execve` 调用，执行了 `finger doug` 命令。

解释：

* `exec arg` 令牌包含 shell 传递给内核的已处理命令行。
* `path` 令牌持有内核查找到的可执行文件路径。
* `attribute` 令牌描述该二进制文件，含文件模式。
* `subject` 令牌存储审计用户 ID、有效用户 ID 和组 ID、真实用户 ID 和组 ID、进程 ID、会话 ID、端口 ID 以及登录地址。

> **注意**
>
> 审计用户 ID 与真实用户 ID 不同，因用户 `robert` 执行此命令前已切换至 `root` 账户，但命令仍以原始认证用户审计。

* `return` 令牌指示执行成功，`trailer` 结束该记录。

由于审计日志可能异常庞大，可使用 `auditreduce` 选取记录子集。以下示例选取审计日志文件中（AUDITFILE 为占位符，需替换为实际文件名，如 `20240521140528.not_terminated`）为用户 `trhodes` 产生的所有审计记录：

```sh
# auditreduce -u trhodes /var/audit/AUDITFILE | praudit
```

`audit` 组默认为空，因此仅 `root` 可读 **/var/audit** 中的审计跟踪；将用户加入 `audit` 组可授予审计审阅权限。

审计日志包含敏感信息，因此建议审慎授予审计审阅权限。

#### 使用审计管道进行实时监控

审计管道为可克隆伪设备，应用程序可借此接入实时审计记录流，主要面向入侵检测和系统监控程序开发者。审计管道设备也为管理员提供了便捷的实时监控手段，不受审计跟踪文件所有权或日志轮替中断事件流的影响。要追踪实时审计事件流：

```sh
# praudit /dev/auditpipe
```

默认情况下，审计管道设备节点仅可由 `root` 用户访问。要使 `audit` 组成员也能访问，可在 **/etc/devfs.rules** 中添加一条 `devfs` 规则：

```sh
add path 'auditpipe*' mode 0440 group audit
```

审计事件容易产生反馈循环：每查看一条审计事件便会生成更多审计事件。例如，如果审计了所有网络 I/O，并通过 SSH 会话运行 `praudit`，则会持续高速产生审计事件流，因为打印的每个事件都会触发新事件。因此建议在无细粒度 I/O 审计的会话中运行 `praudit`（接审计管道设备）。

#### 轮替与压缩审计跟踪文件

审计跟踪由内核写入，审计守护进程 auditd 管理。管理员不应使用 newsyslog.conf(5) 等工具直接轮替审计日志，应改用 `audit` 关闭审计、重新配置并轮替日志。以下命令令审计守护进程创建新审计日志，并通知内核切换。旧日志终止后重命名，可供管理员后续处理：

```sh
# audit -n
```

如果 auditd 当前未运行，此命令失败并报错。

在 **/etc/crontab** 中加入以下行，每 12 小时执行一次轮替：

```sh
0     */12       *       *       *       root    /usr/sbin/audit -n
```

保存 **/etc/crontab** 文件后此更改即生效。

基于文件大小自动轮替审计跟踪文件可通过 audit\_control 中的 `filesz` 实现。

审计跟踪文件可能变得极大，审计守护进程关闭跟踪后，通常需压缩或归档。audit\_warn 脚本可针对各类审计事件执行自定义操作，包括跟踪在轮替时正常终止的情形。例如，可在 **/etc/security/audit\_warn** 中添加以下内容，以在关闭时压缩审计跟踪：

```sh
#
# Compress audit trail files on close.
#
if [ "$1" = closefile ]; then
        gzip -9 $2
fi
```

其他归档操作可能包含复制跟踪文件至中央服务器、删除旧跟踪文件，或精简审计跟踪以移除不需要的记录。此脚本仅在审计跟踪文件正常终止时运行，非正常关机遗留的未终止跟踪则不触发。

## 课后习题

1. 启用进程记账功能后，在系统中执行一系列操作（创建文件、运行命令、切换用户），使用 `lastcomm` 导出记录并解释各字段含义，找出对应的记录条目。
2. 使用 `sa -u` 生成按用户统计的命令使用报告，分析“cpu”和“re”两列的含义差异，说明为何这两个值通常不相等。
3. 讨论进程记账可能带来的隐私问题及多用户系统中的应对措施。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://book.bsdcn.org/di-28-zhang-an-quan-shen-ji/di-28.1-jie-an-quan-shi-jian-shen-ji.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
