一、概述
1.1 背景介绍
生产环境的安全防护不能只依赖边界防火墙。一旦攻击者突破外层防线,在主机内部进行的横向移动、权限提升、后门植入等行为,如果没有主机层面的检测能力,往往要到业务异常甚至数据泄露后才被发现。
一个完整的入侵检测体系通常包含三个层面:
- 网络层(NIDS):基于流量分析,典型工具如 Suricata、Snort,擅长检测已知攻击特征,但对加密流量无能为力。
- 主机层(HIDS):直接运行在目标主机上,监控文件变更、进程行为、用户操作,是整个防御体系的最后一道防线。
- 应用层:WAF、RASP 等,专注于检测针对 Web 应用的攻击。
那么,主机入侵检测具体需要关注哪些方面呢?其核心能力包括五点:文件完整性检测(关键二进制和配置文件是否被篡改)、Rootkit 扫描(内核级和用户态后门检测)、日志审计(谁在什么时间做了什么操作)、进程监控(异常进程和隐藏进程发现)以及网络连接异常检测(如反弹 Shell、挖矿外联等)。
常见的攻击链通常始于 SSH 暴力破解或 Web 漏洞(如 RCE、文件上传)获取初始权限,随后通过内核漏洞或滥用 SUID 程序提权到 root,并利用 crontab 或 systemd 植入后门维持权限,最终可能部署挖矿木马消耗系统资源。
面对市面上众多的 HIDS 工具,我们该如何选择?下表是几款主流工具的简要对比:
| 工具 |
文件完整性 |
Rootkit检测 |
实时监控 |
中心化管理 |
部署复杂度 |
| AIDE |
强 |
无 |
否(定期扫描) |
无 |
低 |
| Tripwire |
强 |
无 |
否 |
商业版支持 |
中 |
| OSSEC |
中 |
有 |
是 |
有(C/S架构) |
中 |
| Wazuh |
强 |
有 |
是 |
有(ELK集成) |
高 |
| rkhunter |
无 |
强 |
否(定期扫描) |
无 |
低 |
实际生产中,单一的入侵检测工具往往难以覆盖所有场景。一个推荐的做法是采用组合方案:使用 AIDE 负责文件完整性基线校验、用 rkhunter 定期扫描 Rootkit、通过 auditd 提供内核级的操作审计、并利用 ClamAV 处理恶意文件查杀。
1.2 技术特点
- AIDE(Advanced Intrusion Detection Environment):基于文件属性数据库的完整性检测工具。它支持多种哈希算法,配置灵活,且系统资源占用较低。
- rkhunter:专注于 Rootkit、后门和本地漏洞检测。它维护了一个已知 Rootkit 的签名库,同时也支持用户自定义检查项。
- auditd:这是 Linux 内核审计子系统的用户态守护进程,可以记录系统调用级别的详细操作日志,能够很好地满足等保或 PCI-DSS 等合规性要求。
- ClamAV:一款开源的杀毒引擎,其病毒库由社区维护更新,支持命令行扫描和守护进程模式。
1.3 适用场景
- 等保合规审计:等保二级以上明确要求具备入侵检测和安全审计能力,
auditd 配合 AIDE 可以满足大部分技术检查项。
- 安全基线检查:在新服务器上线前,进行全面的安全基线核查,确认系统未被预装后门。
- 入侵事件响应:在发现系统异常后,进行快速的排查和取证,此时需要一套系统化的检查流程和工具链。
- 日常安全巡检:通过定期自动化的扫描,及时发现配置漂移和异常变更。
1.4 环境要求
| 组件 |
版本要求 |
说明 |
| 操作系统 |
Ubuntu 22.04+ / CentOS 8+ |
推荐 Ubuntu 22.04 LTS |
| AIDE |
0.18.x |
apt 默认仓库版本即可 |
| rkhunter |
1.4.x |
安装后需更新签名库 |
| auditd |
3.x |
内核 4.x+ 支持完整审计特性 |
| ClamAV |
1.x |
需定期更新病毒库 (freshclam) |
| 磁盘空间 |
审计日志预留 10GB+ |
auditd 日志增长较快,需配置轮转 |
二、详细步骤
2.1 文件完整性检测(AIDE)
2.1.1 安装与初始化
# Ubuntu/Debian
sudo apt update && sudo apt install -y aide
# CentOS/RHEL
sudo dnf install -y aide
2.1.2 AIDE 配置文件
# /etc/aide/aide.conf - AIDE 主配置文件
# 数据库路径配置
database_in=file:/var/lib/aide/aide.db # 当前基线数据库(只读)
database_out=file:/var/lib/aide/aide.db.new # 检查后生成的新数据库
database_new=file:/var/lib/aide/aide.db.new # --update 时写入的目标
# 日志输出
report_url=file:/var/log/aide/aide.log
report_url=stdout
# 自定义检测规则组(按需组合文件属性)
# p: 权限 i: inode n: 硬链接数 u: 属主 g: 属组
# s: 文件大小 b: 块数 m: mtime c: ctime a: atime
# sha256: SHA-256 哈希 sha512: SHA-512 哈希
# S: 检查文件是否变大(只增长) acl: POSIX ACL xattrs: 扩展属性
# 关键二进制文件:全属性 + 强哈希
BINLIB = p+i+n+u+g+s+b+m+c+sha256+sha512
# 配置文件:关注内容变更和权限
CONFFILE = p+i+n+u+g+s+sha256
# 日志文件:只关注权限和属主,忽略内容变化(日志本身会增长)
LOGFILE = p+u+g
# 数据目录:关注权限和属主变更
DATAONLY = p+u+g+sha256
# ========== 监控目录定义 ==========
# 关键系统二进制目录 - 这些目录的文件被篡改意味着系统已被入侵
/bin BINLIB
/sbin BINLIB
/usr/bin BINLIB
/usr/sbin BINLIB
/usr/lib BINLIB
# 系统配置目录 - 监控配置篡改
/etc CONFFILE
# 引导目录 - 防止 bootkit
/boot BINLIB
# 内核模块 - 防止恶意内核模块加载
/lib/modules BINLIB
# ========== 排除目录(减少误报) ==========
# 排除频繁变化的目录
!/var/log
!/var/spool
!/var/cache
!/var/tmp
!/tmp
!/run
!/proc
!/sys
!/dev
# 排除包管理器数据库(安装/更新软件时会变化)
!/var/lib/dpkg
!/var/lib/apt
!/var/lib/rpm
2.1.3 基线数据库生成与安全存储
# 初始化基线数据库(首次运行,耗时取决于监控目录大小)
sudo aide --init
# 将新生成的数据库设为当前基线
sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db
# 安全存储:将基线数据库复制到只读介质或远程服务器
# 攻击者如果能修改基线数据库,AIDE 就失去意义
sudo cp /var/lib/aide/aide.db /mnt/readonly-backup/aide.db.$(date +%Y%m%d)
2.1.4 定期检查与基线更新
# 执行完整性检查(对比当前文件系统与基线数据库)
sudo aide --check
# 输出解读:
# f: 文件 d: 目录 l: 符号链接
# added: 新增文件(基线中不存在)
# removed: 删除文件(基线中存在但文件系统中没有)
# changed: 属性变更(哈希、权限、属主等)
# 合法变更后更新基线(如系统补丁、配置调整后)
sudo aide --update
sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db
配置 crontab 每日自动检查:
# /etc/cron.d/aide-check
0 3 * * * root /usr/bin/aide --check | mail -s "AIDE Report $(hostname) $(date +\%F)" security@company.com
2.2 Rootkit 检测(rkhunter + chkrootkit)
2.2.1 rkhunter 安装与配置
# 安装
sudo apt install -y rkhunter
# 安装后立即更新签名库和文件属性数据库
sudo rkhunter --update
sudo rkhunter --propupd
关键配置项调整:
# /etc/rkhunter.conf 关键配置
# 启用自动更新检查
UPDATE_MIRRORS=1
MIRRORS_MODE=0
WEB_CMD=""
# 邮件告警
MAIL-ON-WARNING=security@company.com
MAIL_CMD=mail -s "[rkhunter] {subject}" {recipient}
# 允许 SSH root 登录检查(根据实际策略调整)
ALLOW_SSH_ROOT_USER=no
# 允许 SSH 协议版本(只允许 v2)
ALLOW_SSH_PROT_V1=0
# 白名单配置 - 处理已知误报
# 系统更新后某些二进制文件哈希会变化,加入白名单避免误报
SCRIPTWHITELIST=/usr/bin/egrep
SCRIPTWHITELIST=/usr/bin/fgrep
SCRIPTWHITELIST=/usr/bin/which
SCRIPTWHITELIST=/usr/bin/ldd
# 允许隐藏目录(某些软件正常创建的隐藏目录)
ALLOWHIDDENDIR=/etc/.java
ALLOWHIDDENDIR=/dev/.udev
# 允许的 /dev 下非设备文件
ALLOWDEVFILE=/dev/shm/pulse-shm-*
ALLOWDEVFILE=/dev/shm/PostgreSQL.*
# 系统包管理器(用于验证文件属性)
PKGMGR=DPKG # Debian/Ubuntu 用 DPKG,CentOS 用 RPM
2.2.2 扫描执行与报告解读
# 完整扫描(交互模式,按回车跳过每个检查阶段)
sudo rkhunter --check
# 非交互模式(适合 cron 任务)
sudo rkhunter --check --skip-keypress --report-warnings-only
# 查看扫描日志
sudo cat /var/log/rkhunter.log
# 日志中的关键字段:
# [Found] - 发现可疑项,需要人工确认
# [Warning] - 警告项,可能是误报也可能是真实威胁
# [OK] - 检查通过
# [Not found] - 未发现对应 Rootkit 签名
2.2.3 chkrootkit 交叉验证
单一工具可能存在漏检,建议使用 chkrootkit 进行交叉验证:
# 安装
sudo apt install -y chkrootkit
# 执行扫描
sudo chkrootkit
# 静默模式(只输出可疑项)
sudo chkrootkit -q
# 两个工具的检测原理不同:
# rkhunter: 基于签名匹配 + 文件属性检查 + 系统配置审计
# chkrootkit: 基于特征字符串搜索 + 系统命令输出分析
# 交叉验证可以显著降低漏检率
2.3 系统审计框架(auditd)
2.3.1 架构原理
auditd 是 Linux 内核审计子系统的用户态组件。内核中的 audit 模块会在系统调用的入口和出口处插入钩子,根据用户预先定义的规则决定是否记录该操作。审计事件通过 netlink socket 从内核传递到用户态的 auditd 守护进程,最终被写入日志文件。
其核心组件包括:
auditd:守护进程,负责接收内核审计事件并写入日志。
auditctl:运行时管理工具,用于动态添加、删除或查看规则。
ausearch:审计日志搜索工具。
aureport:审计日志报告生成工具。
audisp-remote:审计日志远程转发插件。
# 安装
sudo apt install -y auditd audispd-plugins
# 启动并设置开机自启
sudo systemctl enable --now auditd
2.3.2 企业级审计规则
# /etc/audit/rules.d/security.rules - 企业级安全审计规则集
# 加载方式:sudo augenrules --load
# ========== 基础配置 ==========
# 审计缓冲区大小(繁忙系统调大,避免丢事件)
-b 8192
# 缓冲区满时的处理策略:1=打印警告并继续 2=立即关机(高安全环境)
-f 1
# 忽略配置错误继续加载(避免单条规则错误导致全部失败)
-c
# ========== 身份与认证审计 ==========
# 监控用户/组数据库文件的读写
-w /etc/passwd -p wa -k identity_mod
-w /etc/shadow -p wa -k identity_mod
-w /etc/group -p wa -k identity_mod
-w /etc/gshadow -p wa -k identity_mod
-w /etc/security/opasswd -p wa -k identity_mod
# 监控 sudoers 配置变更
-w /etc/sudoers -p wa -k privilege_escalation
-w /etc/sudoers.d/ -p wa -k privilege_escalation
# ========== 权限变更审计 ==========
# 监控文件权限修改(chmod/chown/fchmod/fchown)
-a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -F auid>=1000 -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S chown,fchown,fchownat,lchown -F auid>=1000 -F auid!=4294967295 -k perm_mod
# 监控 setuid/setgid 设置(提权关键操作)
-a always,exit -F arch=b64 -S setuid,setgid,setreuid,setregid -F auid>=1000 -F auid!=4294967295 -k priv_cmd
# ========== 用户操作审计 ==========
# 监控登录相关配置
-w /etc/login.defs -p wa -k login_config
-w /etc/securetty -p wa -k login_config
-w /etc/pam.d/ -p wa -k pam_config
# 监控 SSH 配置变更
-w /etc/ssh/sshd_config -p wa -k sshd_config
-w /etc/ssh/ssh_config -p wa -k ssh_config
# 监控 crontab 变更(后门常用持久化手段)
-w /etc/crontab -p wa -k cron_mod
-w /etc/cron.d/ -p wa -k cron_mod
-w /var/spool/cron/ -p wa -k cron_mod
# ========== 网络连接审计 ==========
# 监控网络套接字创建(检测反弹 Shell 和异常外联)
-a always,exit -F arch=b64 -S connect -F auid>=1000 -F auid!=4294967295 -k net_connect
-a always,exit -F arch=b64 -S bind -F auid>=1000 -F auid!=4294967295 -k net_bind
-a always,exit -F arch=b64 -S accept -F auid>=1000 -F auid!=4294967295 -k net_accept
# ========== 可执行文件审计 ==========
# 监控 /tmp 和 /var/tmp 下的程序执行(攻击者常在临时目录释放恶意文件)
-a always,exit -F arch=b64 -S execve -F dir=/tmp -k exec_tmp
-a always,exit -F arch=b64 -S execve -F dir=/var/tmp -k exec_tmp
-a always,exit -F arch=b64 -S execve -F dir=/dev/shm -k exec_shm
# 监控内核模块加载(防止 LKM Rootkit)
-w /sbin/insmod -p x -k kernel_mod
-w /sbin/rmmod -p x -k kernel_mod
-w /sbin/modprobe -p x -k kernel_mod
-a always,exit -F arch=b64 -S init_module,finit_module -k kernel_mod
-a always,exit -F arch=b64 -S delete_module -k kernel_mod
# ========== 规则锁定(放在最后) ==========
# 锁定规则,防止运行时被篡改(重启后才能修改)
-e 2
2.3.3 审计日志查询与报告
# ausearch - 按条件搜索审计事件
# 搜索所有身份文件变更事件
sudo ausearch -k identity_mod -ts today
# 搜索指定用户的所有操作
sudo ausearch -ua 1001 -ts recent
# 搜索指定时间范围内的提权操作
sudo ausearch -k privilege_escalation -ts "2024-01-15 00:00:00" -te "2024-01-15 23:59:59"
# 搜索失败的系统调用(可能是攻击尝试)
sudo ausearch --success no -ts today
# aureport - 生成汇总报告
# 认证事件报告(登录成功/失败统计)
sudo aureport -au --summary
# 可执行文件报告
sudo aureport -x --summary
# 异常事件报告
sudo aureport --anomaly
# 失败事件汇总
sudo aureport --failed --summary
为了防止攻击者清除本地日志,应配置审计日志远程转发:
# /etc/audit/plugins.d/au-remote.conf
active = yes
direction = out
path = /sbin/audisp-remote
type = always
format = string
# /etc/audit/audisp-remote.conf
remote_server = 192.168.1.100 # 远程日志服务器地址
port = 60 # 远程端口
transport = tcp # 传输协议
queue_depth = 1024 # 本地队列深度
fail_action = syslog # 远程不可达时写 syslog
2.4 应急响应流程
2.4.1 应急响应六步法
标准的应急响应流程通常分为六个阶段:
- 准备:工具链就绪、响应预案制定、联系人清单维护。
- 识别:确认安全事件是否真实发生,评估影响范围。
- 遏制:阻止攻击扩散,包括短期遏制(断网/封 IP)和长期遏制(修补漏洞)。
- 根除:清除攻击者留下的所有后门、恶意文件、异常账号。
- 恢复:从可信备份恢复系统,逐步恢复业务。
- 总结:复盘攻击路径,完善防护措施,更新响应预案。
2.4.2 初始响应检查清单
发现疑似入侵后,应按以下顺序采集信息(优先采集易失性数据):
# ===== 1. 系统基本信息 =====
uname -a # 内核版本
cat /etc/os-release # 系统版本
uptime # 运行时间(判断是否被重启过)
date # 当前时间(确认时区)
timedatectl # NTP 同步状态
# ===== 2. 用户账号排查 =====
# 检查异常用户(UID=0 的非 root 用户是高危信号)
awk -F: '$3==0 {print $1}' /etc/passwd
# 检查近期新增用户
grep -v "nologin\|false" /etc/passwd
# 检查空密码用户
awk -F: '($2=="") {print $1}' /etc/shadow
# 检查 sudo 权限用户
grep -v "^#" /etc/sudoers | grep -v "^$"
cat /etc/sudoers.d/*
# 当前登录用户和历史登录记录
w
last -20
lastb -20 # 失败的登录尝试
# ===== 3. 进程排查 =====
# 查看所有进程(关注异常进程名、异常路径)
ps auxf
# 查看进程打开的文件(定位恶意进程的文件和网络连接)
ls -la /proc/[PID]/exe # 查看进程对应的可执行文件
ls -la /proc/[PID]/fd # 查看进程打开的文件描述符
# 检查已删除但仍在运行的进程(攻击者常删除恶意文件但进程仍在)
ls -la /proc/*/exe 2>/dev/null | grep "(deleted)"
# ===== 4. 网络连接排查 =====
# 查看所有网络连接(关注 ESTABLISHED 和 LISTEN 状态)
ss -tulnp
netstat -tulnp
# 查看异常外联(排除已知业务 IP)
ss -tnp state established
# ===== 5. 文件排查 =====
# 查找最近 3 天内被修改的文件(排除日志和缓存目录)
find / -mtime -3 -type f \( ! -path "/var/log/*" ! -path "/var/cache/*" ! -path "/proc/*" ! -path "/sys/*" ! -path "/run/*" \) 2>/dev/null
# 查找 SUID/SGID 文件(提权常用)
find / -perm -4000 -type f 2>/dev/null
find / -perm -2000 -type f 2>/dev/null
# 查找隐藏文件和目录
find / -name ".*" -type f 2>/dev/null | grep -v -E "^/(proc|sys|run)"
# ===== 6. 定时任务排查 =====
# 系统级定时任务
cat /etc/crontab
ls -la /etc/cron.d/
ls -la /etc/cron.daily/
ls -la /etc/cron.hourly/
# 用户级定时任务
for user in $(cut -d: -f1 /etc/passwd); do
crontab -l -u "$user" 2>/dev/null && echo "=== $user ==="
done
# systemd 定时器(新型持久化手段)
systemctl list-timers --all
三、示例代码和配置
3.1 自动化安全巡检脚本
#!/bin/bash
# 文件名:security_audit.sh
# 功能:一键采集系统安全状态,生成巡检报告
# 用法:sudo bash security_audit.sh
set -euo pipefail
REPORT_DIR="/tmp/security_audit_$(hostname)_$(date +%Y%m%d_%H%M%S)"
mkdir -p "${REPORT_DIR}"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "${REPORT_DIR}/audit.log"
}
log "===== 安全巡检开始 ====="
log "主机名: $(hostname)"
log "IP 地址: $(hostname -I | awk '{print $1}')"
log "系统版本: $(cat /etc/os-release | grep PRETTY_NAME | cut -d'\"' -f2)"
log "内核版本: $(uname -r)"
log "报告目录: ${REPORT_DIR}"
# ---------- 1. 用户账号检查 ----------
log "--- 采集用户账号信息 ---"
{
echo "=== UID=0 的用户(应该只有 root)==="
awk -F: '$3==0 {print $1}' /etc/passwd
echo -e "\n=== 可登录的用户 ==="
grep -v "nologin\|false\|/bin/sync\|/bin/halt\|/bin/shutdown" /etc/passwd
echo -e "\n=== 空密码用户 ==="
awk -F: '($2=="" || $2=="!") {print $1}' /etc/shadow 2>/dev/null || echo "无法读取 shadow 文件"
echo -e "\n=== 最近 30 天登录记录 ==="
last -30 | head -50
echo -e "\n=== 最近失败登录 ==="
lastb 2>/dev/null | head -30 || echo "无 lastb 记录"
} > "${REPORT_DIR}/01_users.txt"
# ---------- 2. 进程检查 ----------
log "--- 采集进程信息 ---"
{
echo "=== 进程树 ==="
ps auxf
echo -e "\n=== 已删除但仍运行的进程 ==="
ls -la /proc/*/exe 2>/dev/null | grep "(deleted)" || echo "未发现"
echo -e "\n=== CPU 占用 TOP 20 ==="
ps aux --sort=-%cpu | head -21
} > "${REPORT_DIR}/02_processes.txt"
# ---------- 3. 网络连接检查 ----------
log "--- 采集网络连接信息 ---"
{
echo "=== 监听端口 ==="
ss -tulnp
echo -e "\n=== 已建立的连接 ==="
ss -tnp state established
echo -e "\n=== 路由表 ==="
ip route
echo -e "\n=== DNS 配置 ==="
cat /etc/resolv.conf
} > "${REPORT_DIR}/03_network.txt"
# ---------- 4. 定时任务检查 ----------
log "--- 采集定时任务 ---"
{
echo "=== 系统 crontab ==="
cat /etc/crontab 2>/dev/null
echo -e "\n=== /etc/cron.d/ ==="
ls -la /etc/cron.d/ 2>/dev/null
for f in /etc/cron.d/*; do
[ -f "$f" ] && echo "--- $f ---" && cat "$f"
done
echo -e "\n=== 用户 crontab ==="
for user in $(cut -d: -f1 /etc/passwd); do
cron_content=$(crontab -l -u "$user" 2>/dev/null) && \
echo "--- ${user} ---" && echo "$cron_content"
done
echo -e "\n=== systemd 定时器 ==="
systemctl list-timers --all --no-pager 2>/dev/null
} > "${REPORT_DIR}/04_crontabs.txt"
# ---------- 5. SUID/SGID 文件 ----------
log "--- 扫描 SUID/SGID 文件 ---"
{
echo "=== SUID 文件 ==="
find / -perm -4000 -type f 2>/dev/null
echo -e "\n=== SGID 文件 ==="
find / -perm -2000 -type f 2>/dev/null
} > "${REPORT_DIR}/05_suid_sgid.txt"
# ---------- 6. 最近修改的文件 ----------
log "--- 扫描最近 3 天修改的文件 ---"
find / -mtime -3 -type f \
\( ! -path "/proc/*" ! -path "/sys/*" ! -path "/run/*" \
! -path "/var/log/*" ! -path "/var/cache/*" ! -path "/tmp/*" \) \
2>/dev/null > "${REPORT_DIR}/06_recent_files.txt"
log "===== 巡检完成,报告目录: ${REPORT_DIR} ====="
# 打包报告
tar czf "${REPORT_DIR}.tar.gz" -C /tmp "$(basename ${REPORT_DIR})"
log "报告已打包: ${REPORT_DIR}.tar.gz"
3.2 入侵痕迹自动化排查脚本
#!/bin/bash
# 文件名:intrusion_detect.sh
# 功能:自动化检测常见入侵痕迹
# 用法:sudo bash intrusion_detect.sh
set -euo pipefail
RED='\033[0;31m'
YELLOW='\033[1;33m'
GREEN='\033[0;32m'
NC='\033[0m'
ALERT_COUNT=0
alert() {
echo -e "${RED}[!] 告警: $1${NC}"
((ALERT_COUNT++)) || true
}
warn() {
echo -e "${YELLOW} 注意: $1${NC}"
}
ok() {
echo -e "${GREEN}[+] 正常: $1${NC}"
}
echo "=========================================="
echo " 入侵痕迹自动化排查"
echo " 时间: $(date)"
echo " 主机: $(hostname)"
echo "=========================================="
# ---------- 1. 异常用户检测 ----------
echo -e "\n--- 1. 用户账号检查 ---"
# 检查 UID=0 的非 root 用户
uid0_users=$(awk -F: '$3==0 && $1!="root" {print $1}' /etc/passwd)
if [ -n "$uid0_users" ]; then
alert "发现非 root 的 UID=0 用户: ${uid0_users}"
else
ok "无异常 UID=0 用户"
fi
# 检查空密码用户
empty_pass=$(awk -F: '($2=="" ) {print $1}' /etc/shadow 2>/dev/null)
if [ -n "$empty_pass" ]; then
alert "发现空密码用户: ${empty_pass}"
else
ok "无空密码用户"
fi
# 检查 /etc/passwd 和 /etc/shadow 的权限
passwd_perm=$(stat -c %a /etc/passwd)
shadow_perm=$(stat -c %a /etc/shadow)
[ "$passwd_perm" != "644" ] && alert "/etc/passwd 权限异常: ${passwd_perm}(应为 644)"
[ "$shadow_perm" != "640" ] && [ "$shadow_perm" != "600" ] && alert "/etc/shadow 权限异常: ${shadow_perm}(应为 640 或 600)"
# ---------- 2. 隐藏进程检测 ----------
echo -e "\n--- 2. 隐藏进程检测 ---"
# 对比 ps 和 /proc 的进程列表
ps_pids=$(ps -eo pid --no-headers | sort -n)
proc_pids=$(ls -d /proc/[0-9]* 2>/dev/null | awk -F/ '{print $3}' | sort -n)
hidden=$(comm -13 <(echo "$ps_pids" | tr -d ' ') <(echo "$proc_pids"))
if [ -n "$hidden" ]; then
alert "发现隐藏进程 PID: ${hidden}"
else
ok "未发现隐藏进程"
fi
# 检查已删除但仍运行的可执行文件
deleted_procs=$(ls -la /proc/*/exe 2>/dev/null | grep "(deleted)" || true)
if [ -n "$deleted_procs" ]; then
alert "发现已删除但仍运行的进程:\n${deleted_procs}"
else
ok "无已删除的运行进程"
fi
# ---------- 3. 异常网络连接检测 ----------
echo -e "\n--- 3. 网络连接检查 ---"
# 检测常见挖矿矿池端口(3333, 4444, 5555, 8888, 14444)
mining_ports="3333|4444|5555|8888|14444"
mining_conn=$(ss -tnp state established 2>/dev/null | grep -E ":($mining_ports)" || true)
if [ -n "$mining_conn" ]; then
alert "发现疑似挖矿连接:\n${mining_conn}"
else
ok "未发现挖矿端口连接"
fi
# 检测反弹 Shell 特征(进程关联了 socket 且连接外部)
reverse_shell=$(ss -tnp state established 2>/dev/null | grep -E "bash|sh|python|perl|nc|ncat" || true)
if [ -n "$reverse_shell" ]; then
alert "发现疑似反弹 Shell:\n${reverse_shell}"
else
ok "未发现反弹 Shell 特征"
fi
# ---------- 4. Webshell 检测 ----------
echo -e "\n--- 4. Webshell 扫描 ---"
# 常见 Web 目录
WEB_DIRS=("/var/www" "/usr/share/nginx" "/opt/tomcat/webapps" "/srv/http")
webshell_found=0
for dir in "${WEB_DIRS[@]}"; do
if [ -d "$dir" ]; then
# 检测 PHP Webshell 关键函数
php_shells=$(grep -rl --include="*.php" -E "eval\s*\(|base64_decode\s*\(|system\s*\(|passthru\s*\(|shell_exec\s*\(|assert\s*\(" "$dir" 2>/dev/null || true)
if [ -n "$php_shells" ]; then
alert "在 ${dir} 发现疑似 PHP Webshell:\n${php_shells}"
webshell_found=1
fi
# 检测 JSP Webshell
jsp_shells=$(grep -rl --include="*.jsp" -E "Runtime\.getRuntime|ProcessBuilder|exec\s*\(" "$dir" 2>/dev/null || true)
if [ -n "$jsp_shells" ]; then
alert "在 ${dir} 发现疑似 JSP Webshell:\n${jsp_shells}"
webshell_found=1
fi
fi
done
[ "$webshell_found" -eq 0 ] && ok "未发现 Webshell"
# ---------- 5. 挖矿进程检测 ----------
echo -e "\n--- 5. 挖矿进程检测 ---"
# 按进程名匹配已知挖矿程序
mining_procs=$(ps aux | grep -iE "xmrig|cryptonight|stratum|minerd|kworkerds|kdevtmpfsi|solr\.sh" | grep -v grep || true)
if [ -n "$mining_procs" ]; then
alert "发现疑似挖矿进程:\n${mining_procs}"
else
ok "未发现已知挖矿进程"
fi
# CPU 使用率超过 90% 的进程(挖矿特征)
high_cpu=$(ps aux --sort=-%cpu | awk 'NR>1 && $3>90 {print $0}')
if [ -n "$high_cpu" ]; then
warn "发现 CPU 占用超过 90% 的进程:\n${high_cpu}"
else
ok "无异常高 CPU 进程"
fi
# ---------- 汇总 ----------
echo -e "\n=========================================="
if [ "$ALERT_COUNT" -gt 0 ]; then
echo -e "${RED}排查完成,共发现 ${ALERT_COUNT} 个告警项,请人工确认!${NC}"
else
echo -e "${GREEN}排查完成,未发现明显入侵痕迹。${NC}"
fi
echo "=========================================="
3.3 auditd 企业级规则集完整配置
# /etc/audit/rules.d/99-security-hardening.rules
# 企业级安全审计规则集 - 完整版
# 适用于等保三级 / PCI-DSS 合规要求
# 加载:sudo augenrules --load && sudo auditctl -l
# ========== 全局配置 ==========
-D # 清除已有规则
-b 8192 # 内核审计缓冲区
-f 1 # 失败策略:1=printk 2=panic
-c # 忽略错误继续
# ========== 时间变更审计(防止攻击者篡改时间掩盖痕迹) ==========
-a always,exit -F arch=b64 -S adjtimex,settimeofday,clock_settime -k time_change
-w /etc/localtime -p wa -k time_change
# ========== 用户/组变更 ==========
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/group -p wa -k identity
-w /etc/gshadow -p wa -k identity
-w /etc/security/opasswd -p wa -k identity
-w /usr/sbin/useradd -p x -k user_mgmt
-w /usr/sbin/userdel -p x -k user_mgmt
-w /usr/sbin/usermod -p x -k user_mgmt
-w /usr/sbin/groupadd -p x -k user_mgmt
-w /usr/sbin/groupdel -p x -k user_mgmt
# ========== 权限提升 ==========
-w /etc/sudoers -p wa -k priv_esc
-w /etc/sudoers.d/ -p wa -k priv_esc
-w /usr/bin/sudo -p x -k priv_esc
-w /usr/bin/su -p x -k priv_esc
-a always,exit -F arch=b64 -S setuid,setgid,setreuid,setregid,seteuid,setegid -F auid>=1000 -F auid!=4294967295 -k priv_esc
# ========== 网络配置变更 ==========
-w /etc/hosts -p wa -k net_config
-w /etc/hostname -p wa -k net_config
-w /etc/resolv.conf -p wa -k net_config
-w /etc/network/ -p wa -k net_config
-w /etc/netplan/ -p wa -k net_config
-a always,exit -F arch=b64 -S sethostname,setdomainname -k net_config
# ========== SSH 与认证 ==========
-w /etc/ssh/sshd_config -p wa -k sshd_config
-w /etc/pam.d/ -p wa -k pam_mod
-w /etc/security/limits.conf -p wa -k security_limits
-w /var/log/faillog -p wa -k login_events
-w /var/log/lastlog -p wa -k login_events
# ========== 定时任务(持久化检测) ==========
-w /etc/crontab -p wa -k cron_persist
-w /etc/cron.d/ -p wa -k cron_persist
-w /etc/cron.daily/ -p wa -k cron_persist
-w /etc/cron.hourly/ -p wa -k cron_persist
-w /etc/cron.weekly/ -p wa -k cron_persist
-w /etc/cron.monthly/ -p wa -k cron_persist
-w /var/spool/cron/ -p wa -k cron_persist
# systemd 服务(另一种持久化手段)
-w /etc/systemd/system/ -p wa -k systemd_persist
-w /usr/lib/systemd/system/ -p wa -k systemd_persist
# ========== 内核模块 ==========
-w /sbin/insmod -p x -k kernel_module
-w /sbin/rmmod -p x -k kernel_module
-w /sbin/modprobe -p x -k kernel_module
-a always,exit -F arch=b64 -S init_module,finit_module,delete_module -k kernel_module
# ========== 文件删除审计(反取证检测) ==========
-a always,exit -F arch=b64 -S unlink,unlinkat,rename,renameat -F auid>=1000 -F auid!=4294967295 -k file_delete
# ========== 临时目录执行审计 ==========
-a always,exit -F arch=b64 -S execve -F dir=/tmp -k exec_from_tmp
-a always,exit -F arch=b64 -S execve -F dir=/var/tmp -k exec_from_tmp
-a always,exit -F arch=b64 -S execve -F dir=/dev/shm -k exec_from_tmp
# ========== 规则锁定(必须放在最后) ==========
-e 2
四、最佳实践和注意事项
4.1 最佳实践
4.1.1 安全基线建设
安全基线建设并非一次性工作,而是一个持续维护的过程。CIS Benchmark 为各主流发行版提供了详细的加固清单,直接参照执行比自己摸索更为可靠。
核心加固动作示例:
#!/bash
set -euo pipefail
# 最小化安装原则:清理不必要的包
dpkg --list | grep -E "^ii" | awk '{print $2}' > /tmp/installed_packages.txt
# 逐一审查,移除不需要的服务
sudo apt purge -y telnetd rsh-server xinetd
# 关闭不必要的服务
for svc in avahi-daemon cups bluetooth; do
sudo systemctl stop "$svc" 2>/dev/null || true
sudo systemctl disable "$svc" 2>/dev/null || true
sudo systemctl mask "$svc" 2>/dev/null || true
done
# SUID/SGID 文件清理:先摸底,再逐个确认是否需要
find / -type f \( -perm -4000 -o -perm -2000 \) -exec ls -la {} \; 2>/dev/null > /tmp/suid_sgid_audit.txt
# 对确认不需要 SUID 的文件去除权限
sudo chmod u-s /usr/bin/newgrp
sudo chmod u-s /usr/sbin/pppd
CIS Benchmark 关键检查项速查:
| 检查类别 |
具体项目 |
命令 |
| 文件系统 |
/tmp 独立分区且 noexec |
mount | grep /tmp |
| 网络参数 |
禁用 IP 转发 |
sysctl net.ipv4.ip_forward |
| 访问控制 |
SSH 禁止 root 登录 |
grep PermitRootLogin /etc/ssh/sshd_config |
| 审计策略 |
auditd 已启用 |
systemctl is-active auditd |
| 密码策略 |
最小长度 ≥ 14 位 |
grep minlen /etc/security/pwquality.conf |
4.1.2 日志集中管理
将日志仅存储在本地主机上,等于给攻击者留下了销毁证据的机会。入侵者在获得 root 权限后,往往会首先清理日志。因此,日志必须实时转发到远端服务器。
rsyslog 远程转发配置示例:
# /etc/rsyslog.d/50-remote.conf
# 使用 TCP 保证可靠传输(@@表示TCP,@表示UDP)
*.* @@logserver.internal:514
# 本地队列防止网络中断丢日志
$ActionQueueType LinkedList
$ActionQueueFileName remote_fwd
$ActionResumeRetryCount -1
$ActionQueueSaveOnShutdown on
利用文件属性实现日志防篡改(只追加):
# 设置只追加属性,即使 root 也无法删除或修改已有内容
sudo chattr +a /var/log/auth.log
sudo chattr +a /var/log/syslog
# 验证属性
lsattr /var/log/auth.log
# 输出:-----a--------e----- /var/log/auth.log
# 注意:logrotate 需要特殊处理,轮转前临时去除属性
# 在 /etc/logrotate.d/rsyslog 中添加 prerotate/postrotate 脚本
日志保留策略建议:
| 日志类型 |
本地保留 |
远端保留 |
说明 |
| 认证日志 |
90 天 |
1 年 |
安全审计核心数据 |
| 系统日志 |
30 天 |
6 个月 |
故障排查依据 |
| 审计日志 |
90 天 |
1 年 |
合规要求通常 ≥ 180 天 |
| 应用日志 |
15 天 |
3 个月 |
按业务需求调整 |
4.1.3 纵深防御体系
单点防御在面对真实攻击时往往显得脆弱。纵深防御的核心思路是:在每一层都假设上一层已经被突破。
┌─────────────────────────────────────────────┐
│ 网络层:iptables/nftables + Suricata NIDS │
│ ┌─────────────────────────────────────────┐ │
│ │ 主机层:auditd + AIDE + rkhunter │ │
│ │ ┌─────────────────────────────────────┐│ │
│ │ │ 应用层:WAF + RASP + 输入校验 ││ │
│ │ │ ┌─────────────────────────────────┐││ │
│ │ │ │ 数据层:加密存储 + 访问控制 │││ │
│ │ │ └─────────────────────────────────┘││ │
│ │ └─────────────────────────────────────┘│ │
│ └─────────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
各层防护措施对比:
| 防护层 |
工具/方案 |
检测能力 |
局限性 |
| 网络层 |
iptables + Suricata |
已知攻击特征、端口扫描 |
加密流量无法深度检测 |
| 主机层 |
auditd + AIDE + OSSEC |
文件篡改、提权操作、异常进程 |
内核级 Rootkit 可绕过 |
| 应用层 |
ModSecurity + OpenRASP |
SQL注入、XSS、命令注入 |
业务逻辑漏洞难以覆盖 |
| 数据层 |
LUKS 磁盘加密 + GPG |
数据泄露后无法解密 |
运行时内存中数据仍为明文 |
4.1.4 自动化响应
手动响应在凌晨三点收到告警时,效率往往很低。自动化是缩短 MTTR(平均恢复时间)的关键。
Wazuh + ELK 集成架构下的自动封禁方案示例:
#!/bin/bash
set -euo pipefail
# Wazuh Active Response 脚本:自动封禁暴力破解 IP
# 文件路径:/var/ossec/active-response/bin/block-ip.sh
LOCAL=$(dirname "$0")
LOCK="${LOCAL}/fw-drop"
LOCK_PID="${LOCK}/pid"
# 从 Wazuh 传入的参数中提取 IP
ACTION=$1
IP=$3
if [ "x${ACTION}" = "xadd" ]; then
# 封禁 IP,有效期 1 小时
iptables -I INPUT -s "${IP}" -j DROP
# 记录封禁日志
echo "$(date '+%Y-%m-%d %H:%M:%S') BLOCKED ${IP}" >> /var/log/active-response.log
elif [ "x${ACTION}" = "xdelete" ]; then
# 解封
iptables -D INPUT -s "${IP}" -j DROP
echo "$(date '+%Y-%m-%d %H:%M:%S') UNBLOCKED ${IP}" >> /var/log/active-response.log
fi
告警分级与升级机制:
| 级别 |
触发条件 |
响应动作 |
通知方式 |
| P3-低 |
单次 SSH 失败、端口扫描 |
记录日志,不告警 |
日报汇总 |
| P2-中 |
5 分钟内 ≥ 10 次 SSH 失败 |
自动封禁 IP 1 小时 |
企业微信/钉钉通知 |
| P1-高 |
SUID 文件变更、新增 crontab |
封禁 + 隔离主机网络 |
电话告警 + 工单 |
| P0-紧急 |
Rootkit 检出、内核模块加载 |
立即隔离 + 保留现场 |
电话 + 短信 + 启动应急预案 |
4.2 注意事项
4.2.1 配置注意事项
⚠️ 警告:应急响应中的操作失误可能比入侵本身造成更大的损失。
- AIDE 基线数据库(
/var/lib/aide/aide.db)必须离线存储或存放在只读介质上。攻击者拿到 root 后可以重新生成基线,让所有篡改“合法化”。
- auditd 规则不是越多越好。规则过多会显著增加系统调用开销,生产环境建议控制在 50 条以内,重点监控关键路径。
- 应急响应时绝对不要直接关机或重启。内存中的恶意进程信息、网络连接状态、
/proc 下的运行时数据会全部丢失,这些都是取证的关键证据。
- 不要在被入侵的主机上直接运行杀毒工具或清理脚本。先做磁盘镜像,在镜像副本上操作。
- 修改 SSH 配置后务必保持当前会话不断开,新开终端测试连接。配置错误导致 SSH 锁死是运维事故的经典场景。
4.2.2 常见错误
| 错误现象 |
原因分析 |
解决方案 |
| AIDE 检查报告大量误报 |
未排除动态变化的文件(日志、缓存) |
在 aide.conf 中用 ! 排除 /var/log、/tmp 等目录 |
| auditd 导致系统卡顿 |
规则匹配范围过大,审计日志写入量爆炸 |
缩小规则范围,增加 -F auid>=1000 过滤系统进程 |
| rkhunter 报 “Warning: Hidden file found” |
/dev/.udev 等是系统正常文件 |
在 /etc/rkhunter.conf 中加入白名单 ALLOWHIDDENFILE |
| ClamAV 扫描占满 CPU |
默认全盘扫描无资源限制 |
使用 nice -n 19 降低优先级,--max-filesize 限制单文件大小 |
| 日志转发丢失数据 |
rsyslog 使用 UDP 协议,网络抖动丢包 |
改用 TCP(@@)并启用磁盘队列缓冲 |
4.2.3 取证注意事项
数字取证的核心原则是保持证据链的完整性。任何操作都可能改变证据状态,因此必须遵循严格的采集顺序。
易失性数据采集优先级(RFC 3227):
优先级从高到低:
1. CPU 寄存器、缓存 → 几乎无法采集,忽略
2. 内存内容 → volatility / /proc/PID/maps
3. 网络连接状态 → ss -tnp / netstat -tnp / /proc/net/tcp
4. 运行中的进程 → ps auxf / /proc/PID/
5. 磁盘数据 → dd 镜像
6. 远程日志 → 日志服务器备份
取证操作规范示例:
#!/bin/bash
set -euo pipefail
# 取证数据采集脚本(在被入侵主机上执行,工具从只读U盘加载)
EVIDENCE_DIR="/mnt/usb/evidence/$(hostname)_$(date +%Y%m%d_%H%M%S)"
mkdir -p "${EVIDENCE_DIR}"
# 1. 采集内存信息
cp /proc/meminfo "${EVIDENCE_DIR}/meminfo.txt"
ps auxf > "${EVIDENCE_DIR}/ps_full.txt"
cat /proc/net/tcp > "${EVIDENCE_DIR}/proc_net_tcp.txt"
# 2. 采集网络连接
ss -tnp > "${EVIDENCE_DIR}/ss_connections.txt"
iptables -L -n -v > "${EVIDENCE_DIR}/iptables_rules.txt"
# 3. 采集用户和登录信息
last -aiF > "${EVIDENCE_DIR}/last_logins.txt"
lastlog > "${EVIDENCE_DIR}/lastlog.txt"
cat /etc/passwd > "${EVIDENCE_DIR}/passwd.txt"
# 4. 采集定时任务
for user in $(cut -d: -f1 /etc/passwd); do
crontab -l -u "$user" 2>/dev/null > "${EVIDENCE_DIR}/crontab_${user}.txt" || true
done
# 5. 计算哈希保证完整性
find "${EVIDENCE_DIR}" -type f -exec sha256sum {} \; > "${EVIDENCE_DIR}/checksums.sha256"
echo "取证数据已保存至 ${EVIDENCE_DIR}"
法律合规要点:
- 取证过程需全程记录操作日志,包括时间、操作人、具体命令。
- 证据文件应计算 SHA256 哈希值并由多人签字确认。
- 磁盘镜像应使用写保护设备,确保原始证据不被修改。
- 涉及个人隐私数据时,需遵循《数据安全法》和《个人信息保护法》相关规定。
五、故障排查和监控
5.1 故障排查
5.1.1 日志查看
安全事件排查的第一步永远是查看日志。虽然不同 Linux 发行版的日志路径略有差异,但核心日志就那么几个:
# 认证日志:SSH 登录、sudo 操作、PAM 认证
# Debian/Ubuntu
tail -100 /var/log/auth.log | grep -E "(Failed|Accepted|session opened)"
# RHEL/CentOS
tail -100 /var/log/secure | grep -E "(Failed|Accepted|session opened)"
# 审计日志:auditd 记录的系统调用
# 查看最近的提权操作
ausearch -k privilege_escalation -ts recent
# 查看文件篡改事件
ausearch -k etc_modification -ts today
# journalctl 按优先级过滤(0=emerg 到 7=debug)
# 只看 warning 及以上级别
journalctl -p 0..4 --since "1 hour ago" --no-pager
# 查看特定服务的日志
journalctl -u sshd --since "2025-01-01" --until "2025-01-02" --no-pager
5.1.2 常见问题排查
可疑进程分析
当发现 CPU 异常飙升或出现不认识的进程名时,/proc 目录是最直接的信息来源:
# 定位可疑进程(假设 PID 为 12345)
PID=12345
# 查看进程的真实可执行文件路径(即使进程名被伪装)
ls -la /proc/${PID}/exe
# 输出示例:/proc/12345/exe -> /tmp/.hidden/xmrig (deleted)
# “deleted” 说明文件已被删除但进程仍在运行
# 查看进程启动的完整命令行
cat /proc/${PID}/cmdline | tr '\0' ' '
# 查看进程的环境变量(可能包含 C2 地址等关键信息)
cat /proc/${PID}/environ | tr '\0' '\n' | head -20
# 查看进程打开的文件描述符
ls -la /proc/${PID}/fd/
# 查看进程的网络连接
lsof -p ${PID} -i -n
# 实时跟踪进程的系统调用(谨慎使用,有性能开销)
strace -fp ${PID} -e trace=network,write -o /tmp/strace_${PID}.log &
# 跟踪 10 秒后停止
sleep 10 && kill %1
隐藏文件与后门检测
# 查找隐藏文件和目录(排除正常的 . 和 ..)
find / -name ".*" -not -path "/proc/*" -not -path "/sys/*" \
-not -name "." -not -name ".." -ls 2>/dev/null | head -50
# 检查 LD_PRELOAD 劫持(用户态 Rootkit 常用手法)
# 如果有输出,说明存在全局共享库劫持
cat /etc/ld.so.preload 2>/dev/null
echo $LD_PRELOAD
# 对比系统命令是否被替换(用静态编译的 busybox 做对照)
# 正常的 ps 和被劫持的 ps 输出对比
/path/to/busybox ps auxf > /tmp/ps_clean.txt
ps auxf > /tmp/ps_system.txt
diff /tmp/ps_clean.txt /tmp/ps_system.txt
# 如果有差异,说明 ps 命令可能被篡改或存在进程隐藏
# 检查动态链接库是否被篡改
for cmd in ps ls netstat ss top; do
echo "=== ${cmd} ==="
ldd "$(which ${cmd})" 2>/dev/null
done
异常网络连接追踪
# 查看所有对外建立的 TCP 连接(重点关注非常规端口)
ss -tnp state established | awk '{print $4, $5, $6}' | sort -t: -k2 -n
# 从 /proc/net/tcp 解析连接(即使 ss/netstat 被篡改也能获取)
# 字段:本地地址:端口 远端地址:端口 状态(01=ESTABLISHED)
awk '$4 == "01" {print $2, $3}' /proc/net/tcp | while read local remote; do
# 十六进制转十进制 IP
local_ip=$(printf "%d.%d.%d.%d" \
0x${local:6:2} 0x${local:4:2} 0x${local:2:2} 0x${local:0:2})
local_port=$((16#${local##*:}))
remote_ip=$(printf "%d.%d.%d.%d" \
0x${remote:6:2} 0x${remote:4:2} 0x${remote:2:2} 0x${remote:0:2})
remote_port=$((16#${remote##*:}))
echo "${local_ip}:${local_port} -> ${remote_ip}:${remote_port}"
done
# 外联 IP 威胁情报查询(使用 VirusTotal API)
# 替换为实际的 API Key
VT_API_KEY="your_api_key_here"
SUSPECT_IP="1.2.3.4"
curl -s "https://www.virustotal.com/api/v3/ip_addresses/${SUSPECT_IP}" \
-H "x-apikey: ${VT_API_KEY}" | jq '.data.attributes.last_analysis_stats'
挖矿木马清除流程
挖矿木马是当前最常见的入侵后行为,清除需要系统化操作:
#!/bin/bash
set -euo pipefail
# 挖矿木马清除流程
echo "===== 第一步:定位挖矿进程 ====="
# 按 CPU 使用率排序,挖矿进程通常占满 CPU
ps aux --sort=-%cpu | head -10
# 常见挖矿进程名(会伪装成系统进程)
MINERS="xmrig|kdevtmpfsi|kinsing|solrd|dbused|xmr-stak|minerd"
ps aux | grep -iE "${MINERS}" | grep -v grep
echo "===== 第二步:清除恶意文件 ====="
# 根据 /proc/PID/exe 找到实际文件路径并删除
# kill 进程前先记录完整信息
PID=$(pgrep -f "xmrig" || true)
if [ -n "${PID}" ]; then
ls -la /proc/${PID}/exe 2>/dev/null
cat /proc/${PID}/cmdline | tr '\0' ' '
kill -9 ${PID}
fi
echo "===== 第三步:清理持久化机制 ====="
# 检查并清理 crontab
for user in $(cut -d: -f1 /etc/passwd); do
crontab -l -u "$user" 2>/dev/null | grep -iE "(curl|wget|\.sh|mining|pool)" && \
echo "发现可疑 crontab 条目,用户: $user"
done
# 检查 systemd 服务
find /etc/systemd/system/ /usr/lib/systemd/system/ -name "*.service" -newer /etc/os-release -ls
# 检查 /etc/rc.local 和 /etc/profile.d/
cat /etc/rc.local 2>/dev/null
ls -la /etc/profile.d/
echo "===== 第四步:加固防止复发 ====="
# 修改被利用的入口(如 Redis 未授权访问)
# 更新系统补丁
# 重置所有可能泄露的凭据
echo "请手动完成加固操作"
5.1.3 内存取证基础
磁盘上的文件可以被删除,但只要进程还在运行,内存中就保留着关键信息:
# 查看进程的内存映射
cat /proc/${PID}/maps
# 从进程内存中提取可疑字符串(C2 地址、密钥等)
strings /proc/${PID}/mem 2>/dev/null | grep -iE "(http|https|\.onion|password|pool\.|stratum)" | sort -u
# 更安全的方式:dump 指定内存区域
# 从 maps 中找到可读写的堆区域
grep "heap" /proc/${PID}/maps
# 输出示例:01a00000-05000000 rw-p 00000000 00:00 0 [heap]
# 使用 gdb 导出内存段(需要 gdb 已安装)
gdb -batch -pid ${PID} -ex "dump memory /tmp/heap_dump.bin 0x01a00000 0x05000000" 2>/dev/null
strings /tmp/heap_dump.bin | grep -iE "(pool\.|stratum|wallet)" | head -20
5.2 性能监控
5.2.1 关键安全指标
安全监控和性能监控的区别在于:性能监控关注“系统是否正常”,而安全监控关注“系统是否被控制”。以下指标需要持续采集:
# SSH 失败登录次数(最近 1 小时)
journalctl -u sshd --since "1 hour ago" --no-pager | grep -c "Failed password"
# SUID 文件数量变化(与基线对比)
find / -type f -perm -4000 2>/dev/null | wc -l
# 基线值记录在 /var/lib/security/suid_baseline.txt
# 异常外联连接数(排除已知业务端口)
ss -tnp state established | awk '{print $5}' | grep -v -E ":(80|443|53|123|514)$" | wc -l
# CPU 使用率 TOP5 进程(挖矿检测)
ps aux --sort=-%cpu | awk 'NR<=6{printf "%-10s %-6s %-6s %s\n", $1, $2, $3, $11}'
5.2.2 监控指标说明
| 指标名称 |
正常范围 |
告警阈值 |
说明 |
| SSH 失败登录/小时 |
< 5 |
≥ 20 |
超过阈值触发暴力破解告警 |
| SUID 文件数量 |
与基线一致 |
任何变化 |
新增 SUID 文件可能是提权后门 |
| 异常外联连接数 |
0 |
≥ 1 |
非业务端口外联需立即排查 |
| CPU 单进程占用 |
< 80% |
≥ 95% 持续 5 分钟 |
挖矿木马典型特征 |
/tmp 目录可执行文件数 |
0 |
≥ 1 |
攻击载荷常落地在 /tmp |
| 新增 crontab 条目 |
与基线一致 |
任何变化 |
持久化后门常用手段 |
| 内核模块数量 |
与基线一致 |
任何变化 |
内核级 Rootkit 检测 |
5.2.3 Prometheus 安全指标采集与告警
node_exporter 提供基础系统指标,安全相关的自定义指标需要通过 textfile collector 注入:
#!/bin/bash
set -euo pipefail
# 安全指标采集脚本,由 cron 每分钟执行
# 输出到 node_exporter 的 textfile 目录
TEXTFILE_DIR="/var/lib/prometheus/node-exporter"
PROM_FILE="${TEXTFILE_DIR}/security_metrics.prom"
TMP_FILE="${PROM_FILE}.tmp"
# SSH 失败登录次数(最近 5 分钟)
ssh_failures=$(journalctl -u sshd --since "5 min ago" --no-pager 2>/dev/null | grep -c "Failed password" || echo 0)
echo "security_ssh_failed_logins_5m ${ssh_failures}" > "${TMP_FILE}"
# SUID 文件数量
suid_count=$(find / -type f -perm -4000 2>/dev/null | wc -l)
echo "security_suid_file_count ${suid_count}" >> "${TMP_FILE}"
# 异常外联连接数
abnormal_conn=$(ss -tnp state established 2>/dev/null | awk '{print $5}' | grep -v -E ":(80|443|53|123|514)$" | grep -c "." || echo 0)
echo "security_abnormal_outbound_connections ${abnormal_conn}" >> "${TMP_FILE}"
# /tmp 下可执行文件数
tmp_exec=$(find /tmp /var/tmp /dev/shm -type f -executable 2>/dev/null | wc -l)
echo "security_tmp_executable_count ${tmp_exec}" >> "${TMP_FILE}"
# 原子替换,避免 node_exporter 读到半写文件
mv "${TMP_FILE}" "${PROM_FILE}"
Prometheus 告警规则示例:
# /etc/prometheus/rules/security_alerts.yml
groups:
- name: security_alerts
rules:
- alert: SSHBruteForceDetected
expr: security_ssh_failed_logins_5m > 20
for: 1m
labels:
severity: warning
annotations:
summary: "SSH 暴力破解检测 - {{ $labels.instance }}"
description: "5 分钟内 SSH 失败登录 {{ $value }} 次"
- alert: SUIDBinaryChanged
expr: changes(security_suid_file_count[1h]) > 0
for: 0m
labels:
severity: critical
annotations:
summary: "SUID 文件数量变化 - {{ $labels.instance }}"
description: "SUID 文件数量发生变化,当前 {{ $value }} 个,可能存在提权后门"
- alert: AbnormalOutboundConnection
expr: security_abnormal_outbound_connections > 0
for: 2m
labels:
severity: warning
annotations:
summary: "异常外联连接 - {{ $labels.instance }}"
description: "检测到 {{ $value }} 个非业务端口外联连接"
- alert: SuspiciousExecutableInTmp
expr: security_tmp_executable_count > 0
for: 1m
labels:
severity: critical
annotations:
summary: "临时目录发现可执行文件 - {{ $labels.instance }}"
description: "/tmp 或 /dev/shm 下存在 {{ $value }} 个可执行文件"
5.3 备份与恢复
5.3.1 系统快照与取证镜像
入侵发生后,第一时间制作磁盘镜像是取证的基础。镜像操作本身不能修改原始数据:
#!/bin/bash
set -euo pipefail
# 磁盘取证镜像脚本
SOURCE_DISK="/dev/sda"
IMAGE_DIR="/mnt/forensic"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
IMAGE_FILE="${IMAGE_DIR}/disk_image_${TIMESTAMP}.raw"
# dd 全盘镜像(适合离线取证)
# bs=4M 提升速度,conv=noerror,sync 遇到坏块不中断
sudo dd if="${SOURCE_DISK}" of="${IMAGE_FILE}" bs=4M conv=noerror,sync status=progress
# 计算镜像哈希
sha256sum "${IMAGE_FILE}" > "${IMAGE_FILE}.sha256"
echo "镜像完成:${IMAGE_FILE}"
echo "SHA256:$(cat "${IMAGE_FILE}.sha256")"
# LVM 快照方式(适合在线取证,对业务影响小)
# 前提:系统使用 LVM 且 VG 有剩余空间
sudo lvcreate -L 10G -s -n forensic_snap /dev/vg0/root
# 挂载快照为只读
sudo mount -o ro /dev/vg0/forensic_snap /mnt/snapshot
# 取证完成后删除快照
# sudo lvremove /dev/vg0/forensic_snap
5.3.2 入侵后恢复流程
恢复不是简单地“删掉恶意文件然后重启”。不彻底的清理只会让攻击者卷土重来。标准流程如下:
1. 评估影响范围
├── 哪些主机被入侵(横向移动排查)
├── 哪些数据可能泄露
├── 攻击者的入侵路径和驻留时间
└── 是否涉及供应链(被入侵主机是否作为跳板攻击了其他系统)
2. 隔离与遏制
├── 网络隔离(iptables DROP 所有非管理流量,不要直接拔网线)
├── 保留现场(内存 dump、磁盘镜像)
└── 冻结相关账号凭据
3. 清除恶意文件
├── 根据取证结果定位所有恶意文件
├── 清理持久化机制(crontab、systemd、rc.local、authorized_keys)
├── 检查并修复被篡改的系统命令
└── 清除内核模块后门(如有)
4. 修复漏洞
├── 修补被利用的漏洞(系统补丁、应用更新)
├── 关闭不必要的服务和端口
└── 修复错误配置(弱密码、未授权访问)
5. 重建受损系统
├── 严重入侵建议重装系统(从可信镜像)
├── 从干净备份恢复业务数据
└── 重新部署应用(不要从被入侵主机复制二进制文件)
6. 安全加固
├── 部署 HIDS(AIDE + auditd + rkhunter)
├── 启用日志远程转发
├── 实施网络分段
└── 所有凭据轮换(SSH 密钥、数据库密码、API Token)
7. 复盘总结
├── 编写事件报告(时间线、影响、根因、改进措施)
├── 更新应急预案
└── 安全意识培训
六、总结
6.1 技术要点回顾
- ✅ 组合检测:文件完整性检测(AIDE)+ Rootkit 扫描(rkhunter/chkrootkit)+ 内核审计(auditd)构成主机入侵检测的核心三驾马车,缺一不可。
- ✅ 日志为王:日志是安全事件排查的生命线,必须实时转发到远端并设置防篡改属性,本地日志在攻击者拿到 root 权限后毫无可信度。
- ✅ 取证优先:应急响应遵循“先取证后清除”原则,易失性数据(内存、网络连接、进程信息)的采集优先级高于磁盘数据。
- ✅ 纵深防御:构建覆盖网络层、主机层、应用层、数据层的纵深防御体系,每一层都假设上一层已被突破,单点防御在真实攻击面前不堪一击。
- ✅ 自动化响应:自动化响应能力决定了 MTTR 的下限,利用 Wazuh + ELK + 自定义 Active Response 脚本可以实现从检测到遏制的闭环。
6.2 进阶学习方向
-
Wazuh 企业级 HIDS 平台
- 集成 AIDE 文件完整性、OSSEC 规则引擎、漏洞扫描、合规检查于一体。
- 与 ELK Stack 深度集成,提供统一的安全事件可视化面板。
- 学习资源:Wazuh 官方文档。
- 实践建议:先在测试环境部署单节点,熟悉规则编写后再推广到生产集群。
-
eBPF 实时入侵检测
- Falco:CNCF 项目,基于系统调用的运行时威胁检测,规则语法直观。
- Tetragon:Cilium 团队出品,支持内核级策略执行(不只是检测,还能阻断)。
- 学习资源:Falco 官方文档、Tetragon GitHub。
- 实践建议:eBPF 对内核版本有要求(≥ 4.18),可优先在容器化环境中落地。
-
MITRE ATT&CK 框架映射
- 将检测规则与 ATT&CK 战术/技术编号对应,量化检测覆盖率。
- 识别防御盲区,有针对性地补充检测能力。
- 学习资源:MITRE ATT&CK for Linux 矩阵。
6.3 参考资料
- CIS Benchmarks - 各操作系统安全基线配置标准。
- AIDE 官方手册 - 文件完整性检测工具详细文档。
- Linux Audit 系统文档 - Red Hat 审计系统配置指南。
- RFC 3227 - 证据收集和保存指南,定义了数字取证证据采集的优先级标准。
- Wazuh 官方文档 - 开源 HIDS 平台部署与规则编写指南。
希望这份详实的指南能帮助你在实际工作中构建起有效的 Linux 主机安全防线。更多深入的技术讨论和实践分享,欢迎在 云栈社区 与广大开发者交流。
附录
A. 命令速查表
# ==================== 应急响应命令速查 ====================
# ----- 用户排查 -----
cat /etc/passwd | awk -F: '$3==0{print $1}' # 查找 UID=0 的用户
cat /etc/passwd | awk -F: '$7!~/nologin|false/{print}' # 可登录用户
lastlog | grep -v "Never" # 有登录记录的用户
last -aiF | head -20 # 最近登录历史
grep "sudo" /var/log/auth.log | tail -20 # sudo 操作记录
# ----- 进程排查 -----
ps auxf # 进程树(含父子关系)
ps aux --sort=-%cpu | head -10 # CPU TOP10
ps aux --sort=-%mem | head -10 # 内存 TOP10
ls -la /proc/*/exe 2>/dev/null | grep deleted # 已删除但仍运行的进程
find /proc/*/fd -ls 2>/dev/null | grep deleted # 已删除但被进程持有的文件
# ----- 网络排查 -----
ss -tnlp # 监听端口
ss -tnp state established # 已建立连接
ss -tnp | awk '{print $5}' | sort | uniq -c | sort -rn # 外联 IP 统计
iptables -L -n -v --line-numbers # 防火墙规则
# ----- 文件排查 -----
find / -ctime -1 -type f 2>/dev/null | head -50 # 最近 24 小时变更的文件
find / -name ".*" -type f -not -path "/proc/*" 2>/dev/null # 隐藏文件
find /tmp /var/tmp /dev/shm -type f -executable # 临时目录可执行文件
rpm -Va 2>/dev/null || dpkg --verify 2>/dev/null # 包完整性校验
# ----- 日志排查 -----
grep "Failed password" /var/log/auth.log | tail -20 # SSH 失败登录
grep "Accepted" /var/log/auth.log | tail -20 # SSH 成功登录
ausearch -k privilege_escalation -ts recent # 提权审计事件
journalctl -p 0..3 --since "24 hours ago" --no-pager # 严重级别日志
B. 配置参数详解
auditd 规则语法:
| 参数 |
说明 |
示例 |
-w |
监控文件/目录 |
-w /etc/passwd |
-p |
权限过滤(r读/w写/x执行/a属性变更) |
-p wa |
-k |
规则标签(用于 ausearch 过滤) |
-k passwd_changes |
-a |
追加规则到列表 |
-a always,exit |
-F arch= |
CPU 架构过滤 |
-F arch=b64 |
-S |
系统调用过滤 |
-S execve |
-F auid>= |
审计 UID 过滤(排除系统进程) |
-F auid>=1000 |
-F dir= |
目录过滤 |
-F dir=/tmp |
-e 2 |
锁定规则(重启前不可修改) |
必须放在规则文件最后 |
AIDE 监控属性:
| 属性 |
含义 |
推荐使用场景 |
p |
权限 |
所有关键文件 |
i |
inode 号 |
检测文件替换 |
n |
链接数 |
检测硬链接攻击 |
u |
用户属主 |
权限变更检测 |
g |
组属主 |
权限变更检测 |
s |
文件大小 |
二进制文件篡改检测 |
sha256 |
SHA256 哈希 |
高安全要求场景 |
md5 |
MD5 哈希 |
一般场景(速度快) |
m |
修改时间 |
配置文件监控 |
S |
检查文件是否变大 |
日志文件监控 |
常用组合:
NORMAL = p+i+n+u+g+s+m+sha256 — 关键系统文件
DATAONLY = p+n+u+g+s+sha256 — 数据文件(忽略时间戳)
LOG = p+u+g+S — 日志文件(只增不减)
C. 术语表
| 术语 |
英文 |
解释 |
| HIDS |
Host-based Intrusion Detection System |
主机入侵检测系统,运行在目标主机上监控异常行为 |
| NIDS |
Network-based Intrusion Detection System |
网络入侵检测系统,基于流量分析检测攻击 |
| IOC |
Indicator of Compromise |
入侵指标,用于识别已发生的安全事件的技术特征 |
| C2/C&C |
Command and Control |
命令与控制服务器,攻击者远程操控被入侵主机的通信节点 |
| TTPs |
Tactics, Techniques and Procedures |
战术、技术和过程,描述攻击者行为模式的框架 |
| MTTR |
Mean Time To Respond |
平均响应时间,从检测到安全事件到完成遏制的时间 |
| ATT&CK |
Adversarial Tactics, Techniques & Common Knowledge |
MITRE 提出的攻击行为知识库和分类框架 |
| Rootkit |
Root Kit |
一组用于隐藏入侵痕迹并维持 root 权限的恶意工具集合 |
| SUID |
Set User ID |
文件权限位,执行时以文件属主身份运行而非当前用户 |
| eBPF |
extended Berkeley Packet Filter |
Linux 内核虚拟机技术,可安全地在内核态运行自定义程序 |
| WAF |
Web Application Firewall |
Web 应用防火墙,针对 HTTP 层攻击的防护设备 |
| SIEM |
Security Information and Event Management |
安全信息与事件管理平台,集中收集和分析安全日志 |