分析 Linux 系统证据
使用时机
- 调查受入侵的 Linux 服务器或工作站时
- 识别持久化机制(cron、systemd、SSH 密钥)时
- 通过 shell 历史和认证日志追踪用户活动时
- 事件响应中确定基于 Linux 的入侵范围时
- 检测 rootkit、后门和未授权修改时
前提条件
- 具有取证镜像或 Linux 系统的只读实时访问权限
- 了解 Linux 文件系统层次标准 (FHS)
- 熟悉常见 Linux 日志位置 (/var/log/)
- 工具: chkrootkit、rkhunter、AIDE、auditd 日志
- 熟悉 systemd、cron 和 PAM 配置
- 用于完整证据收集的 root 访问权限
工作流程
步骤 1: 挂载并收集系统证据
# 以只读方式挂载取证镜像
mount -o ro,loop,offset=$((2048*512)) /cases/case-2024-001/images/linux_evidence.dd /mnt/evidence
# 创建收集目录
mkdir -p /cases/case-2024-001/linux/{logs,config,users,persistence,network}
# 收集认证日志
cp /mnt/evidence/var/log/auth.log* /cases/case-2024-001/linux/logs/
cp /mnt/evidence/var/log/secure* /cases/case-2024-001/linux/logs/
cp /mnt/evidence/var/log/syslog* /cases/case-2024-001/linux/logs/
cp /mnt/evidence/var/log/kern.log* /cases/case-2024-001/linux/logs/
cp /mnt/evidence/var/log/audit/audit.log* /cases/case-2024-001/linux/logs/
cp /mnt/evidence/var/log/wtmp /cases/case-2024-001/linux/logs/
cp /mnt/evidence/var/log/btmp /cases/case-2024-001/linux/logs/
cp /mnt/evidence/var/log/lastlog /cases/case-2024-001/linux/logs/
cp /mnt/evidence/var/log/faillog /cases/case-2024-001/linux/logs/
# 收集用户证据
for user_dir in /mnt/evidence/home/*/; do
username=$(basename "$user_dir")
mkdir -p /cases/case-2024-001/linux/users/$username
cp "$user_dir"/.bash_history /cases/case-2024-001/linux/users/$username/ 2>/dev/null
cp "$user_dir"/.zsh_history /cases/case-2024-001/linux/users/$username/ 2>/dev/null
cp -r "$user_dir"/.ssh/ /cases/case-2024-001/linux/users/$username/ 2>/dev/null
cp "$user_dir"/.bashrc /cases/case-2024-001/linux/users/$username/ 2>/dev/null
cp "$user_dir"/.profile /cases/case-2024-001/linux/users/$username/ 2>/dev/null
cp "$user_dir"/.viminfo /cases/case-2024-001/linux/users/$username/ 2>/dev/null
cp "$user_dir"/.wget-hsts /cases/case-2024-001/linux/users/$username/ 2>/dev/null
cp "$user_dir"/.python_history /cases/case-2024-001/linux/users/$username/ 2>/dev/null
done
# 收集 root 用户证据
cp /mnt/evidence/root/.bash_history /cases/case-2024-001/linux/users/root/ 2>/dev/null
cp -r /mnt/evidence/root/.ssh/ /cases/case-2024-001/linux/users/root/ 2>/dev/null
# 收集系统配置
cp /mnt/evidence/etc/passwd /cases/case-2024-001/linux/config/
cp /mnt/evidence/etc/shadow /cases/case-2024-001/linux/config/
cp /mnt/evidence/etc/group /cases/case-2024-001/linux/config/
cp /mnt/evidence/etc/sudoers /cases/case-2024-001/linux/config/
cp -r /mnt/evidence/etc/sudoers.d/ /cases/case-2024-001/linux/config/
cp /mnt/evidence/etc/hosts /cases/case-2024-001/linux/config/
cp /mnt/evidence/etc/resolv.conf /cases/case-2024-001/linux/config/
cp -r /mnt/evidence/etc/ssh/ /cases/case-2024-001/linux/config/
步骤 2: 分析用户账户和认证
# 分析用户账户异常
python3 << 'PYEOF'
print("=== 用户账户分析 ===\n")
# 解析 /etc/passwd
with open('/cases/case-2024-001/linux/config/passwd') as f:
for line in f:
parts = line.strip().split(':')
if len(parts) >= 7:
username, _, uid, gid, comment, home, shell = parts[0], parts[1], int(parts[2]), int(parts[3]), parts[4], parts[5], parts[6]
# 标记 UID 0(root 等效)的账户
if uid == 0 and username != 'root':
print(f" 告警: UID 0 账户: {username} (shell: {shell})")
# 标记不应拥有登录 shell 的账户
if shell not in ('/bin/false', '/usr/sbin/nologin', '/bin/sync') and uid >= 1000:
print(f" 用户: {username} (UID:{uid}, Shell:{shell}, Home:{home})")
# 标记拥有登录 shell 的系统账户
if uid < 1000 and uid > 0 and shell in ('/bin/bash', '/bin/sh', '/bin/zsh'):
print(f" 警告: 系统账户拥有 shell: {username} (UID:{uid}, Shell:{shell})")
# 解析 /etc/shadow 获取账户状态
print("\n=== 密码状态 ===")
with open('/cases/case-2024-001/linux/config/shadow') as f:
for line in f:
parts = line.strip().split(':')
if len(parts) >= 3:
username = parts[0]
pwd_hash = parts[1]
last_change = parts[2]
if pwd_hash and pwd_hash not in ('*', '!', '!!', ''):
hash_type = '未知'
if pwd_hash.startswith('$6$'): hash_type = 'SHA-512'
elif pwd_hash.startswith('$5$'): hash_type = 'SHA-256'
elif pwd_hash.startswith('$y$'): hash_type = 'yescrypt'
elif pwd_hash.startswith('$1$'): hash_type = 'MD5 (弱)'
print(f" {username}: {hash_type} 哈希, 最后更改: 第 {last_change} 天")
PYEOF
# 分析登录历史
last -f /cases/case-2024-001/linux/logs/wtmp > /cases/case-2024-001/linux/analysis/login_history.txt
lastb -f /cases/case-2024-001/linux/logs/btmp > /cases/case-2024-001/linux/analysis/failed_logins.txt 2>/dev/null
步骤 3: 检查持久化机制
# 检查所有用户的 cron 作业
echo "=== CRON 作业 ===" > /cases/case-2024-001/linux/persistence/cron_analysis.txt
# 系统 cron
for cronfile in /mnt/evidence/etc/crontab /mnt/evidence/etc/cron.d/*; do
echo "--- $cronfile ---" >> /cases/case-2024-001/linux/persistence/cron_analysis.txt
cat "$cronfile" 2>/dev/null >> /cases/case-2024-001/linux/persistence/cron_analysis.txt
echo "" >> /cases/case-2024-001/linux/persistence/cron_analysis.txt
done
# 用户 crontab
for cronfile in /mnt/evidence/var/spool/cron/crontabs/*; do
echo "--- 用户 crontab: $(basename $cronfile) ---" >> /cases/case-2024-001/linux/persistence/cron_analysis.txt
cat "$cronfile" 2>/dev/null >> /cases/case-2024-001/linux/persistence/cron_analysis.txt
echo "" >> /cases/case-2024-001/linux/persistence/cron_analysis.txt
done
# 检查 systemd 服务持久化
echo "=== SYSTEMD 服务 ===" > /cases/case-2024-001/linux/persistence/systemd_analysis.txt
find /mnt/evidence/etc/systemd/system/ -name "*.service" -newer /mnt/evidence/etc/os-release \
>> /cases/case-2024-001/linux/persistence/systemd_analysis.txt
for svc in /mnt/evidence/etc/systemd/system/*.service; do
echo "--- $(basename $svc) ---" >> /cases/case-2024-001/linux/persistence/systemd_analysis.txt
cat "$svc" >> /cases/case-2024-001/linux/persistence/systemd_analysis.txt
echo "" >> /cases/case-2024-001/linux/persistence/systemd_analysis.txt
done
# 检查授权 SSH 密钥(后门检测)
echo "=== SSH 授权密钥 ===" > /cases/case-2024-001/linux/persistence/ssh_keys.txt
find /mnt/evidence/home/ /mnt/evidence/root/ -name "authorized_keys" -exec sh -c \
'echo "--- {} ---"; cat {}; echo ""' \; >> /cases/case-2024-001/linux/persistence/ssh_keys.txt
# 检查 rc.local 和 init 脚本
cat /mnt/evidence/etc/rc.local 2>/dev/null > /cases/case-2024-001/linux/persistence/rc_local.txt
# 检查 /etc/profile.d/ 中的登录触发脚本
ls -la /mnt/evidence/etc/profile.d/ > /cases/case-2024-001/linux/persistence/profile_scripts.txt
# 检查 LD_PRELOAD 劫持
grep -r "LD_PRELOAD" /mnt/evidence/etc/ 2>/dev/null > /cases/case-2024-001/linux/persistence/ld_preload.txt
cat /mnt/evidence/etc/ld.so.preload 2>/dev/null >> /cases/case-2024-001/linux/persistence/ld_preload.txt
步骤 4: 分析 Shell 历史和命令执行
# 分析每个用户的 bash 历史
python3 << 'PYEOF'
import os, glob
print("=== SHELL 历史分析 ===\n")
suspicious_commands = [
'wget', 'curl', 'nc ', 'ncat', 'netcat', 'python -c', 'python3 -c',
'perl -e', 'base64', 'chmod 777', 'chmod +s', '/dev/tcp', '/dev/udp',
'nmap', 'masscan', 'hydra', 'john', 'hashcat', 'passwd', 'useradd',
'iptables -F', 'ufw disable', 'history -c', 'rm -rf /', 'dd if=',
'crontab', 'at ', 'systemctl enable', 'ssh-keygen', 'scp ', 'rsync',
'tar czf', 'zip -r', 'openssl enc', 'gpg --encrypt', 'shred',
'chattr', 'setfacl', 'awk', '/tmp/', '/dev/shm/'
]
for hist_file in glob.glob('/cases/case-2024-001/linux/users/*/.bash_history'):
username = hist_file.split('/')[-2]
print(f"用户: {username}")
with open(hist_file, 'r', errors='ignore') as f:
lines = f.readlines()
print(f" 命令总数: {len(lines)}")
flagged = []
for i, line in enumerate(lines):
line = line.strip()
for cmd in suspicious_commands:
if cmd in line.lower():
flagged.append((i+1, line))
break
if flagged:
print(f" 可疑命令: {len(flagged)}")
for lineno, cmd in flagged:
print(f" 第 {lineno} 行: {cmd[:120]}")
print()
PYEOF
步骤 5: 检查 Rootkit 和修改过的二进制文件
# 检查已知 rootkit 指示器
# 将系统二进制哈希值与已知正确值比较
find /mnt/evidence/usr/bin/ /mnt/evidence/usr/sbin/ /mnt/evidence/bin/ /mnt/evidence/sbin/ \
-type f -executable -exec sha256sum {} \; > /cases/case-2024-001/linux/analysis/binary_hashes.txt
# 检查 SUID/SGID 二进制文件(潜在的权限提升)
find /mnt/evidence/ -perm -4000 -type f 2>/dev/null > /cases/case-2024-001/linux/analysis/suid_files.txt
find /mnt/evidence/ -perm -2000 -type f 2>/dev/null > /cases/case-2024-001/linux/analysis/sgid_files.txt
# 检查 /tmp 和 /dev/shm 中的可疑文件
find /mnt/evidence/tmp/ /mnt/evidence/dev/shm/ -type f 2>/dev/null \
-exec file {} \; > /cases/case-2024-001/linux/analysis/tmp_files.txt
# 检查隐藏文件和目录
find /mnt/evidence/ -name ".*" -not -path "*/\.." -type f 2>/dev/null | \
head -100 > /cases/case-2024-001/linux/analysis/hidden_files.txt
# 检查内核模块
ls -la /mnt/evidence/lib/modules/$(ls /mnt/evidence/lib/modules/ | head -1)/extra/ 2>/dev/null \
> /cases/case-2024-001/linux/analysis/extra_modules.txt
# 检查修改过的 PAM 配置(认证后门)
diff /mnt/evidence/etc/pam.d/ /cases/baseline/pam.d/ 2>/dev/null \
> /cases/case-2024-001/linux/analysis/pam_changes.txt
关键概念
| 概念 | 描述 |
|---|---|
| /var/log/auth.log | Debian/Ubuntu 系统上的主要认证日志 |
| /var/log/secure | RHEL/CentOS 系统上的主要认证日志 |
| wtmp/btmp | 记录成功和失败登录会话的二进制日志 |
| .bash_history | 用户命令历史文件(攻击者可能清除) |
| crontab | 常用于持久化的定时任务系统 |
| authorized_keys | 授予账户无密码访问的 SSH 公钥 |
| SUID 位 | 允许以文件所有者身份执行的文件权限(权限提升向量) |
| LD_PRELOAD | 在所有其他库之前加载共享库的环境变量(钩子技术) |
工具与系统
| 工具 | 目的 |
|---|---|
| chkrootkit | Linux 系统的 Rootkit 检测扫描器 |
| rkhunter | Rootkit Hunter - 检查 rootkit、后门和本地漏洞 |
| AIDE | 高级入侵检测环境 - 文件完整性监控 |
| auditd | 用于系统调用和文件访问监控的 Linux 审计框架 |
| last/lastb | 解析 wtmp/btmp 以获取登录和失败登录历史 |
| Plaso/log2timeline | 包含 Linux 证据的超时间线创建工具 |
| osquery | 用于实时取证调查的基于 SQL 的系统查询工具 |
| Velociraptor | 具有 Linux 证据收集功能的端点代理 |
常见场景
场景 1: SSH 暴力破解后遭入侵 分析 auth.log 中的失败 SSH 尝试,随后找到成功记录,识别攻击 IP,检查 .bash_history 中的入侵后命令,检查 authorized_keys 中是否添加了后门密钥,检查 crontab 持久化,审查网络连接。
场景 2: 通过应用漏洞导致 Web 服务器遭入侵 检查 Web 服务器访问和错误日志中的利用尝试,检查 /tmp 和 /dev/shm 中的 Webshell,分析 Web 服务器用户(www-data)的活动,检查通过 SUID 二进制或内核漏洞的权限提升,审查出站连接。
场景 3: 数据库服务器上的内部威胁 分析可疑用户的 bash_history 中的数据库导出命令,检查 home 目录或 /tmp 中的大型 tar/zip 文件,检查 scp/rsync 命令中的数据转移,审查 cron 作业中的自动化数据外泄,检查 USB 设备日志。
场景 4: 云实例上的加密货币挖矿 检查 /proc(实时)或 systemd 服务文件中的高 CPU 进程,检查 crontab 条目中的矿机重启脚本,检查 /tmp 中的挖矿二进制文件,分析用于矿池通信的网络连接,检查 authorized_keys 中的攻击者访问。
输出格式
Linux 取证摘要:
系统: webserver01 (Ubuntu 22.04 LTS)
主机名: webserver01.corp.local
内核: 5.15.0-91-generic
用户账户:
总数: 25 (3 个 UID 0 - 1 个异常)
交互式 shell: 8 个用户
最近创建: admin2 (创建于 2024-01-15)
认证事件:
成功 SSH 登录: 456
失败 SSH 尝试: 12,345 (来自 23 个不同 IP)
Sudo 执行: 89
发现的持久化机制:
Cron 作业: 3 个可疑 (反向 shell, 矿机重启)
Systemd 服务: 1 个未知 (update-checker.service)
SSH 密钥: root 的 authorized_keys 中有 2 个未授权密钥
rc.local: 已被修改,包含下载启动器
可疑活动:
- bash_history 中包含 wget 到 pastebin URL
- SUID 二进制 /tmp/…
(根据原文截断,仅翻译已给部分。)