ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Linux挖矿病毒kdevtmpfsi应急响应与清除加固实战

Linux挖矿病毒kdevtmpfsi应急响应与清除加固实战

凌晨一点被监控短信叫醒,某台内部Linux服务器的CPU跑满,ssh上去看到top里躺着一个叫kdevtmpfsi的陌生进程,负载飙到八九百。那是我第一次在真实生产环境里完整处置这个家族化挖矿样本,也是后来我遇到次数最多、变种最杂的Linux挖矿病毒之一。

凭名字判断它跟内核驱动没啥关系,纯粹是用了类似内核设备文件的小写串做伪装,实际就是挖矿木马释放的二进制。这类病毒常见入口是Redis未授权访问、Docker API裸奔、Web中间件RCE或者是SSH弱口令,只要一个口子没堵上,crontab里就会多一行定时任务,每几分钟把它重新拉起来。

如果你也遇到CPU突然飙高、进程名奇怪、或者排查时发现/tmp目录出现了删不掉的陌生文件,这篇文章可以直接当作处置手册用。从进程定位、文件清理、计划任务排查,到入口封堵和加固,每一步我都会讲清楚为什么要这么做,以及踩过的坑在哪里。

1. 先认清对手:kdevtmpfsi到底是怎样工作的

1.1 病毒进程和文件画像

kdevtmpfsi这个名字是混淆用的,让人误以为是跟kernel设备临时文件系统相关的正常内核线程。但真实行为完全不是这样:它运行时会拉高CPU使用率到接近100%,持续进行equihash算法计算,本质上是在为矿池打工。

常见落盘位置和文件特征有两类,一套是主程序,一套是辅助组件:

  • /tmp/kdevtmpfsi:主挖矿程序,随机小写字母命名
  • /tmp/kinsing:同家族植入程序,负责下载、持久化、清理竞争挖矿程序
  • /usr/bin/kdevtmpfsi:部分变种会额外写入系统目录增强存活能力
  • /tmp/php-cgi、/tmp/lsock、/tmp/networkservice:后续出现的辅助文件,通常用于移除其他矿工、内网横向感染

如果你看到这些文件,不要犹豫,它们都不属于正常业务。它们的共同特征是:文件目录权限一般是/tmp、没有经过标准软件包管理器安装、修改时间与系统上线时间严重不符。

恶意程序命名方式也在不断变化,有的变种会使用kdevtmpfsi、kinsing,后来的版本可能叫xr、kdevtmpfsi的MD5短哈希、或者其他随机字符串。识别重点是看进程的行为,而不是死记文件名。

注意:很多运维同学习惯用文件名判断病毒,一旦碰到变种改名就会误判。判断一个进程是否可疑,最直接的手段是看它从哪里启动、CPU占用如何、网络连到哪去。这三项对上了,基本可以定性。

1.2 典型的感染链路与传播机制

这类病毒传播路径高度固定,我统计过的案例里,90%以上是这么进来的:

  • Redis未授权访问:服务器上的Redis监听在0.0.0.0:6379,没有密码或者只有弱密码。攻击者用Redis写文件功能向/var/spool/cron/目录写入root计划任务,crontab每分钟执行一次下载命令,把恶意程序拉到本地再运行。
  • Docker API未授权:Docker daemon的2375端口对外暴露,没有TLS认证。攻击者直接调用Docker API创建容器,把宿主机根目录挂载进容器后写入crontab或ssh公钥。
  • Web中间件远程代码执行:常见的框架漏洞如果没打补丁,攻击者可以执行任意命令,再通过命令回调下载并执行挖矿程序。
  • SSH弱口令暴力破解:简单密码被爆破后登录,直接写入计划任务和公钥后门。

病毒进入后还有一套自清理逻辑,发现系统里其他挖矿程序会主动杀掉并删除对方文件,这大概是矿工之间的"内卷"。

搞清楚入口链路比清病毒本身更重要。我处理过很多反复感染的案例,进程杀一次、文件删一次,过半小时又回来了,原因就是入口还开着,攻击者可以随时重新种下去。所以在清除之前,先记录所有可能的入口,后面单独花力气封堵。

2. 应急响应第一步:快速定位与确认告警

2.1 登录前先评估影响面

接到CPU告警不要急着扑进服务器操作,先问自己几个问题:这台机器是物理机还是云主机?有没有外网IP?业务上能否直接停掉?连不上服务器时靠什么手段处置?

这一步看起来很浪费时间,但恰恰决定了后续操作能不能顺利执行。比如一台有外网的云主机,挖矿程序正在和内网其他机器通信,你贸然把进程杀了,矿池地址可能已经写进文件,重启后又拉起来。又比如服务器已经ssh不稳,可能并发的大流量连接导致无法登录,需要提前准备带外管理通道。

建议先做这几件事:

  • 使用带外管理平台或KVM查看服务器是否还能登录
  • 备份当前进程快照和网络连接快照,后续要用来溯源
  • 确认服务器是否属于核心业务节点,评估能否直接隔离网络

2.2 用top和ps快速锁定嫌疑进程

登录后第一件事,不要直接执行修复,先取证。我会把ps aux、top -bn1、ss -antp三个命令的输出保存到本地文件,后面分析用。

# 采集当前所有进程,按CPU使用率排序 ps aux --sort=-%cpu | head -30 # 采集动态进程状态 top -bn1 | head -40 # 采集网络连接情况 ss -antp | sort -k1,1

根据进程名的CPU占用能大概看出问题。正常业务进程即使高负载,名称和路径也是可识别的。看到奇怪的/tmp下进程、或者用户名异常的进程,记下PID,然后配合查看进程详情。

# 查看PID的启动命令 cat /proc/PID/cmdline # 查看进程可执行文件的真实路径 ls -l /proc/PID/exe # 查看进程的环境变量,有些恶意程序会存放下载地址 cat /proc/PID/environ

其中/proc/PID/exe是最关键的,很多木马会在执行后删除源文件,但/proc下软链还会保留路径,也能看到文件是否已被删除。通过ls -l里的(deleted)标记能判断程序当前还在运行但磁盘文件已被清掉。

2.3 顺藤摸瓜查网络连接

在抓取完进程信息后,立即查看网络连接,通常能发现挖矿程序正在与矿池地址通信。

# 查看所有监听和外部连接 ss -antp | grep PID # 或使用netstat查看 netstat -antlp | grep PID

矿池通信的典型端口是4444、3333、5555、9000,但并不是固定限制。有些矿工已经使用常规的8080、443、80端口做隧道,所以不能只看端口,更多要看外部IP是否有名有姓。矿池地址通常解析到海外机房,比如荷兰、俄罗斯、美国的一些IP段,这些IP在正常业务里几乎不会出现。

这里有个细节:如果发现外联地址很可疑,可以对这个IP做whois查询,看看是不是矿池服务器。不要直接在服务器上反向连接该地址做探测,避免引起攻击方注意或扩大感染面。

2.4 排查计划任务和后门

kdevtmpfsi系列的持久化手段基本绕不开crontab。检查这个方向时,要覆盖root用户、系统级计划任务、还有一些常见的隐藏位置。

# 列出root用户计划任务 crontab -u root -l # 查看系统级计划任务文件 cat /etc/crontab ls -la /etc/cron.d/ ls -la /var/spool/cron/ ls -la /var/spool/cron/crontabs/

恶意计划任务一般长这样:

* * * * * /tmp/kdevtmpfsi >/dev/null 2>&1 */3 * * * * /tmp/kinsing

它们会每隔几分钟甚至每分钟执行一次,确保受害者手工清理后能快速复活。除了crontab,还要检查/etc/rc.local、/etc/init.d/、systemd服务文件中是否有陌生启动项。有些变种会写入/etc/ld.so.preload实现更隐蔽的加载,但kdevtmpfsi本身较少使用这一招,家族内的植入脚本倒是有时会用。

3. 完整清除演练:手动清理kdevtmpfsi

3.1 网络隔离:切断挖矿程序的远程控制链路

清理前先做网络隔离,最直接的方式是添加防火墙规则,禁止服务器向矿池方向通信。

# 封禁已知矿池IP(额外会使用官方安全情报库再次确认) iptables -A OUTPUT -d 目标矿池IP -j DROP

如果无法快速判断矿池IP,可以直接关闭服务器外网出口,或者用云控制台的安全组配置出方向全拒。这个方法最简单有效,因为矿工在断网状态下无法和矿池通信,效率也会下降,但注意它不能清除已存在的计划任务,还需要继续处理。

小心一点:有些加固方案会建议直接拔网线或关机,这在测试环境可以。生产环境如果这台机器承担了对外服务,就要权衡业务影响。稳妥做法是先用iptables只封矿池地址,保留正常业务流量。

3.2 终止挖矿进程和相关子进程

确认进程PID后,先看看进程间父子关系,再动手。

# 查看所有相关进程 ps -ef | grep -E 'kdevtmpfsi|kinsing' # 逐个终止 kill -9 PID1 PID2

或者用pkill匹配进程名:

pkill -9 -f kdevtmpfsi pkill -9 -f kinsing

注意一个关键问题:不要只杀主进程,kdevtmpfsi启动后可能拉起多个worker子进程,如果只杀父进程,子进程会变成孤儿继续挖矿。每次杀完都要重新用ps aux确认所有相关进程都不在了。

这里还有一个实操细节,先保留一份PID和进程命令行的记录,之后写溯源报告要用。直接杀掉虽然干净,但少了证据链。我通常会先把/proc/PID/environ和/proc/PID/cmdline存下来,再执行kill。

3.3 删除落盘文件与恶意计划任务

进程清掉后,开始清理文件。先把可疑文件备份一份,再删除。

# 备份样本用于分析 tar czf /tmp/malware_sample.tar.gz /tmp/kdevtmpfsi /tmp/kinsing 2>/dev/null # 删除恶意文件 rm -f /tmp/kdevtmpfsi rm -f /tmp/kinsing rm -f /usr/bin/kdevtmpfsi

同时清理计划任务:

# 清空当前用户计划任务 crontab -r

如果是root的计划任务,直接编辑文件删除恶意行:

sed -i '/kdevtmpfsi/d' /var/spool/cron/root sed -i '/kinsing/d' /var/spool/cron/root

再检查/etc/cron.d/里面有没有对应的定时任务文件,有的话一并删除或者注释掉。

不建议只靠crontab -e手工删,因为有些恶意行写在多个用户或系统级任务里,漏一处就前功尽弃。我一般会用grep -r 'kdevtmpfsi' /etc/cron* /var/spool/cron /tmp全局搜索,确认没有遗漏再往下走。

3.4 排查SSH后门与其他隐藏项

随时检查SSH目录,因为攻击者在拿到权限后,极有可能写入自己的公钥。

# 检查root用户和其他用户的authorized_keys cat /root/.ssh/authorized_keys find /home -name authorized_keys -exec cat {} \;

如果发现不认识的公钥,删除即可。注意公钥是连续字符串,复制不全会导致删错,我习惯先备份文件再手工删除。

其次是账户后门:

# 检查是否存在新增用户 awk -F: '$3==0 {print $1}' /etc/passwd # 检查具备登录权限的账户 cat /etc/passwd | grep '/bin/bash'

再次是sshd配置检查:

cat /etc/ssh/sshd_config | grep -vE '^#|^$'

重点确认PermitRootLogin no、PasswordAuthentication no是否生效。如果配置不理想,修复后在重启sshd前用另一个会话验证配置没有错误,避免把自己锁在门外。

4. 堵住入口:清除后必须做的加固项目

4.1 加固Redis服务:封堵最常见入口

kdevtmpfsi家族高频利用的入口就是Redis未授权访问。修复方案很明确:

# 修改redis配置 bind 127.0.0.1 protected-mode yes requirepass 这里填一个足够复杂的密码

改动后重启服务并验证本机可以连接,远程无法连接。很多生产环境确实需要Redis对特定网段开放访问,这种情况下不要只靠密码,在iptables或云安全组层面限制源IP比密码更可靠。

注意排查Redis日志,看看攻击者是否已经获取了redis权限。通过日志可以发现大量异常命令或者大文件写入的痕迹。如果有,确认损坏范围后建议更换redis密码并考虑让攻击者删除的公钥、计划任务全部恢复。

4.2 封堵Docker API暴露

另一个常见入口是Docker的2375端口相声裸奔。管理员为了远程管理把daemon暴露在公网上,又没加TLS,攻击者用一行代码就能拿到宿主机root权限。

修复要点:

# 修改 /etc/docker/daemon.json,不再使用裸tcp { "hosts": ["unix:///var/run/docker.sock"] }

如果非要远程管理Docker,官方的TLS方案是唯一推荐做法,不要寄希望于裸TCP加防火墙。同时在云安全组里把2375端口彻底关闭。

4.3 SSH登录加固

SSH弱密码爆破是另一大入口。实战中百分之几十的挖矿感染都来自弱口令爆破后留下的壳。建议打开或者确认以下内容:

  • 禁止root直接登录:PermitRootLogin prohibit-password或者no
  • 启用密钥登录,关闭密码登录:PasswordAuthentication no
  • 配置登录失败限速:合理使用fail2ban或等价方案
  • 定期审计公钥,发现不认识的key立刻移除

改配置之前先做一步,确认自己手里有可用的密钥,否则一旦重启sshd就可能在门外下不来。我在调试SSH配置时一定保持两个会话:一个会话改配置文件并测试,一个会话保留连接。

4.4 系统账号与权限全面审查

不管入口是哪个,最终攻击者都想拿到高权限账号。检查范围包括:

  • /etc/passwd里是否有UID=0的隐藏账号
  • /etc/shadow中是否有空密码账号
  • /home目录中是否有最近新建的不认识用户
  • /etc/sudoers中是否有异常向

顺手检查文件时间点,找出与感染时间基本重合、但权限不正常的可执行文件。这些系统层面会剧烈拖慢处置速度,但非常值得做。

另外把SSH命令历史和shell历史捞出来看一遍,攻击者执行的命令往往能准确告诉你们从哪里进来、做了什么:

cat /root/.bash_history cat /var/log/auth.log | grep -i accepted | awk '{print $9}' | sort | uniq -c

5. 常见问题与处置实录

5.1 问题速查表

现象可能原因处置方案
进程刚杀掉又出现crontab存在残留任务全局检索计划的恶意行,删除后确认入口已封
crontab被反复改写Redis未授权或Docker API裸露先封堵入口,再清理任务,否则白干
/tmp下文件删除后自动重建有守护进程在定期下载检查/tmp目录可写权限,找所有下载脚本
kill后进程名变化木马有多态改名机制分析进程历史,用文件hash做全盘扫描
清理后CPU依然很高可能有其他家族挖矿程序并存重新按CPU排序,展开完整进程排查
找不到具体入口漏洞类型复杂拉取所有登录日志,复查弱口令和未授权服务

5.2 一次典型复发的处置实录

有一年处理一台云主机,CPU飙到400%以上,找到的进程就是kdevtmpfsi。按老流程清了一遍,杀进程、删文件、清crontab,结果第二天早上收到同样的告警。

回来复查,发现了两个问题:第一,Redis端口在线且未授权,攻击者随时能再往crontab写任务;第二,之前我只是删掉了root用户crontab里的恶意行,但/etc/cron.d/里有一个压根看不出来异常命名的文件,里面藏着挖矿下载脚本。

这次的处置步骤变成了:关闭Redis外网监听、加密码认证,删除/etc/cron.d/里的异常文件,把/root/.ssh/authorized_keys里不认识的两行公钥全部移除,然后才重新杀进程删文件。之后连续观察三天,CPU一直稳定,问题才算真正结束。

这让我后来养成一个习惯:不管首次清得多么干净,修复后都要隔一段时间复查,尤其在入口没有完全确认封闭的情况下,几小时后回来看一眼crontab和/tmp目录,是否又出现新文件。挖矿类问题的核心往往不是木马本身能多隐蔽,而是攻击者留下的入口能不能反复进入。

5.3 从应急到复盘:一次完整处置记录模板

处置过程中顺手把时间线记录下来,后面复盘开头会很好用:

  • 发现时间、告警来源、最初症状
  • 登录时间、当前在线用户、可疑连接IP
  • 确认的进程名、文件路径、外连地址
  • 执行过的清理动作、验证结果
  • 确认的漏洞入口、加固措施
  • 观察期结束后的复查结论

不用写太华丽的报告,自己看得清、其他同事接手能看懂就够了。我见过很多处置现场一团乱麻,结果环节没人能说清楚当时处理了哪些地方,最后只能选择重装系统。记录是应急处置里被低估但高价值的组成部分。

6. 事后复盘与小技巧

这里分享一点个人经验:每次处置完挖矿病毒,我都要保留样本文件,放一份到隔离的取证机上。很多时候第一轮清理草草了事,第二次发生一模一样的感染,能有样本在最开始就配置好静态检测,节省大量时间。

kdevtmpfsi这类挖矿病毒虽然看起来来势汹汹,清除手段其实很成熟,关键是步骤别乱。最忌讳一开始就重装系统或者盲目跑加固工具,先把该记录的记录清楚,再把入口封好,然后按顺序清理进程、文件、计划任务、后门账号,最后做长期观察。

如果业务上允许,遇到顽固反复的感染,最稳妥的方案确实是把受害机器当作失陷主机彻底重装,并在重装前保留端口和流量日志用于后续分析。但很多时候业务不允许马上停机,这时候手动作业的质量就非常关键。宁可慢一点把每个入口查全,也不要为了赶时间只清理表面症状。

序列里还有一个容易被忽略的细节,/tmp目录权限。很多业务脚本依赖/tmp做临时存储,但该目录对所有人可写,本身就是恶意程序的温床。如果有条件给/tmp挂一个独立的tmpfs且限制执行权限,会大大降低这类文件的落地成功率。

处理这类问题多了,你会发现安全加固其实不是装多少安全产品,而是把最常规的几件事做扎实:高危端口不裸奔、管理服务不弱口令、系统补丁及时打、日志留得住。做到了这几点,挖矿病毒找上门的机会都会小很多。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进