服务器信息: Netcup VPS 1000 G12 iv Pro NUE ADV25 / Debian 13 / 4 核 CPU
事件时间: 2026 年 5 月 12 日
关键词: 门罗币挖矿、qBittorrent 漏洞利用、nginx 反代认证绕过、自动化攻击
前言
5 月 12 日凌晨,我发现自己的 Netcup VPS 异常卡顿。SSH 进去一看,CPU 占用率直接打满 400%,load average 高达 4.5(4 核机器)。本以为是某个服务出了问题,结果一路排查下来,发现这是一起完整的自动化挖矿木马入侵事件。从发现异常到完成溯源,整个过程留下了非常清晰的攻击链条,记录下来供大家参考。
第一阶段:发现异常
通过 ps aux --sort=-%cpu 查看进程,立刻发现了罪魁祸首:
几个关键特征一目了然:
- 进程名
vid,伪装成视频相关程序,藏在/var/tmp/目录下 - 连接矿池
gulf.moneroocean.stream:12048,这是知名的门罗币(Monero)矿池 - CPU 占用 385%,
--cpu-max-threads-hint 100表示设置为占满所有 CPU 核心 - PPid 为 1,说明由守护进程或系统级调用拉起,具备持久化机制
同时发现了大量可疑的 sh 和 sleep 进程,它们与挖矿进程共享相同的文件描述符(fd),这是典型的挖矿木马守护脚本。
第二阶段:应急处置
杀进程、删文件
第一时间杀掉挖矿进程,删除恶意二进制文件:
清除守护脚本
进一步检查发现,多个 sh 进程在循环下载并执行恶意脚本:
共有 5 组这样的守护进程(PID 759794-768932),全部杀掉:
阻断恶意域名
在 /etc/hosts 中屏蔽恶意域名,防止再次连接:
清理残留文件
/tmp 目录下有上千个 4c-7-r-*.log 文件(4c-7-r 是挖矿的 Worker 前缀),/var/tmp 下有 gopids、other_project、springboot 等可疑目录,全部清除。
第三阶段:持久化检查
逐一排查常见的持久化手段:
| 检查项 | 结果 |
|---|---|
| crontab | 干净(仅宝塔面板定时任务) |
| /etc/crontab | 干净 |
| systemd 服务 | 未发现可疑服务 |
| ~/.bashrc / /etc/profile | 未被注入 |
| authorized_keys | 仅本人公钥 |
持久化的主要方式是那些反复下载 run.sh 的 sh 守护进程,杀掉后不再复活。
第四阶段:溯源分析
入侵入口定位
通过排查各项服务和日志,逐步缩小范围:
- SSH:无暴力破解记录,未被入侵
- 宝塔面板:日志正常,未被入侵
- qBittorrent:发现重大线索
qBittorrent 的 systemd 日志中出现了俄语的挖矿启动信息:
这说明 qBittorrent 进程本身在执行挖矿命令,攻击者通过 qBittorrent 的功能投递了恶意载荷。
攻击者操作记录
进一步分析 nginx 访问日志,找到了攻击者的完整操作记录。5 月 3 日,一个使用 python-requests/2.33.1 的自动化脚本对 qBittorrent WebUI 发起了攻击:
同一天内重复了 7 次相同的操作模式,每次都是:
GET /— 访问首页(直接返回 200 主界面,而非登录页)POST /api/v2/app/setPreferences— 修改配置(设置"下载完成后执行脚本")POST /api/v2/torrents/add— 添加恶意种子触发下载
关键发现:攻击者全程没有登录操作。 5 月 3 日的日志中没有任何 /api/v2/auth/login 请求,所有 API 调用都直接返回 200 成功。
根因确认:nginx 反代导致认证被绕过
我明明修改过 qBittorrent 的密码,为什么攻击者不需要登录就能操作?
答案在 nginx 反代配置中:
proxy_set_header Host localhost 这行配置,将所有请求的 Host 头设置为 localhost。由于 nginx 和 qBittorrent 运行在同一台机器上,请求通过 127.0.0.1 转发,qBittorrent 的 AuthSubnetWhitelistEnabled(本地子网免认证,v5.x 默认开启)认为这是来自本地的可信请求,直接跳过了认证。
也就是说,所有经过 nginx 反代的请求都被 qBittorrent 当作本地请求处理,密码形同虚设。
完整攻击链
攻击者信息汇总
| 项目 | 详情 |
|---|---|
| 攻击方式 | python-requests/2.33.1 自动化脚本批量扫描 |
| 首次攻击时间 | 2026-05-03 09:55:25 |
| 恶意脚本来源 | files.norwater.no → IP: 83.242.8.97(挪威) |
| 矿池地址 | gulf.moneroocean.stream → IP: 45.155.102.89 |
| 门罗币钱包 | 47pEbRZN8Hg1HEm8wniGhVYSyyYPFLc6ccRMejZZSaGYQbJXAfUjbGTDHrWiQRb5bi8s4hmHNaeZUSac7w4H8JntGQ1vJWS |
| Worker 标识 | 4c-7-r- 前缀 |
| 攻击工具特征 | 俄语日志输出、python 自动化脚本 |
第五阶段:安全加固
1. SSH 安全
关闭密码登录,仅保留密钥认证:
2. 修复 nginx 反代配置
修改 Host 头,不再让后端认为是本地请求:
3. 添加 nginx Basic Auth
在 nginx 层增加一层认证,即使后端认证被绕过也有保护:
4. 关闭 qBittorrent 本地子网免认证
在 qBittorrent 配置文件中明确禁用:
5. 关闭不必要的端口
经验教训
1. nginx 反代内网服务时务必注意认证问题
这是这次事件最核心的教训。当 nginx 和后端服务在同一台机器上时,proxy_set_header Host localhost 配合 proxy_pass http://localhost:port 会让后端认为所有请求都来自本地。如果后端有"本地请求免认证"的逻辑(qBittorrent、很多管理面板都有),反代等于把认证彻底架空。
正确做法: 永远使用 proxy_set_header Host $host,并在后端关闭本地免认证,或在 nginx 层加额外的认证。
2. 不要依赖单一认证
即使后端服务设置了强密码,也应该在反代层增加额外的认证(如 Basic Auth、IP 白名单)。多层防护确保单点失效不会导致被入侵。
3. 及时关注默认配置的安全隐患
qBittorrent v5.x 默认开启 AuthSubnetWhitelistEnabled,信任来自 127.0.0.0/8 的请求。这种默认配置在直接暴露的场景下没问题,但通过反代访问时就变成了严重漏洞。部署服务前务必检查默认配置的安全影响。
4. 自动化攻击无处不在
这次入侵不是针对性攻击,而是僵尸网络的批量扫描。攻击者使用 python 脚本自动化扫描公网上的 qBittorrent 实例,一旦发现可免认证访问的目标就自动投毒。从 5 月 3 日被攻击到 5 月 12 日发现,中间已经挖了 9 天的矿。
时间线总结
| 时间 | 事件 |
|---|---|
| 2026-04-06 14:03 | 部署 qBittorrent,配置 nginx 反代 |
| 2026-05-03 09:55 | 攻击者首次通过自动化脚本入侵,设置恶意执行脚本 |
| 2026-05-03 09:55 - 19:10 | 攻击者反复投放恶意种子(共 7 次) |
| 2026-05-06 前后 | 恶意脚本开始持续执行,产生大量挖矿日志 |
| 2026-05-12 03:17 | 守护脚本启动新一轮挖矿进程 |
| 2026-05-12 03:50 | 挖矿程序 vid 启动,CPU 打满 400% |
| 2026-05-12 04:00 | 发现异常,开始排查 |
| 2026-05-12 04:06 | 杀掉挖矿进程和守护脚本 |
| 2026-05-12 04:10 | 完成全面清理和安全加固 |
| 2026-05-12 05:00 | 完成溯源分析,确认攻击链条 |
最终安全状态确认
希望这篇文章能帮助遇到类似情况的朋友快速定位和解决问题。服务器安全无小事,尤其是在配置反向代理时,一定要充分理解每一行配置的安全含义。