故障排查与清理笔记:Nezha Agent 供应链攻击与脱机数据救援
- Linux
- 4小时前
- 15热度
- 0评论
1. 故障背景与根因定位
多台公网节点及通过 Tailscale 组网的无公网 IP 节点(含 PVE 宿主机)发生规模化资源耗尽与强制关机现象。初期在进行 Minecraft 服务端(7.6GB)打包下载时触发频繁宕机,后经溯源,确认为 Nezha Agent 供应链投毒攻击。
入侵链路原理: > 攻击者利用漏洞攻陷了暴露在公网的哪吒监控中控端(Nezha Dashboard)。由于 Nezha Agent(探针)在各宿主机上以
root权限运行,且其网络机制为 Agent 主动向 Dashboard 发起 WebSocket 长连接(出站流量)。攻击者借此合法通道下发恶意负载,此机制无视本地防火墙入站规则及 NAT 隔离,导致包括纯内网节点在内的所有挂载探针的机器全数沦陷。
2. 阶段一:业务数据脱机抢救(防 OOM/IO 崩溃)
在尝试使用 tar 或 SFTP 提取游戏服务端时,服务器频繁发生 Kernel Panic(内核恐慌)与断电。
解释: 感染状态下,木马与杀毒软件(clamd)已榨干系统内存,大批量碎文件(如 .mca)读取产生密集磁盘 I/O,瞬间撑爆缓存(Page Cache)触发系统自我保护机制强制关机。
必须彻底避开已腐烂的操作系统环境,实施物理级脱机救援(Live CD 协议)。
解释: 操作系统如同房屋。当屋内布满陷阱(木马/死锁机制)时,我们不进屋,而是在院子里搭个临时帐篷(纯净 Live 镜像),直接从窗户把家具(数据)搬走。此时原系统的木马处于“休眠死肉”状态,绝对无法运行。
2.1 PVE 直通与光盘引导
- 将 64GB 物理 U 盘插入宿主机,在 PVE 硬件设置中执行 USB 直通:

- 挂载纯净 Ubuntu Server ISO 镜像,调整引导顺序为光驱优先。

- 启动虚拟机,选择
Try or Install Ubuntu Server,通过Help -> Enter Shell进入纯净命令行。
2.2 挂载与物理拷贝
识别逻辑卷与 U 盘挂载点(根据图示确认为 ubuntu--vg-ubuntu--lv 与 sdb1):

执行挂载与数据抢救:
mkdir -p /mnt/oldsys
mkdir -p /mnt/usb
mount /dev/mapper/ubuntu--vg-ubuntu--lv /mnt/oldsys
mount /dev/sdb1 /mnt/usb
# cp (复制命令) -a (归档模式: 保留文件原权限) -r (递归: 拷贝所有层级) -v (详细模式: 输出过程)
cp -arv /mnt/oldsys/root/mc/* /mnt/usb/mc_backup/
2.3 乱码排错与安全卸载
拷贝过程中出现如 350212231 等八进制转义乱码。

解释: 并非文件损坏或感染,纯粹因 Live 临时系统缺乏中文字库,系统将其转换为 UTF-8 底层字节码展示。
拷贝完成后必须执行强制刷写与安全卸载:
# sync (同步: 强制将内存中未写完的缓存数据写入物理 U 盘,防止拔盘损坏)
sync
# umount (卸载: 安全断开挂载点)
umount /mnt/usb
3. 阶段二:感染特征与持久化机制分析
业务安全转移后,进入旧系统排查木马特征。
3.1 异常驻留进程
root 1802545 0.4 0.1 1230740 7744 ? Ssl 19:44 0:00 /dev/shm/.kworker_u8
剖析:
- 路径伪装: 位于
/dev/shm/(共享内存挂载点),运行在物理 RAM 中,躲避常规磁盘扫描且重启即焚。 - 命名混淆: 进程名伪造为内核线程,并注入了零宽不可见字符(Zero-width characters)。这使得肉眼看着是常规字母,但直接手动输入进程名执行查杀会因字符不匹配而失效报错(
No such file or directory)。
3.2 守护与自动复活闭环
利用 crontab -l 发现恶意定时任务:
*/30 * * * * /usr/freemem.sh >> /tmp/tmp.txt
* * * * * pgrep -x .kworker_u8 > /dev/null || /dev/shm/.kworker_u8 > /dev/null 2>&1 &
剖析: ` (每分钟执行一次),使用pgrep -x (精确匹配: 仅匹配进程名完全一致的目标)` 检查木马存活。
|| (逻辑或: 若前置命令执行失败/找不到进程,则立即执行后置命令)确保木马一旦被杀,1 分钟内必然从内存重新拉起分配新 PID。
4. 核心清理步骤(防复活查杀)
操作原则: 必须严格遵循“阻断守护 -> 击杀进程 -> 清理实体 -> 剥离通道”的逆向拆解顺序。
步骤 1:阻断 Crontab 守护(安全过滤法)
解释: 恶意任务含零宽字符,手动 crontab -e 极易误删或残留。严禁使用 echo 全盘覆盖法则,避免误删生产环境中未知的合法业务计划任务。使用管道过滤法进行精准剔除。
# grep (文本搜索) -v (反向匹配: 剔除包含目标字符串的行)
crontab -l | grep -v "/dev/shm" | grep -v "worker" | crontab -
执行后 crontab -l 确认脏代码已消失。
步骤 2:强制截断进程
无视零宽字符,通过片段模糊正则匹配进行击杀:
# pkill (通过名称终止进程) -f (完整命令行匹配: 忽略零宽字符干扰,强制终止包含片段的所有进程)
pkill -f "worker"
pkill -f "kwo"
步骤 3:铲除物理文件与残留脚本
清除内存挂载点实体及配套辅助脚本:
# rm (删除) -r (递归) -f (强制: 忽略不存在的文件,不提示确认)
rm -rf /dev/shm/.kw*
rm -f /usr/freemem.sh
步骤 4:剥离感染源 (Nezha Agent)
切断被攻击者用来下发指令的 WebSSH/探针通道:
# stop (停止运行); disable (禁用自启: 移除 systemd 软链接)
systemctl stop nezha-agent
systemctl disable nezha-agent
rm -f /etc/systemd/system/nezha-agent.service
# daemon-reload (重载守护进程: 让系统抹除对该服务的认知缓存)
systemctl daemon-reload
rm -rf /opt/nezha
5. 鉴权阻断与验证加固
5.1 清理后门密钥与重置凭据
攻击者获取 root 后必定写入免密公钥。执行硬阻断:
# > (重定向覆写: 物理清空文件内容至 0 字节,粉碎预留的免密隧道)
> ~/.ssh/authorized_keys
passwd root
5.2 验证
reboot
解释: 重启可强制卸载可能被木马挂载 (Hook) 的系统级内核模块,释放隐蔽子线程。重启后再次查验 ps aux 与 crontab -l,若无异常则节点止血成功。建议后续引入含独立 x86 网关和 DPI 深度包检测的三层网络架构隔离内网环境。
5.3 净室重建规范 (Clean Room Protocol)
解释: 鉴于
root权限已失陷,系统内核及环境变量可能已被篡改。查杀木马仅为争取数据迁移时间的“止血”操作,必须执行零信任的物理级重装,彻底切断交叉感染链。
- 数据提纯提取: 严禁整体打包
/var/www或/opt目录。仅提取纯净业务数据(如通过mysqldump导出的.sql文件、.mca存档)。坚决遗弃旧系统的任何第三方脚本或可执行文件(.sh、.bin),业务代码必须自官方或干净的 Git 库重拉。 - 底层环境销毁: 依托 PVE 虚拟化隔离优势,直接从物理机控制台
Remove销毁失陷虚拟机,物理抹除受污染的逻辑卷(LV)。随后挂载官方纯净镜像部署独立新实例。 - 全链路凭据轮换: 弃用旧系统全部凭据。重新生成高强度密钥,重置所有数据库、Redis 及 API 的鉴权 Token。
- 管控面板隐身: 针对高危 Web 控制台,严禁监听
0.0.0.0暴露于公网。强制绑死127.0.0.1配合 Tailscale 内网穿透访问,实现公网维度物理隐身。
新系统挂载公网前,必须通过 sshd_config 锁死入口防线:
nano /etc/ssh/sshd_config
# Port (修改监听端口: 规避 22 端口的全网自动化盲扫,建议设为 10000 以上)
Port 38291
# PasswordAuthentication (禁用密码认证: 彻底阻断字典爆破,强制依赖非对称密钥鉴权)
PasswordAuthentication no
# PermitRootLogin (限制 Root 登录: 禁止密码直连 Root,切断最易被利用的提权路径)
PermitRootLogin prohibit-password
# 重载配置使规则生效
systemctl restart sshd


