Linux 基础体系 · 第 85/85 篇。示例面向现代主流 Linux 发行版;发行版差异、权限和生产风险会明确说明。
Linux 主机事件响应:隔离、取证、时间线、证据保全和恢复
Linux 主机事件响应,是在怀疑主机遭到入侵、恶意程序执行、凭据泄露、越权操作或异常配置变更后,对主机进行控制影响、保存证据、重建事实、修复根因并安全恢复服务的过程。
它不是“登录服务器后执行几条检查命令”,也不是简单地删除恶意文件。响应人员必须同时处理两个目标:
- 降低继续危害的概率:阻断横向移动、数据外传和持久化。
- 尽量保留能够证明事实的证据:包括内存、进程、网络连接、日志、文件元数据和磁盘内容。
这两个目标经常冲突。例如,立即关机会阻止攻击者继续操作,却会丢失内存中的进程、密钥和网络状态;直接删除恶意程序可能暂时止血,却会破坏分析所需的样本和文件时间信息。因此,事件响应本质上是在不确定信息下进行的有证据约束的状态转换。
一、先建立响应模型:你要回答哪些问题
一次完整的主机事件响应,至少要回答以下问题:
- 发生了什么:是误报、配置错误、凭据滥用,还是主机已经被执行了未授权代码?
- 何时发生:攻击者首次进入、获得权限、建立持久化、访问数据和离开的时间分别是什么?
- 从哪里进入:SSH 密钥、密码、暴露服务、漏洞、供应链软件,还是已有主机上的凭据?
- 攻击者做了什么:执行过哪些程序,读取或修改过哪些文件,访问过哪些网络目标?
- 影响边界在哪里:只有一台主机,还是同一凭据、镜像、密钥或软件版本导致多台主机受影响?
- 现在是否仍在继续:是否有活动进程、反连、定时任务、systemd 服务、内核模块或其他持久化机制?
- 恢复后如何证明风险下降:根因是否修复,凭据是否轮换,服务是否经过验证,监控和审计是否恢复?
可以把主机状态抽象为:
其中:
- :进程和内核对象状态;
- :网络连接、监听端口和路由状态;
- :文件系统及其元数据;
- :日志、审计和命令记录;
- :内存中的凭据、进程映像和临时数据;
- :配置、凭据、信任关系和外部依赖。
隔离、取证、恢复不是对某一个文件操作,而是改变这个状态向量。比如:
- 断开网络主要改变 ,但可能触发服务退出并改变 ;
- 关机会清除 ,并使部分 、 不可再观察;
- 删除恶意文件会改变 ,同时破坏原始证据;
- 轮换密钥改变 ,但不能证明过去没有被使用。
因此,所有操作都应记录“操作前状态、操作动作、操作后状态和执行人”。
二、证据、线索和结论不是同一个概念
1. 证据的三个层次
响应过程中常见的材料可以分为三个层次:
- 原始数据:例如磁盘镜像、内存采集结果、原始日志文件。
- 派生数据:例如从镜像中导出的文件、从日志生成的时间线、从审计日志筛选出的事件。
- 分析结论:例如“攻击者通过某个 SSH 密钥登录后执行了下载命令”。
派生数据和结论都必须能够追溯到原始数据。否则,后续复核时无法判断筛选是否遗漏、时区是否转换错误、工具是否修改了文件。
2. 证据不等于“看起来可疑”
以下现象只能作为线索,不能单独证明入侵:
/tmp中出现二进制文件;- 进程名与常见系统进程相似;
- SSH 日志中出现海外 IP;
- 某个文件的修改时间很新;
ps看到一个未知进程;auditd记录了某次执行。
例如,/tmp 中的文件可能是编译器、安装程序或应用临时文件;海外 IP 可能是公司出口、VPN 或云厂商;文件修改时间可能由解包、恢复备份或时间戳伪造造成。
更可靠的判断通常需要多个独立来源相互印证:
这里的交集不是数学上必须完全相同,而是指不同证据源对同一事件在时间、主体和动作上相互支持。
三、响应前的决策:先隔离还是先取证
1. 影响优先级
可用以下因素决定动作顺序:
| 情况 | 首要动作 |
|---|---|
| 正在进行数据外传、勒索、破坏或横向移动 | 立即隔离网络,必要时停止服务 |
| 仅发现可疑文件,未发现活动连接 | 先进行有限的易失数据采集,再隔离 |
| 内存中可能存在攻击者控制、密钥或反连 | 优先可信环境采集内存或网络隔离后采集 |
| 业务为高可用集群,存在健康副本 | 先从流量层摘除受影响节点,再保留节点取证 |
| 机器是唯一生产实例,停止会造成重大损失 | 先执行最小破坏性的隔离和采集,并同步升级决策 |
这里的“先取证”不是无限期观察。攻击者继续活动会改变现场、删除日志、加密数据,延迟本身也是证据损失。
2. 隔离不等于关机
隔离是阻止主机继续与不可信系统通信,常见层次包括:
- 流量层隔离:从负载均衡器、服务发现或路由中摘除主机。
- 网络层隔离:安全组、交换机端口、VLAN、ACL 或防火墙限制出入站。
- 主机层隔离:在主机上设置防火墙规则或停止特定服务。
- 电源层隔离:关机、断电或通过带外管理停止实例。
优先使用主机外部的隔离手段。被攻陷的主机上的防火墙命令可能被拦截、替换或触发异常;同时,修改规则本身也会改变现场。
一个常见状态流如下:
stateDiagram-v2
[*] --> Normal: 正常运行
Normal --> Suspected: 告警或异常线索
Suspected --> Contained: 网络/服务隔离
Suspected --> VolatileCapture: 需要保留易失数据
VolatileCapture --> Contained: 采集完成
Contained --> DiskAcquisition: 磁盘或文件级取证
DiskAcquisition --> Analysis: 时间线与根因分析
Analysis --> Rebuild: 无法可信清理或高权限失陷
Analysis --> Remediate: 根因和持久化已明确
Remediate --> Validate: 修复、轮换、验证
Rebuild --> Validate: 重装并恢复
Validate --> Monitor: 灰度上线与加强监控
Monitor --> Closed: 复盘与留存
关键点是:Contained 和 VolatileCapture 可以根据风险先后调整,但不能把“已隔离”误认为“已清除”。
3. 示例:主机级隔离的风险
以下命令在某些 Linux 系统上可阻止所有新建连接:
sudo nft list ruleset
sudo nft add table inet ir
sudo nft 'add chain inet ir input { type filter hook input priority -100; policy drop; }'
sudo nft 'add chain inet ir output { type filter hook output priority -100; policy drop; }'
它们的前提和风险是:
- 系统使用
nftables,并且当前用户有CAP_NET_ADMIN或 root 权限; - 可能中断 SSH、监控、存储和取证传输;
- 规则写入内核后会改变网络状态;
- 如果没有带外管理,可能把响应人员锁在主机外;
- 某些发行版通过 firewalld、ufw 或云代理管理规则,直接修改 nftables 可能被覆盖。
因此,生产环境通常应先使用云安全组、交换机 ACL 或负载均衡器隔离。若必须本机操作,应先记录当前规则,并准备带外恢复路径:
sudo nft list ruleset > /safe/ir/nft-before.txt
date -u --iso-8601=ns | tee -a /safe/ir/actions.log
“安全目录”应位于可信的外部存储或只写采集介质;如果 /safe/ir 仍在被调查的本机上,它不能自动成为可信保存位置。
四、易失数据取证:先保存会消失的事实
1. 什么是易失数据
易失数据是关机、进程退出、网络变化或内核状态更新后可能丢失或改变的数据,典型包括:
- 当前时间和时区;
- 进程树及命令行;
- 加载的内核模块;
- 网络接口、路由、监听端口和连接;
- 登录会话;
/proc中的进程环境和打开文件;- 内存中的凭据、临时脚本和进程映像;
- 临时目录中的未落盘内容。
采集顺序通常是从变化最快、最容易消失的数据开始,再采集稳定数据:
- 记录采集人员、主机标识、UTC 时间;
- 采集网络连接和进程;
- 采集登录会话、挂载点、内核模块;
- 采集关键进程的
/proc信息; - 视风险和工具能力采集内存;
- 再进行文件和日志采集。
2. 使用可信工具和绝对路径
如果攻击者修改了 PATH、替换了 ps、ss 或 ls,直接执行命令的结果可能不可信。可以先记录命令路径和校验值:
command -v ps ss ip ls date sha256sum
type -a ps ss ip
sha256sum /usr/bin/ps /usr/bin/ss /usr/sbin/ip /usr/bin/ls
路径因发行版而异,不能假设所有程序都位于相同目录。更高可信度的做法是:
- 从可信救援介质启动;
- 通过带外管理或虚拟机快照获取数据;
- 在隔离环境中挂载磁盘只读分析;
- 将采集结果直接写入外部介质或通过受控链路传出。
3. 一个最小的现场采集脚本
下面脚本用于快速记录状态,不是完整内存取证,也不能替代磁盘镜像。它应从可信路径执行,并把输出写到外部挂载点。
#!/usr/bin/env bash
set -u
OUT=${1:?usage: $0 /external/ir-dir}
mkdir -p -- "$OUT"
exec > >(tee -a "$OUT/collection.log") 2>&1
echo "=== collection ==="
date -u --iso-8601=ns
hostnamectl 2>/dev/null || hostname
id
cat /etc/os-release 2>/dev/null || true
cat /proc/sys/kernel/random/boot_id 2>/dev/null || true
echo "=== processes ==="
/usr/bin/ps -e -o pid,ppid,user,lstart,etimes,stat,cmd --forest
echo "=== network ==="
/usr/sbin/ss -lntup
/usr/sbin/ss -antup
/usr/sbin/ip addr
/usr/sbin/ip route
echo "=== sessions ==="
/usr/bin/w
/usr/bin/who
/usr/bin/last -Fai | head -100
echo "=== mounts and kernel ==="
/usr/bin/findmnt -R
/usr/bin/lsmod 2>/dev/null || true
echo "=== important persistence ==="
systemctl list-unit-files --state=enabled --no-pager 2>/dev/null || true
systemctl list-timers --all --no-pager 2>/dev/null || true
逐步说明:
date -u --iso-8601=ns记录 UTC 纳秒时间,避免后续混淆本地时区;boot_id用于区分本次启动与上次启动;ps的lstart是进程启动时间,etimes是已运行秒数,两者可相互校验;ss -lntup展示监听 TCP 端口及关联进程,但显示进程信息通常需要 root;ss -antup展示已建立和其他 TCP 状态,连接可能在采集期间变化;systemctl只反映 systemd 管理范围,不能覆盖所有持久化方式;findmnt比仅查看/etc/fstab更接近当前实际挂载状态。
ps、ss 和 systemctl 的结果都是实时快照,不具有天然不可篡改性。脚本输出应立即计算哈希并复制到可信位置:
find /external/ir-dir -type f -print0 |
sort -z |
xargs -0 sha256sum > /external/ir-dir/SHA256SUMS
如果采集目录位于被调查主机本地,攻击者仍可能修改它;哈希只能证明“之后读取到的文件与哈希一致”,不能证明文件最初来自可信状态。
4. 内存采集的边界
内存采集可以发现:
- 注入到进程内存中的代码;
- 未落盘的恶意脚本;
- SSH agent、TLS、数据库等进程中的敏感材料;
- 已删除但仍被进程打开的内容;
- 反射加载的共享库或异常映射。
但内存采集本身会改变内存,采集工具需要加载驱动、创建进程或通过内核接口读取数据。现代内核、虚拟机和云环境对内存获取的支持差异很大,不能仅凭“Linux 支持”推断某个工具一定可用。
如果业务和证据等级要求较高,应优先选择:
- 云平台提供的内存快照或取证能力;
- 虚拟机管理器或带外系统的快照;
- 与目标内核、架构和发行版明确兼容的采集工具;
- 可信救援环境。
不要在没有验证兼容性的情况下随意加载第三方内核模块。内核模块会影响系统稳定性,也可能被攻击者利用来隐藏对象。
五、持久化与入口分析:不要只搜恶意文件
攻击者要在重启后继续存在,通常需要持久化;但“没有发现持久化”不等于“没有被入侵”,因为攻击可能只使用短期会话或外部控制器。
1. systemd 持久化
现代发行版大量使用 systemd。应同时检查:
systemctl list-unit-files --all --no-pager
systemctl list-timers --all --no-pager
systemctl --failed --no-pager
find /etc/systemd /run/systemd /usr/lib/systemd /lib/systemd \
-type f -printf '%TY-%Tm-%Td %TH:%TM:%TS %u:%g %m %p\n' 2>/dev/null
需要进一步查看异常单元的完整内容:
systemctl cat suspicious.service
systemctl show suspicious.service \
-p FragmentPath -p DropInPaths -p ExecStart -p User -p Environment
systemctl cat 显示的单元可能来自 /etc/systemd/system、/run/systemd/system 或发行版提供的目录;systemctl show 能暴露 drop-in 配置和环境变量。仅检查 /etc/systemd/system 会漏掉运行时单元和其他来源。
2. 定时任务和用户级持久化
sudo crontab -l
for u in $(getent passwd | awk -F: '$3 >= 0 {print $1}'); do
echo "=== $u ==="
sudo crontab -u "$u" -l 2>/dev/null || true
done
find /etc/cron* /var/spool/cron /var/spool/cron/crontabs \
-type f -ls 2>/dev/null
systemctl --user list-timers --all --no-pager 2>/dev/null
用户级 systemd 服务的实际位置和可见性取决于用户是否有运行中的 user manager。root 检查不到某些用户会话中的状态,因此需要结合用户会话、loginctl 和文件系统检查。
3. SSH 入口和凭据
OpenSSH 事件分析通常需要同时查看:
- 认证成功和失败记录;
sshd的启动、配置错误和会话关闭记录;/etc/ssh/sshd_config及其Include文件;- 用户的
~/.ssh/authorized_keys; - 主机密钥、跳板机和 agent 使用情况;
sudo、su和后续命令执行记录。
日志位置取决于发行版和日志服务。例如,Debian 系常见 /var/log/auth.log,RHEL 系常见 /var/log/secure,systemd journal 可能包含同类记录:
sudo journalctl -u ssh.service --since "2025-01-01" --no-pager
sudo journalctl -u sshd.service --since "2025-01-01" --no-pager
sudo journalctl _COMM=sshd --since "2025-01-01" --no-pager
服务单元名不统一,ssh.service 和 sshd.service 不能硬编码为唯一答案。可以先查:
systemctl list-units --type=service '*ssh*' --all
检查配置时不要只看主文件:
sudo sshd -T
sudo sshd -T -C user=alice,addr=203.0.113.10,host=example
sudo grep -RInE '^(Include|PermitRootLogin|PasswordAuthentication|AuthorizedKeysFile|AllowUsers|AllowGroups|Match)' \
/etc/ssh/sshd_config /etc/ssh/sshd_config.d 2>/dev/null
sshd -T 输出的是解析后的有效配置,通常比直接阅读配置文件更可靠;-C 会应用连接条件相关的 Match 规则。执行配置检查前,应确认当前 OpenSSH 版本支持所用参数,并避免在未验证语法的情况下重启 SSH:
sudo sshd -t
成功时通常没有输出,非零退出码表示配置错误。修改前应保留现有管理会话和带外通道,因为错误配置可能导致新的 SSH 连接全部失败。OpenSSH 的具体选项和语义应以目标版本的官方手册为准。
4. 文件系统中的常见持久化入口
检查范围至少包括:
/etc/ld.so.preload;/etc/profile、/etc/profile.d、用户 shell 启动文件;/etc/sudoers和/etc/sudoers.d;- setuid/setgid 文件;
- 内核模块和 DKMS 配置;
rc.local、init 脚本;- 容器、编排平台和镜像启动配置;
- 应用自身的插件、钩子和上传目录。
例如,寻找近期改变的 setuid 文件:
sudo find / -xdev -type f \( -perm -4000 -o -perm -2000 \) \
-printf '%TY-%Tm-%Td %TH:%TM:%TS %u:%g %m %p\n' 2>/dev/null |
sort
这只能发现当前文件系统中仍存在的对象。攻击者可以恢复原权限、删除文件,或者把恶意代码注入已有可信进程,因此不能把“未发现异常文件”当成清白证明。
六、审计日志和系统日志:它们记录什么,不能证明什么
1. journald、传统日志和 auditd 的差异
三类数据常被混淆:
- journald:systemd 日志服务,收集内核、服务标准输出和 syslog 等内容;可配置为内存保存或持久化到磁盘。
- 传统 syslog 文件:例如
/var/log/auth.log、/var/log/messages,通常由 rsyslog 或其他守护进程写入。 - auditd:Linux Audit 子系统的用户空间管理组件,接收内核审计事件并写入审计日志,适合记录身份、系统调用相关行为、文件访问和权限变化等。
它们的可靠性、字段、丢失模式和检索方式不同。日志服务停止、磁盘满、规则缺失、时钟错误和攻击者拥有 root 权限,都可能导致日志不完整。
2. auditd 事件不是“一行一件事”
一个审计事件可能由多条记录组成,共享同一个事件标识,例如:
type=SYSCALL msg=audit(1700000000.123:456): ...
type=EXECVE msg=audit(1700000000.123:456): ...
type=PATH msg=audit(1700000000.123:456): ...
type=PROCTITLE msg=audit(1700000000.123:456): ...
其中:
1700000000.123是事件时间;456是该主机审计序列中的事件编号;SYSCALL说明系统调用上下文;EXECVE保存执行参数的编码或字段;PATH描述涉及的路径;PROCTITLE可能记录进程标题。
必须按事件 ID 聚合后再解释,不能把每一行当成独立操作。
检索示例:
sudo ausearch -m USER_LOGIN,USER_START,EXECVE,AVC \
--start today --interpret
sudo ausearch -ts 2025-01-15 00:00:00 -te 2025-01-15 23:59:59 \
-ua 1001 --interpret
sudo aureport --auth --success
sudo aureport --exec --summary
ausearch 的参数和可用事件类型受 audit 工具版本影响;--interpret 会将 UID、系统调用号等转换为更易读的形式,但分析时仍应保留原始记录。
3. auditd 规则的因果边界
例如,规则:
sudo auditctl -w /etc/passwd -p wa -k identity-files
表示对 /etc/passwd 设置写入和属性变化监控,并使用 identity-files 作为检索键。它可以帮助发现文件何时被修改、由哪个进程触发,但有几个边界:
- 规则加载前发生的事件不会被补记;
- 审计日志丢失时无法恢复;
- 规则本身可能被删除、修改或禁用;
- 只监控
/etc/passwd不代表监控了所有身份数据库和认证后端; - 文件访问审计不能自动证明文件内容是什么;
- 过宽规则可能造成性能和日志容量压力。
查询:
sudo ausearch -k identity-files --interpret
生产系统应结合 auditd 规则设计、性能评估和合规留存要求。Linux 内核安全文档说明的是内核安全机制和接口边界,而具体发行版的 auditd 默认配置、日志轮换和服务管理仍需以发行版文档为准。
4. “日志里没有记录”不是“没有发生”
缺失记录可能来自:
- 审计规则未覆盖;
- journald 使用了 volatile 存储;
- 日志轮换已覆盖旧文件;
- 磁盘满导致写入失败;
- 网络日志接收端不可达;
- 事件发生在日志服务启动前;
- 攻击者停止或篡改了日志服务;
- 系统时间错误,检索范围不正确。
因此应先检查日志系统健康状态和时间范围:
journalctl --disk-usage
journalctl --verify
systemctl status systemd-journald auditd --no-pager
timedatectl
df -h /var /var/log
journalctl --verify 能检查 journal 文件结构,但通过校验不等于内容未被有权限者修改;df 只能说明当前容量,不能证明过去没有丢日志。
七、时间线:把不同时间语义放到同一条轴上
1. Linux 文件时间不是一个时间
常见文件时间包括:
- mtime:文件内容最后修改时间;
- ctime:inode 状态最后改变时间,例如权限、所有者、链接数或内容变化;
- atime:最后访问时间,但可能因挂载选项、文件系统和内核策略而不更新;
- btime/crtime:创建时间,在部分文件系统和工具中可用,不是所有环境都支持。
查看示例:
stat /path/to/file
stat -c 'path=%n size=%s mode=%A uid=%u gid=%g mtime=%y ctime=%z atime=%x birth=%w' \
/path/to/file
ctime 不是“创建时间”。攻击者修改权限或所有者时,ctime 可能变化;复制文件时,原始 mtime 可能被保留,而新的 inode 具有不同 ctime。
2. 事件时间、观察时间和记录时间
时间线至少应区分:
- 事件时间:动作实际发生的时间;
- 记录时间:日志系统写入记录的时间;
- 观察时间:响应人员执行命令看到状态的时间;
- 文件时间:文件系统记录的 mtime、ctime 等;
- 外部时间:防火墙、身份系统、云平台或远程日志中的时间。
若主机时钟偏移 ,主机日志时间 与可信外部时间 的关系可写成:
但 可能随时间变化,不能简单对整台主机永久加一个常数。应检查 NTP/chrony 状态、启动时间和外部日志:
timedatectl
chronyc tracking 2>/dev/null || true
chronyc sources -v 2>/dev/null || true
cat /proc/uptime
3. 时间线的构造方法
一个可复核的时间线应包含以下字段:
| 字段 | 含义 |
|---|---|
| normalized_time | 转换到统一时区后的时间 |
| source_time | 原始数据中的时间 |
| source | journal、audit、SSH、文件系统、EDR 等 |
| subject | 用户、UID、PID、进程或远端 IP |
| action | 登录、执行、连接、修改、删除 |
| object | 文件、服务、端口、目标主机 |
| confidence | 证据强度及缺失说明 |
构造步骤:
- 保留所有源文件的原始副本;
- 记录每个源文件的 SHA-256;
- 解析不同格式的时间,但保留原始行;
- 统一时区和时间精度;
- 根据 PID、UID、审计事件 ID、SSH 会话和远端 IP 关联事件;
- 标记时间矛盾,而不是强行排序;
- 把“没有证据”与“证明没有发生”分开记录。
一个简化算例:
10:00:01Z:SSH 日志记录用户alice从203.0.113.10登录;10:00:04Z:auditd 记录 UID 1001 执行/usr/bin/curl;10:00:05Z:文件/tmp/x的 mtime 为10:00:05Z;10:00:07Z:防火墙记录主机向198.51.100.20:443发出连接。
这可以形成一条候选链:
但不能仅凭 mtime 证明 /tmp/x 一定由该次 curl 生成,因为另一个进程可能同时修改了它。需要进一步检查 audit PATH、进程父子关系、文件内容哈希和外部网络日志。
4. 反例:时间线看似合理但结论错误
攻击者可以:
- 使用
touch修改 mtime; - 通过
faketime或系统时间设置影响程序记录; - 删除日志后恢复部分内容;
- 利用时区错误制造“错位”的登录和执行记录;
- 复用合法账号,使用户名看似正常。
所以时间线是事件关联模型,不是自动生成的真相。高可信结论应说明哪些字段直接观察到,哪些关系是推断得到的。
八、证据保全:哈希只能保证完整性的一部分
1. 完整性、真实性和可追溯性
证据保全包含至少三个性质:
- 完整性:保存后的内容没有被改变;
- 真实性:能够说明内容来自哪个主机、哪个时间和哪个采集过程;
- 可追溯性:能够说明谁在何时以什么方式接触、复制、分析过它。
SHA-256 可用于完整性校验:
其中 是证据字节序列, 是摘要。重新计算得到同一摘要,说明两次输入在密码学碰撞假设下相同;它不能说明第一次采集时 就是可信内容,也不能证明采集过程没有遗漏。
2. 保全记录示例
每个证据对象应有类似记录:
evidence_id: host-a-disk-001
source: /dev/nvme0n1
acquired_at_utc: 2025-01-15T10:20:30.123456Z
collector: responder-07
method: hardware write-blocked imaging
sha256: ...
storage: evidence-store/2025/host-a/
access: read-only
实际环境还应记录:
- 主机名、实例 ID、磁盘设备和分区;
- 是否使用只读挂载或硬件写保护;
- 采集工具及版本;
- 采集失败、重试和截断信息;
- 证据转交和访问人员;
- 存储系统的权限、保留期和审计记录。
3. 磁盘级采集与文件级采集
磁盘级镜像保存分区结构、未分配空间、删除文件残留和文件系统元数据,适合高可信调查,但耗时、占用空间大,并需要足够的外部存储。
文件级采集更快,适合早期响应或容量受限场景,但通常无法恢复删除文件、Slack 空间和完整文件系统上下文。
在可信救援系统中,典型流程可能是:
sudo blockdev --setro /dev/nvme0n1
sudo dd if=/dev/nvme0n1 of=/mnt/evidence/host-a-nvme0n1.img \
bs=16M iflag=fullblock status=progress conv=noerror,sync
sudo sha256sum /mnt/evidence/host-a-nvme0n1.img \
| tee /mnt/evidence/host-a-nvme0n1.img.sha256
前提和风险:
/mnt/evidence必须是容量足够的外部存储;blockdev --setro是内核层面的只读设置,但不能替代硬件写保护;conv=noerror,sync会在读取错误时继续并填充数据,必须记录错误,否则分析者可能误以为镜像完整;- 对正在运行的根磁盘执行镜像可能得到跨时间点的不一致状态;
- 云盘快照、LVM 快照或存储阵列快照的语义由平台决定,不能自动等价于法证级静态镜像。
若只复制文件,应保留权限、所有者、符号链接和时间:
sudo tar --xattrs --acls --numeric-owner --one-file-system \
-cpf /mnt/evidence/etc-ssh.tar \
/etc/ssh /etc/sudoers /etc/sudoers.d
sudo sha256sum /mnt/evidence/etc-ssh.tar
tar 归档的是指定目录,不包含被删除的文件,也不能捕获当时所有进程状态;--one-file-system 可以避免跨入其他挂载点,但也可能漏掉位于独立分区的关键数据。
九、现场分析的安全顺序
分析时应避免在原始证据上直接修改。推荐分层:
- 原始证据只读保存;
- 制作工作副本;
- 在工作副本上解包、挂载和索引;
- 输出分析报告和派生证据;
- 对派生结果再次计算哈希。
挂载文件系统时应尽量只读:
sudo mount -o ro,noload /dev/mapper/vg-root /mnt/case/root
ro 防止常规写入,noload 对部分日志型文件系统可避免回放日志,但具体支持和语义与文件系统有关。不要在不知道文件系统类型的情况下套用参数:
lsblk -f
blkid /dev/mapper/vg-root
分析可疑二进制时,不要直接在生产主机执行。应使用隔离的沙箱或离线静态分析,并控制网络、权限和共享目录。读取恶意脚本本身通常是低风险的,但执行脚本、加载样本或调用其安装器可能触发破坏和外连。
十、恢复:重建信任,而不是只删除文件
1. 为什么高权限失陷通常倾向重装
当攻击者获得 root 或等价权限后,可能修改:
- 用户态工具;
- systemd、SSH 和日志配置;
- 内核模块;
- 动态链接器加载路径;
- 审计规则和日志;
- 启动过程;
- 容器运行时和镜像;
- 管理员的 SSH 密钥与凭据。
此时“执行 rm -f /tmp/malware”不能恢复信任。即使扫描工具没有发现恶意程序,也不能证明系统中没有隐藏后门。
因此,在以下情况中通常应优先重新部署干净系统:
- root 权限已确认或高度怀疑;
- 启动链、内核或系统工具可能被篡改;
- 关键日志缺失且无法解释;
- 无法确定攻击者停留范围;
- 主机可以由可信镜像和自动化配置快速替换。
2. 重建流程中的证据边界
应先完成必要的取证或保存快照,再重建。恢复数据时分离:
- 业务数据:数据库、对象、用户上传内容;
- 系统配置:服务配置、应用参数;
- 凭据材料:SSH 密钥、API token、数据库密码;
- 可执行内容:二进制、脚本、容器镜像和插件。
不能把原主机的 /etc、整个 home 目录或应用目录未经审查地复制回新系统,因为其中可能包含持久化机制。恢复过程应从可信来源重建系统包和配置,再逐项导入经过验证的数据。
3. 凭据轮换的范围
如果主机被入侵,应考虑轮换:
- 主机用户密码;
- SSH 用户密钥和
authorized_keys; - 主机密钥是否需要重新生成;
- 云访问密钥、实例角色或服务账号;
- 数据库密码;
- CI/CD token;
- TLS 私钥;
- 第三方 API token;
- 跳板机和 agent 中曾在该主机使用过的凭据。
轮换顺序要考虑依赖关系。先撤销攻击者可能继续使用的凭据,再为恢复系统发放最小权限的新凭据。仅修改主机上的 authorized_keys 不足以处理已经泄露的私钥,因为私钥副本可能存在于管理员电脑、备份、agent 或日志中。
4. 恢复验证
恢复后至少验证:
sudo sshd -t
sudo systemctl --failed --no-pager
sudo ss -lntup
sudo systemctl list-timers --all --no-pager
sudo auditctl -s 2>/dev/null || true
sudo journalctl -b --no-pager -p warning
还应进行:
- 从可信基线校验系统包和关键配置;
- 确认只开放预期端口;
- 验证日志持久化、远程转发和磁盘容量;
- 验证 auditd 规则实际加载;
- 验证时间同步;
- 验证备份可恢复且未被污染;
- 先灰度接入流量,再逐步扩大;
- 在一段观察期内提高身份、进程、出站连接和文件变更监控。
恢复不是“服务已启动”。服务能启动只说明进程可以运行,不说明根因已经修复,也不说明凭据没有继续暴露。
十一、常见失败路径及诊断方法
1. 先重启再调查
失败表现:重启后看不到恶意进程和网络连接,临时目录内容消失,内存证据丢失。
原因:关机改变了 、 和 ,同时可能触发日志轮换、临时文件清理和服务自动恢复。
改进:若没有正在造成严重损害,先完成最小易失数据采集;若必须立即重启,应记录决策原因、时间和业务影响,并保存外部网络与身份日志。
2. 直接删除可疑文件
失败表现:服务暂时恢复,但无法判断文件来源、内容和执行链。
原因:删除破坏了样本,文件仍可能被已运行进程持有,持久化入口也可能在其他位置。
改进:先复制、哈希和记录元数据,再隔离执行路径。若文件正在执行,可以先隔离进程的网络,再决定是否保存 /proc/<pid>/exe 和打开文件列表。
3. 只查 last 和 SSH 失败日志
失败表现:看不到攻击者,误判为“没有登录”。
原因:攻击者可能使用已有会话、服务账号、SSH agent、应用漏洞或本地提权;last 依赖 wtmp,记录也可能缺失或被清理。
改进:把 SSH 日志、sudo 日志、auditd、应用日志、网络流量和云身份日志关联起来。
4. 只看 mtime 判断攻击时间
失败表现:时间线与外部日志冲突,却仍以文件 mtime 为准。
原因:mtime 可被保留、修改或受时钟影响,不一定代表创建或执行时间。
改进:同时使用 ctime、audit PATH、进程执行记录、日志写入时间、文件内容关系和外部时间源,并明确置信度。
5. 在被攻陷主机上安装扫描器
失败表现:扫描器安装失败、结果异常,或安装动作覆盖了重要证据。
原因:软件包下载会产生网络和文件系统事件;恶意主机上的工具和内核可能不可信。
改进:优先使用可信救援系统、离线副本或外部 EDR;必须在线安装时记录安装包哈希、时间和变更,并把它视为现场修改。
6. 把哈希当成真实性证明
失败表现:报告中只有一个 SHA-256 值,却没有采集链路和原始来源。
原因:哈希只能验证输入字节是否一致,不能证明采集内容未被攻击者预先修改,也不能证明采集没有遗漏。
改进:结合只读采集、可信时间、外部存储、访问审计、工具版本和交接记录。
十二、把事件响应能力前移到生产体系
事件发生后能否重建事实,取决于平时是否保存了足够的独立数据源。生产运行手册至少应明确:
- 哪些主机启用持久化 journal;
- auditd 记录哪些身份、执行、权限和关键文件事件;
- 日志发送到哪里,网络中断时如何缓存;
- 日志保留多久,容量满时如何告警;
- 主机时钟如何同步,偏差多大时触发告警;
- 关键主机的可信基线是什么;
- 如何从负载均衡和网络侧隔离节点;
- 谁可以批准关机、重装和凭据轮换;
- 备份如何验证未被攻击者污染;
- 取证数据如何访问、保留和销毁。
auditd 规则、事件检索、性能和合规留存应单独进行容量设计:记录越多不一定越好,过宽规则可能增加系统负载并造成日志洪峰;记录太少则无法重建关键动作。需要根据威胁模型选择规则,并通过压测、丢失监控和远程留存验证实际效果。
最终,可靠的响应不是依赖某一条神奇命令,而是让以下链条可重复:
其中任何一步都应留下可审查记录。主机恢复上线只代表服务重新提供,不代表事件已经结束;只有当根因、信任关系、证据边界和后续监控都得到处理,响应才算完成。
系列导航与关联阅读
- 系列入口:Linux 完整学习路线:从内核与文件系统到网络、性能和生产运维
- 上一篇:Linux 补丁与发行版升级:安全更新、内核、重启、灰度和回滚
- 延伸:Linux auditd 审计:规则、事件、性能、检索和合规留存
- 延伸:Linux 生产运行手册:容量、变更、监控、应急和复盘
官方资料
本文依据 Linux 内核、systemd 与主流发行版官方文档重新梳理;正文与实验由 WR BLOG 编写。

评论
0 条讨论