再探 audit 审计机制

在文章如何审计 Linux 系统的操作行为中, 我们详细介绍了审计系统行为的几种方式, 以及对应的优缺点. 但是在 audit 方面介绍还不够深入, 缺乏实践使用的一些准则. 本文则对 audit 机制以及相关工具做更多的延申介绍, 主要包含以下几点:

auditd 工作机制

如何实现

备注: 部分内容参考如何审计 Linux 系统的操作行为.

auditd 主要由内核和用户空间两部分组成. 内核空间主要由 kauditd 组件支持, 目前主要的 Linux 发行版都会内置支持. 以 Linuxaudit 用户空间工具为例说明, 主要流程如下所示:

audit-invoke.png

备注: 更多见 audit 事件, 字段字典, Linux 系统调用. 用户空间侧一般仅关注 1300 ~ 1399 的类型事件;

audit 整体上为分离的架构, auditctl 可以控制 kauditd 生成记录的策略, kauditd 生成的记录事件会发送到 auditd 守护程序, audisp 可以消费 auditd 的记录到其它地方. 其主要的几个组件包含如下:

组件 说明
auditctl 配置 kauditd 事件的规则, 可以及时生效, 用户空间通常使用 auditctl 调整规则;
auditd audit 相关配置的加载, 日志落盘等都通过 auditd 守护程序实现, 同时也和 kauditd 交互;
audisp 与 auditd 通信, 将收到的记录信息发送到其它地方, 比如 syslog 中;
augenrules
ausearch
autrace
aureport
audit 提供的辅助分析工具;

过滤规则

snoopy 规则类似, 不希望审计可能包含的敏感信息命令时, 在使用的时候我们可以忽略一些条目:

### ignore common tools
-a never,exit -F arch=b64 -F exe=/usr/bin/redis-cli
-a never,exit -F arch=b64 -F exe=/usr/bin/mysql
-a never,exit -F arch=b64 -F exe=/usr/bin/mongo

### record system invoke
-a always,exit -F arch=b64 -S execve
-a always,exit -F arch=b32 -S execve
-a always,exit -F arch=b64 -S truncate,ftruncate,creat -F exit=-EACCES -F key=access
-a always,exit -F arch=b64 -S truncate,ftruncate,creat -F exit=-EPERM -F key=access

上述的 -EACCES, -EPERM 是仅在访问错误或权限错误的时候才记录.

系统默认的 auditd 输出信息相对晦涩, 需要二次解析处理:

type=SYSCALL msg=audit(1669631724.918:33310): arch=c000003e syscall=59 success=yes exit=0 a0=11abec0 a1=1288450 a2=12345f0 a3=7ffd90cca5a0 items=2 ppid=19123 pid=19399 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts2 ses=62194 comm="ip" exe="/usr/sbin/ip" key=(null)
type=EXECVE msg=audit(1669631724.918:33310): argc=2 a0="ip" a1="addr"

auditd 机制的延申

由于 auditd 的功能足够丰富, 市面上出现了很多基于 auditd 机制的工具, 相比 Linuxaudit 套件, 这些工具架构更简单:

audit-ext.png

这些工具等同实现了 auditdaudisp 两个组件的功能, 同时还增加了事件的解析功能, 补足了 audit 输出信息晦涩的不足. 另外 output 支持的也更多, 可以直接落盘或者发送到 es, kafka 等组件.

这些工具中, auditbeatelastic 公司产品 beats 中的一员, 周边生态丰富; hidswazuh 属于同类产品, 更侧重于安全分析和事件响应, 相比较 wazuh 更为活跃; go-audit 出现较早, 功能比较集中, 但活跃度不高.

下面则主要介绍 auditbeat, wazuhElkeid 这三类工具.

auditbeat 工作机制

功能说明

auditbeat(比如 7.17 版本) 对审计做了不少扩展, 有的功能 audit 虽然支持, 但是解析更耗资源, 相比定期检查等方式更轻量方便. 目前主要支持三大类的审计功能:

模块 功能 说明
auditd 兼容 Linux Audit 与 kauditd 交互, 消费收到的事件消息,比 audit 日志更易阅读;
File Integrity 文件完整性检查 定期(10s)遍历指定目录下的文件(/bin, /user 等), 保存文件哈希到 boltdb 中; 对比上报哈希值不同的文件信息;
System dataset:
host
login
package
process
socket
user
分别用来获取:
主机信息(ip, kernel, mac 等);
登录信息;
yum/deb 安装信息;
进程启停信息(同文件完整性, 定期(10s)检查);
tcp/udp 网络信息(数据可能很多);
用户创建删除信息;

上述的功能中, 有 3 点需要注意:

1. 定期执行意味着短时间运行的进程或文件可能监控不到;

2. 开启 socket 监控, 可能产生很多日志, 尤其在短连接很多的场景中;

3. auditbeat 提供了内存队列, 磁盘限额存储事件等特性, 防止事件太多造成不可控的影响;

备注: 和内核可能产生 kernel 死锁.

auditbeat 对日志信息做了额外的解析, 比起 audisp 更方便阅读:

auditbeat-info.png

过滤规则

可以参考 snoopy 规则, 做以下过滤:

processors:
  - add_host_metadata: ~
  - drop_event:
      when:
        or:
          - contains:
              process.title: "iptables -S"
          - contains:
              process.title: "telegraf --test"
          - contains:
              process.title: "redis-cli"
          - regexp:
              process.title: "mysql.*-p"
          - equals:
              user.name: "telegraf"
          - equals:
              process.executable: "/usr/sbin/crond"
          - equals:
              process.name: "consul-kv"
          - equals:
              process.name: "sadc"

wazuh 工作机制

功能说明

wazuh 工具整体上功能更全, 也更偏重于安全分析和事件响应, 架构方面主要包含 agentmanager 组件:

数据可以存储到官方指定的 opensearch(兼容 es), 其在此基础上实现了很多看板和数据分析. 不过也可以存储到 es, 但需要单独安装 kibana 插件;

wazuh-info.png

在上面架构中, agent 直接和 cluster 通信, 将搜集的信息发给 cluster 节点, cluster 节点落盘到日志文件, 最后通过 filebeat 消费到 es 集群中.

以下为 agent 主要的一些主要功能, 很多功能受 manager 端开关控制:

功能 说明
支持平台 支持 linux, windows, mac, unix
自动升级 有自动升级的机制;
数据搜集 linux - audit 机制, 自定义内核模块以及系统信息;
windows - auditing 规则和系统信息. auditing 功能不够多, 主要集中于数据的修改以及用户, 进程等;
系统调用 监控指定的系统调用, 仅支持 linux - 可能产生很多数据;
入侵检测 扫描主机发现可能的恶意软件, rootkit 和可疑行为, 同时检测隐藏的文件和进程;
日志分析 会获取系统日志或程序日志并发送到 server 端存储以供分析;
文件完整性检查 同 auditbeat, 定期检查保存哈希到 sqlite 中, 上报哈希变更的信息; 进程检查也类似;
漏洞扫描 定期获取本机软件详单和 server 端的 CVE 数据库交互,进而得到漏洞信息;
事件响应 可以对指定的事件作出动作响应, 比如修改 iptables, 删除用户, 执行指定命令等;
安全(云/容器) 结合各云厂商的安全 api, 来分析云主机的安全情况;

过滤规则

wauzh 通过搜集 audit.log 日志进而分析系统命令的执行, 参考 wazuh-audit, 不过 wazuh 主要以 audit 关键字进行区分, 如下所示:

# cat /var/ossec/etc/lists/audit-keys
audit-wazuh-w:write
audit-wazuh-r:read
audit-wazuh-a:attribute
audit-wazuh-x:execute
audit-wazuh-c:command

所以在创建 audit 过滤规则的时候需要通过 -k 选项添加对应的过滤标识, 如下所示:

### ignore common tools
-a never,exit -F arch=b64 -F exe=/usr/bin/redis-cli
-a never,exit -F arch=b64 -F exe=/usr/bin/mysql
-a never,exit -F arch=b64 -F exe=/usr/bin/mongo

-a always,exit -F arch=b64 -S execve -k audit-wazuh-x
-a always,exit -F arch=b32 -S execve -k audit-wazuh-x
-a always,exit -F arch=b64 -S truncate,ftruncate,creat -F exit=-EACCES -F key=access -k audit-wazuh-r
-a always,exit -F arch=b64 -S truncate,ftruncate,creat -F exit=-EPERM -F key=access -k audit-wazuh-r

备注: auditbeatwazuh 在审计方面是互斥的, wazuh 需要 auditd 服务, 消费日志 audit.log, auditbeat 则需要关闭 auditd 服务, 自己来接收消息.

Elkeid 工作机制

Elkeid 是字节出的一款入侵检测系统, 功能有点类似 wazuh, 不过它的机制有很大的不同, 如下所示:

elkeid-invoke.png

目前主要开源了 agent, driverRASP 几个组件, 通过源码编译时也出现了一些异常,比如缺少一些依赖说明, rasp 组件依赖太多等问题. 不过从这几个组件也能看出 Elkeid 的工作机制有很大的不同.

组件 功能说明
agent 插件及自定义插件管理;
系统信息, 日志数据的搜集;
和 server 端通信, 进行服务发现;
driver 主要用于搜集 kernel 数据, 包括:
hids_driver.lo 内核模块;
跟踪 io, bind, execve 系统调用, 通过 ptrace 实现;
rootkit 检测;
rasp 主要为进程运行时分析, 包括:
jvm - 通过 ASM 修改类的字节码, 跟踪堆栈和参数调用;
golang - 从 gopclntab 块中解析符号表, 再加入 hook api, 进而跟踪堆栈和参数调用;
php - 增加 hook 函数和 opcodes, 跟踪堆栈和参数调用;

driver 组件中, 主要通过 ptrace 和内核模块实现了内核空间的数据搜集, 这种方式对发行版的侵入很大, 通用性不够, 内核模块和内核版本也强绑定, 见 ko_list, 所以这种方式不适合我们线上使用.

其它工具

packetbeat 工作机制

功能说明

packetbeat 同样是 beats 的组件之一, 主要通过 pcap 抓包机制实时分析网络包, 不过比起 auditbeat 的 socket 功能, packetbeat 的功能更丰富, 解析报文支持的协议也更多, 包括:

ICMP, DHCP, DNS, HTTP
AMQP, Cassandra, MySQL, PostgreSQL, Redis, MongoDB, Memcached
NFS, TLS, Thrift

备注: 同 auditbeat, packetbeat 也提供了内存队列, 磁盘限额存储事件等特性, 防止事件太多造成不可控的影响.

过滤规则

过滤规则同样可以使用 drop_event 语法, 如下所示:

processors:
  - add_host_metadata: ~
  - drop_event:
      when:
        or:
          - network:
              source.ip: private
          - network:
              destination.ip: '192.168.1.0/24'

filebeat 工作机制

功能说明

filebeat 同样是 beats 的组件之一, 主要用来搜集文件内容. 目前通过模块化的方式支持并解析了所有常见的系统和软件日志, 包含:

syslog, audit, secure, haproxy, iis, tomcat, nginx, kafka, zeek
mysql, postgresql, mssql, oracle, mongodb, redis, elasticsearch ...

开启模块并设置字段建立索引模板后, 各模块的 mapping 映射信息会自动同步到 es.

过滤规则

由于 filebeat 的目的很单一, 主要为搜集日志, 如果仅考虑系统运维层面, 可以考虑使用以下配置:

filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /var/log/telegraf/telegraf*.log
  fields:
    logmon: telegraf

- type: log
  enable: true
  paths:
    - /var/log/filebeat/filebeat*
  fields:
    logmon: filebeat

- type: log
  enable: true
  paths:
    - /data/scripts/logs/*.log
  fields:
    logmon: scripts

filebeat.config.modules:
  reload.enabled: true
  reload.period: 15s
  path: /etc/filebeat/modules.d/*.yml

并开启以下模块:

mysql, redis, system

各工具对比

上述工具各有优缺点, 不过应用到线上需要慎重考虑. 对各工具的优劣对比如下:

特点 snoopy auditbeat wazuh packetbeat filebeat Elkeid
应用领域 命令审计 命令审计 安全分析 网络分析 日志收集 安全分析
是否全平台
部署简单
方便升级维护
是否活跃
影响应用成都 中高 轻微 轻微 中高 轻微 中高
影响内核程度(可能死锁, 崩溃等) 轻微 中等 中等 轻微 轻微 中高
过滤规则 事后 事后 事后 事后 事前事后
是否适合线上

过滤规则中, 事后表示无论设置什么规则, 都是先由工具接收所有事件后再应用规则. 这意味着如果系统调用的事件很多, 无论是否应用规则, 内核 kauditd 的压力都可能增大.

是否适合线上, wazuh 为感叹号, 因为他的审计依赖 audit 套件, 并消费 audit.log 日志. 另外不少事件响应功能也不是线上所需要的.

容量预估

以测试环境的一台 centos 7 主机为例说明, 该主机相对空闲, 仅运行两台 MySQLtelegraf 监控程序, 单日的数据量大致如下:

auditbeat 测试

编号 功能 数据量
1 开启 execve, 开启 file_integrity, login, process, user, socket 2.5 GB
2 开启 execve, 开启 file_integrity, login, process, user 200 MB
3 同 2, 开启过滤规则 40 MB

filebeat 测试

编号 功能 数据量
1 仅监控运维层面的日志信息 8 MB

wauzh 测试

编号 功能 数据量
1 默认配置, 不设置 audit 规则 25 MB
2 设置 auditctl 规则 接近 auditbeat 的规则 2, 3

packetbeat 测试

未做测试, 主要受配置和系统上运行服务的影响. 网络请求越多, 单日数据量越大. 但上限受内存队列和磁盘限额的调整.

总结: 从上述的数据量来看, auditbeat 的规则 2, 3, filebeatwauzh 的数据量相对合适, 比如 1 千台主机产生的数据量(单日 40G ~ 200G 左右).

细看 auditbeat

根据上述的对比, auditebat 更适合实际的使用情况, 如果需要应用到线上, 我们需要对 auditbeat 有更多的了解.

系统调用的进与出

对每个 Linux系统调用而言, 比如以简单的 open 调用, 对应到内核中为 sys_open 函数:

asmlinkage long sys_open(const char __user *filename,
                int flags, umode_t mode);

如果需要跟踪 open 调用, 可以在 sys_open 函数执行前后两个点来获取上下文信息, 不过为了尽量避免影响函数的执行, 通常都会选择执行完后, 即在 sys_open 函数 exit 的时候开始记录信息.

对应到 auditctl 规则, 可以表示如下:

-a never,exit   # 系统调用 exit 的时候永不记录
-a always,exit  # 总在系统调用 exit 的时候记录

audit 事件

由于可以跟踪很多系统调用, 这些系统函数及其参数信息就可以组成很多可以审计的事件(用户空间 1300 ~ 1399), 比如常见的下面事件:

AUDIT_PATH
AUDIT_CWD
AUDIT_EXECVE
AUDIT_PROCTITLE

事件配合进程和线程的上下文信息即可获取到我们需要的审计信息.

规则测试

auditbeat 规则

# 仅测试环境
-a always,exit -F arch=b64 -S open -S sendfile -S truncate -S ftruncate -S chdir -S fchdir -S rename -S mkdir -S rmdir -S creat -S unlink -S readlink -S openat -S mkdirat -S unlinkat -S renameat -S readlinkat -F key=note

-a always,exit -F arch=b64 -S mount,umount2 -F auid!=-1 -F key=mount
-a always,exit -F arch=b32 -S mount,umount,umount2 -F auid!=-1 -F key=mount

-w /etc/sysconfig/iptables -p wa -k iptables

-w /etc/sysctl.conf -p wa -k sysctl
-w /etc/sysctl.d -p wa -k sysctl

-w /sbin/auditctl -p x -k audittools
-w /sbin/auditd -p x -k audittools
-w /usr/sbin/auditd -p x -k audittools
-w /usr/sbin/augenrules -p x -k audittools

-w /etc/group -p wa -k identity
-w /etc/passwd -p wa -k identity
-w /etc/gshadow -p rwxa -k identity
-w /etc/shadow -p rwxa -k identity

-w /etc/sudoers -p wa -k actions
-w /etc/sudoers.d -p wa -k actions
-w /usr/bin/passwd -p x -k passwd_modification
-w /usr/sbin/groupadd -p x -k group_modification
-w /usr/sbin/groupmod -p x -k group_modification
-w /usr/sbin/addgroup -p x -k group_modification
-w /usr/sbin/useradd -p x -k user_modification
-w /usr/sbin/userdel -p x -k user_modification
-w /usr/sbin/usermod -p x -k user_modification
-w /usr/sbin/adduser -p x -k user_modification
-w /etc/ssh/sshd_config -p rwxa -k sshd
-w /etc/ssh/sshd_config.d -p rwxa -k sshd

# 常见命令打标签, 方便监控
-w /usr/sbin/iptables -p x -k note_cmd
-w /usr/bin/zip -p x -k note_cmd
-w /usr/bin/gzip -p x -k note_cmd
-w /usr/bin/bzip2 -p x -k note_cmd
-w /usr/bin/lz4 -p x -k note_cmd
-w /usr/bin/zstd -p x -k note_cmd
-w /usr/bin/tar -p x -k note_cmd
-w /usr/bin/cp -p x -k note_cmd
-w /usr/bin/mv -p x -k note_cmd
-w /usr/bin/wget -p x -k note_cmd
-w /usr/bin/curl -p x -k note_cmd
-w /usr/bin/scp -p x -k note_cmd
-w /usr/bin/rsync -p x -k note_cmd
-w /usr/bin/ftp -p x -k note_cmd
-w /usr/bin/sftp -p x -k note_cmd
-w /usr/bin/hexdump -p x -k note_cmd
-w /usr/bin/xxd -p x -k note_cmd
-w /usr/bin/ln -p x -k note_cmd

-a always,exit -F arch=b64 -S truncate,ftruncate,creat -F exit=-EACCES -F key=access
-a always,exit -F arch=b64 -S truncate,ftruncate,creat -F exit=-EPERM -F key=access

-a always,exit -F arch=b64 -S bind -S execve -S connect
-a always,exit -F arch=b32 -S bind -S execve -S connect

connect 仅测试环境.

文件完整性规则

- module: file_integrity
  paths:
  - /bin
  - /usr/bin
  - /sbin
  - /usr/sbin
  - /etc

  max_file_size: 3000 MiB

系统规则

- module: system
  datasets:
    - login
    - process
    - user

  state.period: 8h
  process.hash.max_file_size: 1000 MiB

  user.detect_password_changes: true
  login.wtmp_file_pattern: /var/log/wtmp*
  login.btmp_file_pattern: /var/log/btmp*

标签及自定义规则

tags: ["xxxxx"]         # 标识信息

fields:
  logmon: auditbeat     # 自定义字段, 方便 logstash 等工具判断处理

audit 事件忽略

为避免产生过多的日志, 整体上按以下规则忽略事件:

没有 uid 的行为;
忽略 telegraf/zabbix 等监控行为相关的事件;
忽略 crond 相关的事件;
忽略 mysql, redis-cli 等相关的正常事件;

对应 auditbeat 的规则语法如下示例:

  - drop_event:
      when:
        or:
          - equals: # old-uid is not set(-1)
              auditd.summary.actor.primary: "unset"
          - contains:
              process.title: "iptables -S"
          - contains:
              process.args: "-tnlp"
          - equals:
              process.name: "redis-cli"
          - equals:
              process.executable: "mysql"
          - equals:
              process.executable: "mongo"
          - equals:
              user.saved.name: "telegraf"
          - equals:
              user.name: "telegraf"

报警策略

规则报警可以集中在 audit key 信息, 对应 auditbeat 规则的 -k 属性.

总结

在上述的介绍中, 可以看到不通工具都有很强的功能定位行, 而且越偏底层, 带给内核的风险就越大, 所以具体实践中很难将这些功能都集成到一个工具中, 但是借助这些工具又能加强我们的基础能力. 所以如果从功能和风险因素角度来看:

功能 风险
记录执行的命令;
系统文件完整性检查;
进程启停检查;
系统和脚本日志搜集;
所有信息结合 CMDB,可搜索, 可视化, 可告警;
是否对内核, 应用产生影响;
是否加重系统压力;
出现问题是否方便部署升级;
是否会产生安全问题; <是否产生日志过多, 加重存储负担>;

部署多个组件可以将风险都分担开, 不至于一个组件出问题对系统产生很大的影响. 可以参考下图:

+-----------------+
|     Host A      |
|  +-----------+  |
|  | telegraf  |  |           +--------------------+                              +-----------------+
|  +-----------+  |           |   victoriaMetrics  |----------------------------> |  metric monitor |
|  | filebeat  |--+------->   +--------------------+        +---------------+     +-----------------+
|  +-----------+  |           |  logstash / kafak  |------> | elasticsearch |---> |  audit  monitor |
|  | auditbeat |  |           +--------------------+        +---------------+     |  log    monitor |
|  +-----------+  |                                                               +-----------------+
|                 |
+-----------------+

事实上 telegraf 也支持 elasticsearch, 只不过对监控的指标数据而言, victoriametrics 的压缩比更高, 且 alert 组件的功能也更完善. logstash 和 kafka 可以视具体情况而定. 如果需要加工信息, 比如去除一些多余字段, 增加一些 CMDB, 使用人等字段可以考虑使用 kafka, 由消费程序统一处理.

telegraf + filebeat + auditbeat 组合来覆盖系统层所有的监控, 可以很好的满足我们在审计方面的需求. 如果是采用云产品或其它商业产品, 相信在功能方面也是相对分层的, 毕竟几个组件功能都很庞大, 与底层的交互也较深, 也更有利于生产环境的操作维护.