CPU 莫名跑满、带宽夜里打满、云厂商发来违规外连警告、SSH 登录变慢——这些信号出现时,运维最需要的能力不是会多少命令,而是知道按什么顺序查、什么能碰什么不能碰。应急响应最常见的错误有两个:一是慌乱中直接删掉可疑文件,破坏了证据也未必除根;二是只把进程杀掉就宣布恢复,结果过几天又复发。
这篇文章给出一套可执行的排查顺序:先隔离保护现场,再查进程、网络、启动项、计划任务、账号、SSH 公钥和可疑文件,最后给出处置与重建建议。核心结论先放在前面:对确认被植入后门的机器,重装系统并从干净备份恢复,是唯一可靠的处置方式,原地清理只能作为临时止血。
第一步:隔离与保护现场
发现异常后的第一反应常常是"赶紧把那个进程杀掉",但在摸清情况之前这么做有几个问题:杀掉进程会丢失内存中的证据,触发木马的自我保护逻辑(比如由守护进程重新拉起,或者干脆删除自身文件),也让你无法观察它的外连目标和行为模式。
更合理的顺序是:
先做快照或镜像。 云平台支持对系统盘做快照,这一步能在不影响运行的前提下保留磁盘现状,供后续分析或取证使用。快照期间业务仍可运行,代价只是磁盘 IO 略高。
再决定网络隔离策略。 完全断网会让需要外连的木马失去控制通道,但也会让你无法观察它的行为,同时可能影响业务。折中做法是:在安全组或防火墙层面先阻断它对外的可疑连接,保留管理通道(且管理通道要限制来源 IP)。如果已经确认是挖矿或外发数据的木马,则应尽快阻断其外连。
不要急着关机。 内存中的进程、网络连接、加载的模块都是重要证据,关机就全部丢失。除非是勒索软件正在加密文件,那需要立即隔离止损。
保护关键证据。 登录日志、命令历史、Web 访问日志都可能被攻击者清理,先把它们复制一份到别处:
# 打包关键日志,注意放到不会被清理的位置
sudo mkdir -p /root/incident-$(date +%F)
sudo cp -a /var/log/secure /var/log/auth.log /var/log/messages /var/log/syslog \
/var/log/nginx /var/log/cron /root/incident-$(date +%F)/ 2>/dev/null
sudo cp -a /etc/passwd /etc/shadow /etc/sudoers /etc/crontab /root/incident-$(date +%F)/
history > /root/incident-$(date +%F)/history.txt
同时记录当前时间点的进程与网络快照,这两份快照是后面所有分析的基础:
ps auxww > /root/incident-$(date +%F)/ps.txt
ss -antp > /root/incident-$(date +%F)/ss.txt
sudo netstat -antp 2>/dev/null >> /root/incident-$(date +%F)/ss.txt
第二步:查异常进程
看进程不要只看 top 的第一页。挖矿类木马会伪装进程名,常见的手法是起一个名字类似 kworker/2:1、systemd-daemon、dbus-daemon、Xorg、nginx 的进程,看起来和系统进程一模一样。
ps auxww --sort=-%cpu | head -20
top -b -n 1 | head -30
ps -eo pid,ppid,user,comm,%cpu,%mem,etime,args --sort=-%cpu | head -20
关键识别技巧是看进程的可执行文件路径。伪装的进程名可以随便改,但 /proc/PID/exe 指向的真实文件改不了(除非攻击者替换了文件本身):
# 查看 PID 对应的真实可执行文件
sudo ls -l /proc/1234/exe
sudo readlink -f /proc/1234/exe
# 查看进程当前工作目录
sudo ls -l /proc/1234/cwd
# 查看进程打开的文件
sudo ls -l /proc/1234/fd
sudo lsof -p 1234
# 查看进程的父进程和启动时间
ps -o pid,ppid,lstart,args -p 1234
如果 ps 里显示进程名是 kworker/2:1,但 ls -l /proc/1234/exe 指向 /tmp/.x11-unix/systemd 或者显示 (deleted),那基本可以确认是恶意程序。(deleted) 这个标记尤其重要:它表示进程正在运行一个已经从磁盘上删除的文件,这是木马自删除隐藏的典型手法。
另一个技巧是找没有父进程或父进程为 1 的可疑进程,以及比对 ps 与 /proc 的差异。有些 rootkit 会隐藏进程,让 ps 看不到但 /proc 里存在:
# 列出 /proc 下所有数字目录,与 ps 结果比对
ls -d /proc/[0-9]* | wc -l
ps -e --no-headers | wc -l
# 两者数量差异过大时要警惕
第三步:查网络连接与外连
挖矿、反弹 shell、数据外发都表现为异常外连。这一步往往比查进程更快见效。
sudo ss -antp # 所有 TCP 连接及对应进程
sudo ss -antup # 含 UDP
sudo ss -antp state established | head -40
sudo ss -antp | grep -v '127.0.0.1' # 排除本机通信,看外连
重点看这几类:
- 连接到陌生 IP 的高端口(比如 3333、5555、8080、14444、45700 这类),挖矿木马连接矿池常用这些端口。
- 本地监听在奇怪端口上的进程,可能是反弹 shell 或后门。
- 大量处于 SYN_SENT 或 ESTABLISHED 但目标分散的连接,可能是扫描或外发数据。
确认外连目标后,先用防火墙阻断观察,而不是立刻杀进程:
# 阻断到某个可疑 IP 的出站(Debian、Ubuntu)
sudo ufw deny out to 1.2.3.4
# RHEL 系
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" destination address="1.2.3.4" drop'
sudo firewall-cmd --reload
风险提示:添加出站拒绝规则前确认目标不是业务依赖(比如数据库、对象存储、License 服务器)。阻断后要观察业务是否异常,异常就立即删掉规则。
第四步:查启动项与计划任务
木马要能重启后继续运行,必须落地到某个持久化位置。这是排查的重点,也是很多人只杀进程不查持久化导致复发的原因。
systemd 服务:
sudo systemctl list-unit-files --state=enabled
sudo systemctl list-units --type=service --state=running
sudo ls -l /etc/systemd/system/ /lib/systemd/system/ /usr/lib/systemd/system/
sudo systemctl status 可疑服务名
重点看最近新建或修改的 unit 文件,以及名字奇怪的服务。看到可疑服务后,先看它的内容再决定怎么处理:
sudo systemctl cat 服务名
传统启动项:
cat /etc/rc.local # 存在即需检查
ls -l /etc/rc.d/rc.local /etc/rc.local
ls -l /etc/profile.d/ # 用户登录即执行
cat ~/.bashrc ~/.bash_profile ~/.profile /etc/bashrc /etc/profile
.bashrc 和 /etc/profile.d/ 下的脚本会在每次登录或开 shell 时执行,是植入命令的常见位置。检查时要看有没有可疑的 curl ... | sh、base64 编码的命令、或者指向 /tmp、/dev/shm 的执行语句。
计划任务:
sudo crontab -l -u root
for u in $(cut -d: -f1 /etc/passwd); do echo "== $u =="; sudo crontab -l -u $u 2>/dev/null; done
sudo ls -la /etc/cron.d/ /etc/cron.daily/ /etc/cron.hourly/ /etc/cron.weekly/ /etc/cron.monthly/
sudo cat /etc/crontab
sudo ls -la /var/spool/cron/ /var/spool/cron/crontabs/
注意 crontab 里那些每隔几分钟执行一次、命令经过 base64 或混淆、或者 curl/wget 下载后执行的条目。有些木马会把任务写进 /etc/cron.d/ 下一个看似正常的文件名,逐条看内容,不要只看文件名。
systemd timer 是较新的持久化方式,容易被忽略:
systemctl list-timers --all
sudo ls -l /etc/systemd/system/*.timer /lib/systemd/system/*.timer
第五步:查账号、公钥与权限
攻击者拿到权限后通常会留后门账号或直接放公钥,这样即使口令改了也能进来。
# 检查账号
cat /etc/passwd
sudo awk -F: '($3 == 0) {print "UID 0: " $1}' /etc/passwd
sudo awk -F: '($2 == "") {print "空口令: " $1}' /etc/shadow
sudo grep -E ':/bin/(bash|sh)$' /etc/passwd # 有登录 shell 的账号
# 检查登录记录
last -30
lastlog | grep -v 'Never'
w
who
# 检查 sudo 权限
sudo cat /etc/sudoers
sudo ls -l /etc/sudoers.d/
sudo grep -r 'NOPASSWD' /etc/sudoers /etc/sudoers.d/
# 检查 SSH 公钥
cat ~/.ssh/authorized_keys
sudo find / -name authorized_keys -o -name authorized_keys2 2>/dev/null
sudo ls -la /root/.ssh/ /home/*/.ssh/
authorized_keys 里的每一条都要能解释来源。看到不认识的公钥,说明对方已经留下持久入口。只删公钥是不够的,因为对方可能同时在别处留了其他后门,这也是最终要重装的原因之一。
第六步:查可疑文件
木马文件通常藏在对系统运行无影响、不容易被注意的目录:
# /tmp、/dev/shm 是重灾区,正常不应有可执行文件
sudo ls -la /tmp /dev/shm /var/tmp
# 最近 N 天内修改的文件(按实际情况调整)
sudo find / -xdev -mtime -3 -type f 2>/dev/null | grep -vE '^/(proc|sys|dev|run|var/log)' | head -50
# 隐藏文件(点开头)
sudo find / -xdev -name '.*' -type f 2>/dev/null | head -30
# 可执行且位于临时目录的文件
sudo find /tmp /dev/shm /var/tmp -type f -perm -u+x 2>/dev/null
# Web 目录下的异常脚本
sudo find /var/www -name '*.php' -mtime -7 2>/dev/null
Web 目录要单独查,因为 WebShell 是最常见的入口和驻留方式。检查重点是最近修改时间与上线时间不符的文件、文件名随机字符串、内容里出现 eval、base64_decode、system、assert 等函数调用的脚本。
如果有 AIDE 之类的完整性基线,现在是用它的时候:
sudo aide --check
没有基线的话,RHEL、Debian 系都提供了包校验能力,可以检查系统命令是否被替换:
# RHEL、Rocky、CentOS
sudo rpm -Va | grep -v '^.......' | head -30
# Debian、Ubuntu
sudo dpkg --verify | head -30
rpm -Va 会输出校验失败的文件,其中 5 开头表示 MD5 不符(文件被改),S 表示大小变了。如果发现 ps、top、netstat、ls 这些命令本身被替换,说明装了 rootkit 级别的东西,这种情况下系统已不可信,必须重装。
挖矿木马的典型特征
挖矿是目前最常见的植入类型,识别特征相对明显:
CPU 长期接近 100%,且进程名伪装。单核机器尤其明显,多核机器上可能表现为整体负载高但 top 里看不到明显大户(因为进程被隐藏)。
进程名伪装成系统进程,如 kworker/2:1、ksoftirqd、[systemd]、dbus-daemon、sshd 等。识别方法是看 /proc/PID/exe 的真实路径和启动参数。
连接矿池端口。矿池常用端口包括 3333、5555、7777、8008、8080、14444、45700 等,特征是与境外 IP 保持长连接且持续有流量。注意这些端口也是正常服务的常见端口,要结合进程一起判断。
存在 CPU 占用限制逻辑。很多挖矿木马会限制自己只占用部分 CPU(比如 60%-70%),避免触发告警,所以"CPU 没跑满"不等于没中招。
有守护进程和计划任务。杀掉主进程后几秒内被重新拉起,或者 crontab 里有定时下载执行的条目。
占用异常内存和带宽。部分木马会同时做端口扫描横向扩散,表现为本机对内网其他机器发起大量连接。
处置与恢复
按下面的顺序处置:
一,阻断外连。 在防火墙或安全组切断到矿池、控制端的连接,让木马失去作用,同时避免继续消耗资源。
二,清除持久化。 停用并删除恶意的 systemd 服务、timer、crontab 条目、rc.local 与 profile.d 脚本。先停用再删文件,顺序反了可能被重新拉起。
sudo systemctl stop 恶意服务 && sudo systemctl disable 恶意服务
sudo rm -f /etc/systemd/system/恶意服务.service && sudo systemctl daemon-reload
sudo crontab -r -u 被植入的用户 # 注意会删除该用户全部任务,先备份
风险提示:crontab -r 会删除该用户的全部计划任务,执行前先 crontab -l -u 用户 > backup.txt 备份,确认里面没有合法任务。
三,终止进程并删除文件。 先 kill -STOP 暂停观察,确认无影响后再 kill -9。删除文件前先复制一份留证。
四,清理后门。 删除未知公钥、锁定或删除可疑账号、撤销异常的 sudo 授权。
五,改密与轮换。 所有可能泄露的凭证都要换:系统口令、SSH 密钥、数据库口令、应用密钥、API Token、云账号 AccessKey。假设攻击者在机器上待过一段时间,这些都可能已泄露。
六,重装系统。 这一步不是可选项。原地清理无法保证彻底:你可能漏掉一个持久化点,系统命令可能已被替换,内核模块可能已被加载。可靠的做法是从镜像重装系统,只恢复经过检查的数据文件(配置文件和代码从版本库重新拉取,不要直接拷回来),然后重新做加固。
七,复盘与加固。 找出入侵途径(弱口令、暴露端口、未打补丁、WebShell),针对性修复,并把这次的检查项固化成例行巡检。
常见问题
杀掉进程后过一会儿又起来了,怎么办?
说明有守护进程或计划任务在拉起它。按本文第四步逐项查 systemd 服务、timer、crontab、rc.local、profile.d,找到拉起源并先停用,再杀进程。如果反复找不到拉起源,说明系统已被深度控制,直接重装。
木马文件删不掉,提示 Operation not permitted?
可能是文件被设置了不可修改属性。用 lsattr 文件名 查看,chattr -i 文件名 解除后再删。如果系统命令本身也被改过,那 lsattr 的输出也不可信,此时应直接进入重装流程。
只删掉 WebShell 就算恢复了吗?
不算。WebShell 是入口也是结果,攻击者可能已经在系统上做了提权、留了公钥、加了账号。只删文件不查账号、公钥、计划任务和进程,复发概率很高。
重装之后数据怎么恢复?
只恢复业务数据(数据库、上传的文件),并且恢复到重装后的干净系统上。配置文件和程序代码从版本控制系统重新拉取并做检查,不要从被入侵的机器上直接拷贝可执行文件和脚本。数据库恢复前建议先检查有没有被植入的存储过程或触发器。
需要保留现场给安全厂商分析吗?
如果涉及合规要求或需要追责,建议先做磁盘快照和内存转储再处置,并联系专业应急机构。内存转储和磁盘镜像是后续溯源的关键,一旦重装就无法挽回。如果业务优先,至少完成磁盘快照再做重装。
总结
- 发现异常先隔离和保护现场:做快照、备份关键日志、记录进程与网络快照,不急着杀进程、不急着关机,避免丢失证据。
- 查进程的关键是
ls -l /proc/PID/exe看真实可执行路径,留意(deleted)标记和伪装成kworker之类的进程名;ss -antp查异常外连是见效最快的手段。 - 持久化排查必须覆盖 systemd 服务、systemd timer、
/etc/cron*、/var/spool/cron、rc.local、/etc/profile.d/、.bashrc、账号、authorized_keys和 sudoers,漏掉任何一处都会复发。 - 挖矿木马的典型特征是 CPU 长期高占用、进程名伪装、连接矿池常见端口、有守护进程或计划任务拉起,并可能限制自身占用以规避告警。
- 处置完成后必须重装系统并从干净备份恢复数据,同时轮换全部凭证;原地清理只能止血,不能作为最终结论。
企业QQ咨询




