凌晨两点被电话叫起来,登上跳板机一看,某台业务机的 CPU 跑到 300%,出口流量曲线像被人拽着往上拉,登录日志里一串陌生 IP 在反复试密码。这种场景,做过几年运维的人多少都碰到过。Linux 入侵排查这几个字听着像是安全团队的专属活儿,实际上一线顶上去的往往是系统运维和开发,因为机器在你手里,第一个被问"这台机器怎么了"的也是你。我处理过的案例里,真正精心设计的定向攻击是少数,更多的是弱口令被撞开之后塞了个挖矿程序、老版本组件被打穿后落了一堆脚本、或者某个测试账号的密钥泄露被人当成跳板。
这篇内容想解决的是一个很具体的问题:当一台 Linux 机器出现说不清道不明的异常时,从哪里下手、按什么顺序查、哪些东西必须先存下来、哪些动作绝对不能做。命令都是能直接粘上去跑的,参数会解释为什么这么选,也会写清楚哪些结论不能只凭单一证据下判断。适合手里管着几台到几百台机器、需要自己动手排查的运维和开发,也适合刚开始接触主机安全方向、想建立一套完整排查思路的朋友当手册翻。
1. 排查之前先想清楚:整台机器到底在查什么
1.1 从"现象"倒推"证据链"的思路
很多人一上手就是top看一眼、ps扫一遍,看到个陌生进程 kill 掉,然后跟领导说处理完了。过两天同样的问题再来一次,才发现根子还在。入侵排查的本质不是"找到可疑进程并杀掉",而是建立一条能自洽的证据链:什么时间、从哪个入口、用什么身份、做了什么、留下了什么、靠什么活下来。这条链上任何一环缺失,你的结论都是猜测。
所以我习惯先把现象归类。CPU 或内存持续高位,大概率是挖矿类程序;出口流量异常但 CPU 正常,可能是被当成代理节点或者在做数据外传;磁盘空间莫名减少,要怀疑日志被灌或者被人塞了打包的数据;SSH 登录变慢、命令执行有延迟,可能是 DNS 被改或者有程序在劫持网络请求;完全看不出异常但监控报端口扫描,那可能是机器已经被当成跳板去扫别人了。不同的现象对应不同的排查优先级,先分类再动手,比上来就全盘扫要高效得多。
这里有个容易被忽略的点:现象不等于原因。CPU 高可能是因为挖矿,也可能是因为某个被替换过的系统命令在死循环,还可能是定时任务里塞了个每分钟跑一次的重型脚本。你得把现象当成线索的起点,而不是结论本身。我一般会在纸上或者文档里先列三列:观察到什么、可能的解释有哪些、用什么命令去验证或排除。这个习惯看着笨,但能有效防止查到一半跑偏。
1.2 顺序为什么不能乱:先保现场,再动手
排查顺序这件事,踩过坑的人才知道有多重要。见过最典型的错误操作是:发现机器异常,第一反应reboot,重启完发现进程没了、内存里的东西没了、/proc里的信息全空了,只剩一堆日志还不一定完整。还有人是先kill -9把可疑进程干掉,结果那个进程是靠定时任务拉起来的,杀掉之后一分钟又活过来,反而打草惊蛇让对方把痕迹清得更干净。
正确的顺序应该是:隔离网络影响 → 固定现场证据 → 分析 → 处置 → 加固复盘。第一步的"隔离"不是让你直接拔网线,而是先判断这台机器对外提供什么服务、断网会不会影响业务、能不能通过安全组或者防火墙先把异常方向的连接掐掉而保留运维通道。这一步想清楚再动,比事后解释为什么业务挂了要容易得多。
固定证据这部分下面会单独展开讲。这里只说一个原则:任何可能被修改的东西,在动手之前先留一份副本。进程列表、网络连接、登录记录、关键目录的文件列表、/proc下的关键信息,全部落盘。你可以理解为给机器拍一张"现场照片",后面所有分析都基于这张照片,而不是基于一个已经被你的操作污染过的系统。
1.3 三条最常见的入侵路径与对应切入点
从实践来看,绝大多数主机失陷都集中在三条路径上,知道这个分布能帮你快速定位方向。
第一条是远程登录入口失守,包括 SSH 弱口令、密钥泄露、数据库或中间件暴露在公网且用了默认密码。判断方法很直接:看登录日志里有没有大量失败记录后紧跟一次成功、成功登录的源 IP 是不是眼熟的办公网段、登录时间是不是在非工作时段。这条路径占比最高,也最好查。
第二条是应用层漏洞被打穿,比如 Web 服务存在文件上传、命令执行类问题,攻击者通过 Web 进程的用户身份落地脚本。这种情况下登录日志往往是干净的,但 Web 目录下会多出一些不该存在的文件,Web 进程会 fork 出奇怪的子进程,比如www-data用户下跑着一个bash或者python进程在对外连接。
第三条是供应链或组件问题,比如某个依赖包被投毒、某个开源组件版本存在已知问题。这条最难查,因为落地的东西可能伪装得很好,行为也接近正常业务。应对办法主要靠文件完整性校验和流量侧的特征比对。
把这三条路径记在心里,排查的时候先花五分钟判断"最可能是哪条",能省掉大量无头苍蝇式的时间。
2. 现场保护与信息采集:动手之前先把证据固定住
2.1 为什么第一步是留证而不是"删干净"
有个很现实的矛盾:业务负责人希望机器赶紧恢复,安全侧希望把证据留全,两边经常打架。我的处理原则是,在业务可承受的范围内,尽可能先留证再处置。原因很实在——你没法证明自己处理干净了,如果后面复发或者需要追溯影响范围,没有证据就只能靠猜。
留证这件事还有一个隐性价值:它能保护你自己。万一后续要写报告、要做责任界定、要向上面解释"到底丢了什么数据",一份完整的现场记录就是最硬的底气。我见过因为没留证、事后无法判断数据是否外泄,导致整个团队被迫按最坏情况处理的情况,代价远比多花半小时收集信息大。
实际操作中,如果业务确实不能停,可以做折中:先把内存和网络状态这类"一旦重启就没了"的信息抓下来,进程和文件层面的东西可以边分析边补。易失性数据的优先级永远高于磁盘数据,这个顺序不能反。
2.2 一份可以直接照抄的采集清单
下面这套命令我基本是背下来的,出问题时按顺序跑一遍,输出统一重定向到一个目录里。注意所有输出都要带时间戳,方便后面做时间线。
# 建一个带时间的证据目录 mkdir -p /tmp/ir_$(date +%Y%m%d_%H%M%S) && cd $_ # 系统基础信息 date; uptime; uname -a; cat /etc/os-release hostname; whoami; id # 登录相关 who; w; last -n 50; lastb -n 50 # 进程与网络(易失性最高,优先) ps auxf > ps_auxf.txt ps -eo pid,ppid,user,cmd,lstart,etime > ps_detail.txt ss -antp > ss_antp.txt ss -anup > ss_anup.txt lsof -i -P -n > lsof_net.txt # 路由与 ARP ip addr; ip route; arp -an # 已加载模块 lsmod > lsmod.txt跑完后把这些文件打包带走,别留在问题机器上太久。有个细节值得说:ps -eo ... lstart这个参数会打印进程的精确启动时间,这个信息在判断"进程是不是在某个可疑登录之后起来的"时非常关键,比只看ps aux有用得多。lsof -i -P -n里的-P是不做端口名转换、-n是不做 IP 反解,这两个参数能避免排查时因为 DNS 查询卡住,也能防止你的查询行为被对方记录下来。
清单里的lastb经常被漏掉,它读的是登录失败记录,配合last的成功记录一起看,才能判断出"试了多少次、第几次成功的"。
2.3 采集阶段的几个坑
第一个坑是在问题机器上下载工具。很多人习惯装个htop、装个chkrootkit再开始查,这个动作风险很高,因为你不知道系统里的包管理器有没有被动过手脚,也不知道下载过程会不会触发对方设定的告警。正确做法是在自己的干净机器上准备好工具,用离线方式传过去,或者干脆只用系统自带的命令。
第二个坑是命令本身被替换。排查时必须养成一个习惯:对关键命令做校验。which ps、rpm -V procps或者dpkg -V procps,确认ps、netstat、ls、find这些常用命令的二进制没有被改过。判断方法不只是看哈希,还要看文件的修改时间是不是和系统其他文件明显不一致。
第三个坑是输出被重定向到可疑目录。别把证据文件放在/tmp下的公共位置然后忘了清理,也别放在 Web 目录里。我一般会放在一个权限 700 的临时目录,分析完立刻拷走。
提示:采集过程中不要执行任何会改变系统状态的命令,包括
kill、rm、systemctl restart、yum install。所有分析命令尽量用只读方式跑。
3. 账户与登录排查:先搞清楚"谁进来过"
3.1 账号文件的交叉验证
/etc/passwd和/etc/shadow是必看的,但重点不是看有没有多出来的账号,而是看细节对不对。比如某个新账号的 UID 是 0,那就是一个隐藏的 root;某个系统账号的 shell 从/sbin/nologin被改成了/bin/bash,说明有人给它开了登录权限;某个账号的家目录指向/dev/shm这种奇怪位置,基本可以确定有问题。
我一般会跑这么几条做交叉比对:
# 找 UID 为 0 的账号 awk -F: '$3==0 {print $1, $3, $7}' /etc/passwd # 找能登录但不太正常的账号 awk -F: '$7 !~ /nologin|false/ {print $1, $3, $6, $7}' /etc/passwd # 找最近被修改过的账号文件 stat /etc/passwd /etc/shadow /etc/group /etc/sudoers # 空密码账号(输出为空则正常) awk -F: '($2=="") {print $1}' /etc/shadowstat那一步特别重要。/etc/passwd的修改时间如果在系统安装之后很久,而你最近没做过任何账号变更,那就是一个强信号。/etc/sudoers和/etc/sudoers.d/下的文件同理,经常被用来给普通账号加免密提权。
3.2 登录记录里那些容易被忽略的细节
last看的是/var/log/wtmp,lastb看的是/var/log/btmp,lastlog看的是每个账号最后一次登录时间。这三份数据要一起看。我关注的点有几个:成功登录的源 IP 里有没有非公司出口的地址;登录时间是不是集中在凌晨;某个平时不用的账号有没有突然登录;lastlog里显示"从未登录"的账号如果出现在last里,那就对不上了。
还有个位置很多人不知道:/var/log/secure(Debian 系是/var/log/auth.log),这里面记录的是认证过程的原始日志,包括 sudo 使用、su 切换、SSH 认证方式(密码还是密钥)。用grep "Accepted" /var/log/secure找成功登录,grep "Failed"找失败尝试,如果 5 分钟内失败了几千次然后跟着一次成功,基本可以确定是爆破进去的。
# 登录成功的记录,按 IP 聚合看次数 grep "Accepted" /var/log/secure* | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -20 # 失败次数最多的源 IP grep "Failed password" /var/log/secure* | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -20 # 看 sudo 的使用记录 grep -i "sudo" /var/log/secure* | grep -v "pam_unix"注意日志文件可能是轮转过的,secure-20240101这种也要一起 grep,上面的通配符就是干这个用的。有些入侵者会清理secure,但经常忘了清理压缩包或者轮转文件,这些边角料反而成了突破口。
3.3 sudo 与密钥后门
提权痕迹主要看两个地方。一个是sudo日志,正常运维用 sudo 是有规律的,如果出现半夜用某个业务账号执行sudo -i、sudo su -,那就得追。另一个是sudoers的配置变更,特别是NOPASSWD这种免密配置,正常环境里应该严格控制数量。
密钥后门比账号后门更隐蔽。检查每个用户家目录下的~/.ssh/authorized_keys,看里面的公钥是不是都是你认识的。很多人只检查 root 的,忽略了业务账号,而业务账号恰恰是攻击者最喜欢挂密钥的地方,因为它不显眼。
# 列出所有用户的 authorized_keys 及修改时间 for d in /root /home/*; do f="$d/.ssh/authorized_keys" [ -f "$f" ] && echo "== $f" && stat -c '%y %s' "$f" && cat "$f" done # 全局搜一遍有没有藏在别处的密钥文件 find / -name "authorized_keys*" -not -path "/proc/*" 2>/dev/null同时别忘了看/etc/ssh/sshd_config,重点确认PermitRootLogin、PasswordAuthentication、Port这几个值有没有被改过,以及有没有出现AuthorizedKeysFile指向奇怪路径的配置。改配置开放密码登录、再把密钥写进去,是很常见的一套组合。
4. 进程与网络连接排查:抓正在干活的东西
4.1 进程排查的三板斧和 /proc 的正确用法
进程这块,我的习惯是先看整体再看个体。整体用ps auxf看进程树,重点找两类:不该有的父子关系和路径奇怪的可执行文件。比如 Web 容器进程底下突然多出一个sh子进程,或者一个进程的可执行文件路径是/tmp/xxx、/dev/shm/xxx、/var/tmp/xxx,这几种情况基本可以直接标红。
ps auxf里的f参数会显示树状结构,比平铺列表更容易看出父子关系。我一般会再加一个按启动时间排序的视图,按时间倒序看最近起来的进程:
ps -eo pid,ppid,user,pcpu,pmem,lstart,cmd --sort=-lstart | head -40光看ps不够,因为它的输出可能被篡改。真正可靠的是/proc文件系统,它是内核直接暴露的,绕过用户态命令。几个关键文件:
# 进程的完整命令行(用 \0 分隔,能看出被空格伪装的参数) tr '\0' ' ' < /proc/<PID>/cmdline; echo # 可执行文件的真实路径,注意看是否带 " (deleted)" ls -l /proc/<PID>/exe # 进程的工作目录 ls -l /proc/<PID>/cwd # 进程打开的文件 ls -l /proc/<PID>/fd # 进程的环境变量,经常能从这里看到被注入的东西 tr '\0' '\n' < /proc/<PID>/environ/proc/<PID>/exe显示(deleted)是个非常典型的信号——攻击者把恶意文件写进去、启动、然后删掉源文件,进程还在跑但文件没了。这时候可以通过/proc/<PID>/exe把文件捞出来做分析,或者用lsof +L1找出所有被删除但仍被占用的文件。
4.2 连接视角:监听端口与已建立的会话
进程和连接要对着看。先看监听:
ss -antlp重点关注监听在0.0.0.0上的非预期端口,以及由非常规用户(不是 root、不是业务账号)持有的监听。有些后门会监听高端口,比如 4 万以上的随机端口,正常业务很少这么干。
再看已建立的连接:
ss -antp state established这一步的目的是找异常外连。判断标准有三个:目的 IP 不属于你已知的业务依赖、目的端口不符合常见服务(比如往 3333、5555、7777 这种端口连,挖矿和远控常用)、连接持续存在且流量不小。把可疑连接和 PID 对上,再回到/proc去看这个进程到底是谁。
# 把进程、连接、可执行文件路径串起来看 ss -antp | grep ESTAB | awk '{print $6}' | sort -u如果机器上装了lsof,lsof -i -P -n的输出比ss更直观,能看到进程名、PID、用户和连接状态在同一行。两手都跑一遍,结果互相印证。
4.3 进程看不见怎么办:隐藏进程与内核模块
有一种情况是ps和top里都看不到可疑进程,但 CPU 就是高的,或者某个端口确实在监听却找不到持有者。这时候要怀疑两种可能:一是ps这类命令被替换了,二是存在内核级的隐藏。
对付第一种,最土也最有效的办法是直接数/proc下的数字目录,和ps的输出做差集:
# /proc 里的 PID 列表 ls -d /proc/[0-9]* | awk -F/ '{print $3}' | sort -n > /tmp/proc_pids.txt # ps 能看到的所有 PID ps -eo pid --no-headers | tr -d ' ' | sort -n > /tmp/ps_pids.txt # 差集:/proc 有但 ps 没有的,高度可疑 comm -23 /tmp/proc_pids.txt /tmp/ps_pids.txt第二种看内核模块:
lsmod cat /proc/modules对比模块列表和系统正常状态下的差异,特别关注那些名字看起来像正经驱动但加载时间很新的模块。根目录下/lib/modules/$(uname -r)/里有没有多出来的.ko文件,也值得看一眼。这类排查比较深,如果确认有内核级问题,一般建议直接重装系统而不是尝试清理,因为清理不干净的代价太大。
注意:不要在没有备份的情况下
rmmod卸载可疑模块,可能导致系统直接 panic。真要处理,先在测试环境验证。
5. 持久化排查:把复发的根拔掉
5.1 定时任务是重灾区
处理过复发案例的人都知道,定时任务是最常见的持久化手段,没有之一。原因很简单:写进去之后不需要进程常驻,到点就拉起来,平时看进程列表干干净净。
检查范围要覆盖全:
# 所有用户的 crontab for u in $(cut -f1 -d: /etc/passwd); do echo "== $u"; crontab -l -u $u 2>/dev/null done # 系统级定时任务 cat /etc/crontab ls -la /etc/cron.d/ /etc/cron.hourly/ /etc/cron.daily/ /etc/cron.weekly/ cat /etc/cron.d/* # 直接看 spool 目录,绕过 crontab 命令 ls -la /var/spool/cron/ /var/spool/cron/crontabs/最后那一步很关键。crontab -l读的是同一个位置,但如果crontab这个二进制被动过,输出就会被过滤。直接看/var/spool/cron/下的文件内容更可靠。
看定时任务的时候,重点不是有没有,而是跑的是什么。常见伪装是:命令名看起来像系统脚本(/etc/cron.d/0hourly、logrotate),实际指向一个自定义脚本;或者用curl、wget拉远程内容执行;或者用*/1 * * * *这种每分钟一次的高频调度去维持一个守护进程。看到*/1加bash -c的组合,基本可以直接判死。
systemd环境下还有一套:systemctl list-timers --all能看到所有定时器,有些后门会伪装成.timer加.service的组合,比 crontab 更隐蔽。
5.2 自启服务与动态链接劫持
开机自启的检查面比较广,我一般按这个顺序过一遍:
| 位置 | 说明 | 检查命令 |
|---|---|---|
| systemd 服务 | 最常见的自启方式 | systemctl list-unit-files --state=enabled |
| init.d 脚本 | 老系统遗留,容易被忽略 | ls -la /etc/init.d/ |
| rc.local | 部分系统仍会执行 | cat /etc/rc.local |
| profile 类文件 | 登录时触发 | cat /etc/profile /etc/profile.d/*.sh ~/.bashrc ~/.bash_profile |
| systemd 用户级 | 用户登录后触发 | ls -la ~/.config/systemd/user/ |
profile这一类特别值得说。/etc/profile.d/下多一个.sh文件,用户一登录就执行,而且写得很像正常的路径配置。检查时看文件修改时间和内容,正常的 profile 脚本不会有curl | bash、nc -e、base64 -d这类东西。同样,~/.bashrc和~/.bash_logout也要看,后者是登出时触发,更容易被忽略。
动态链接库劫持是偏高级的手法。检查/etc/ld.so.preload这个文件,如果存在且里面写了一个.so路径,基本可以确定有问题——正常系统里这个文件通常不存在。再配合ldd看关键命令依赖的库路径有没有指向非常规位置。
ls -l /etc/ld.so.preload 2>/dev/null && cat /etc/ld.so.preload ldd /bin/ls5.3 持久化位置速查表
整理一份我常用的对照表,排查时按这个过一遍,覆盖率能到九成以上:
| 类型 | 具体位置 | 重点关注 |
|---|---|---|
| 定时任务 | /var/spool/cron/、/etc/cron.d/、/etc/crontab | 高频调度、远程拉取执行 |
| systemd | /etc/systemd/system/、/usr/lib/systemd/system/ | 新增加的 unit、ExecStart 指向临时目录 |
| 开机脚本 | /etc/rc.local、/etc/init.d/ | 内容被追加 |
| Shell 配置 | /etc/profile.d/、~/.bashrc、~/.bash_profile | 远程下载、编码执行 |
| 动态链接 | /etc/ld.so.preload、/etc/ld.so.conf.d/ | 文件存在即为异常 |
| SSH | ~/.ssh/authorized_keys、sshd_config | 陌生公钥、密码登录被开启 |
| PAM | /etc/pam.d/ | 被加入自定义模块 |
| 账号 | /etc/passwd、/etc/shadow、/etc/sudoers.d/ | UID 0、免密提权 |
这张表建议收藏,排查时逐项打勾,比凭记忆靠谱。
6. 文件与日志排查:找落地留下的痕迹
6.1 按时间线找新增和改动过的文件
文件排查的核心是时间线。你先确定一个大概的失陷时间窗口,然后在这个窗口内找新增和修改过的文件。时间窗口怎么定?从登录日志里的异常登录时间、进程的启动时间、可疑连接的首次出现时间倒推,取最早的那个作为起点,再往前留一点余量。
# 找 7 天内修改过的可执行文件,排除系统目录和 proc find / -xdev -type f -mtime -7 \( -perm -u+x -o -name "*.sh" -o -name "*.py" \) \ -not -path "/proc/*" -not -path "/sys/*" -not -path "/usr/*" 2>/dev/null | head -50 # 找最近修改的隐藏文件 find / -xdev -name ".*" -type f -mtime -7 -not -path "/proc/*" 2>/dev/null # 按修改时间排序看某个目录的最近变化 ls -lat /tmp /var/tmp /dev/shm-xdev这个参数很实用,它让find不跨文件系统,避免扫到挂载的网络盘或者容器卷上,速度和准确性都会好很多。/tmp、/var/tmp、/dev/shm这三个目录是必看的,尤其是/dev/shm,它挂在内存里,重启就没了,很多临时落地的文件会放这儿,而且不太引人注意。
还一个思路是按大小找。挖矿程序、打包好的数据文件通常体积不小,可以按大小筛:
find / -xdev -type f -size +10M -mtime -7 -not -path "/proc/*" 2>/dev/null | head -306.2 日志该看哪几个地方
日志这块的思路是"入口看认证,行为看系统,应用看业务"。认证日志前面讲过,这里重点说另外两类。
系统日志/var/log/messages(Debian 系是/var/log/syslog)里能看到的线索包括:服务启动失败的记录、内核模块加载的记录、OOM killer的记录(如果内存被打满)、以及一些网络相关的告警。用grep -i "error\|fail\|deny"快速过一遍,比从头读效率高。
审计日志如果开了auditd,价值极高,/var/log/audit/audit.log里能查到命令执行、文件访问、权限变更的完整记录。很多环境默认没开,建议事后补上,但事发时如果没开就查不了,只能靠其他线索。这也是我要强调的一点:排查能力的天花板,很大程度上由平时的日志留存决定。
应用日志要看业务自身的情况,重点是 Web 访问日志里的异常请求。看什么?状态码 200 但响应体异常的请求、URL 里带编码字符或者命令拼接特征的请求、同一个 IP 短时间内大量访问同一路径、User-Agent 是空或者是扫描器特征。这几类都值得单独拉出来看。
# 找状态码 200 但 URL 里有可疑字符的请求 grep ' 200 ' access.log | grep -Ei '(%27|%3B|%7C|base64|eval|exec|/tmp/)' | head -20 # 按 IP 统计访问量,看有没有明显异常的 awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -206.3 校验与完整性比对
文件完整性校验是判断"系统命令有没有被替换"的关键手段。包管理器自带的校验最方便:
# RPM 系 rpm -Va --nofiles --nodigest # Debian 系 dpkg -V # 单独校验某个包 rpm -V coreutilsrpm -Va的输出里,S表示大小变了、M表示权限变了、5表示内容哈希变了、T表示时间戳变了。对ps、ls、netstat、ss、find、top、crontab这些排查常用命令,只要出现5就要高度警惕,说明二进制被换过。
如果系统里没有包管理器或者记录不全,那就手工算哈希做基线比对。前提是你手里有干净机器的同版本文件,或者有事先保存的哈希清单。这也是我一直建议的做法:在上线初期就给关键命令和核心配置文件做一次哈希基线,存到别的地方去。事后补这个动作,价值会打折扣。
sha256sum /bin/ls /bin/ps /usr/bin/netstat /usr/bin/find /usr/bin/top7. 常见问题与排查技巧实录
7.1 高频问题速查表
整理一份排查过程中最常被问到的对应关系,遇到现象直接查表定位方向:
| 现象 | 优先怀疑 | 首查命令 |
|---|---|---|
| CPU 持续高位,无明显业务增长 | 挖矿程序、死循环脚本 | ps -eo pcpu,pid,cmd --sort=-pcpu |
| 出口流量异常但 CPU 正常 | 数据外传、被当跳板 | ss -antp state established |
| 磁盘空间莫名减少 | 日志被灌、数据打包 | du -sh /* | sort -h |
| SSH 登录慢、命令执行卡 | DNS 被改、网络被劫持 | cat /etc/resolv.conf、ip route |
| 进程杀了又起来 | 定时任务、守护脚本 | ls /var/spool/cron/、systemctl list-timers |
ps看不到但端口在监听 | 命令被替换、内核级隐藏 | ls /proc/[0-9]*与ps做差集 |
| 账号密码改了还是能登进来 | 密钥后门、PAM 后门 | 遍历authorized_keys、查pam.d |
| 文件删除后空间不释放 | 进程持有已删除文件 | lsof +L1 |
7.2 几条踩过坑才明白的经验
第一,别迷信单一命令的输出。任何基于用户态工具的判断,前提都是这个工具可信。所以关键结论至少要用两种方式交叉验证:进程用ps和/proc对,网络用ss和lsof对,账号用文件内容和命令输出对。对不上的地方,往往就是问题所在。
第二,优先看"最近变化的"而不是"看起来可疑的"。新手容易盯着名字奇怪的文件看,但攻击者起名字往往很会伪装。真正可靠的筛选维度是时间:这台机器上周还好好的,这周多了哪些东西、哪些文件被改过、哪些服务是新注册的,这个范围比全盘扫描小得多,也准得多。
第三,处置前先想清楚"影响范围"。一台机器中招,要立刻问三件事:它的密钥或者凭据能不能访问别的机器、它的配置里有没有内网其他机器的地址和密码、它有没有挂载共享存储。很多时候清理一台机器只要半小时,排查横向影响要两三天。这个顺序别搞反。
第四,重装是最后手段,但也是必要手段。如果确认存在内核级隐藏或者关键系统库被替换,别纠结,直接重装加配置重建。清理的成本和残留风险比起来不划算,尤其是业务机器,稳定比省事重要。
第五,事后一定要补日志和基线。每次处理完,我都会检查这台机器的日志留存周期、审计配置、关键文件基线有没有做。这次排查靠的是运气找到线索,下次就得靠数据。把auditd开起来、把登录日志留存时间拉长、把关键命令的哈希存到独立位置,这三件事做完,下次再出事排查效率能翻倍。
最后分享一个我自己一直在用的习惯:给每台机器准备一个只读的排查脚本,所有采集命令都写在里面,出事时一条命令跑完,输出打包。这样既避免了手忙脚乱时漏项,也避免了在紧张状态下敲错命令改坏现场。脚本本身放在版本库里维护,隔一段时间根据新踩的坑补几条,慢慢就成了一套自己的东西。