服务器被植入流量劫持后门(跳转世界杯赌球网站)的排查与解决方案

服务器被植入流量劫持后门(跳转世界杯赌球网站)的排查与解决方案

RONGYAN
2026-06-13 / 1 评论 / 8 阅读 / 耗时: 21 ms /

前言

  今天早上遇到一个非常头疼的问题:我的一台云服务器上部署的网站,访问时会有很大概率跳转到赌球网站(刚好世界杯期间,什么牛鬼蛇神都出来了)。更诡异的是,哪怕我放一个纯空白 HTML 页面上去,依然会被劫持。折腾了半天,最终定位到是一套精心伪装的博彩木马。本文记录完整的排查、分析和清理过程。

一、症状描述

先说环境:

  • 三台云服务器,同一家服务商
  • 出问题的这台:Ubuntu 系统
  • 另外两台正常的:CentOS 系统
  • 所有网站运行在 Nginx 上,通过 宝塔面板 管理

症状:

  1. 访问网站(无论哪个域名),浏览器有很高概率跳转到 https://dd0a000h4orvt.cloudfxxxt.net/?cid=8214805 (域名已做了无害处理)这个赌球网站

世界杯赌球网站

  1. 即使是刚上传的空白 test.html(内容就一句 hello),依然会跳转;
  2. 开启 Cloudflare 小黄云(代理模式)无效,关闭小黄云(DNS only)也无效;
  3. 从服务器上 curl 访问页面,返回正常,没有任何跳转;
  4. 另外两台 CentOS 服务器完全正常

跳转链(之前没有捕捉到前面那个xyz跳转链接所以走了一些弯路):
世界杯赌球网站跳转链接

先是跳转faradfdsa.anfxxc.xyz,接着很快跳转至dd0a000h4orvt.cloudfxxxt.net/?cid=8214805

二、初步分析

2.1 排除 ISP/DNS 层面

因为只有这一台服务器有问题,而三台机器用的是同一家云服务商,所以排除了"运营商线路劫持"的可能。如果是 ISP 层面的劫持,三台服务器应该都会中招。

2.2 为什么 Cloudflare 无效

Cloudflare 的代理模式会将用户流量先经过 Cloudflare 节点再转发到源服务器。如果劫持发生在源服务器发出响应之后(比如浏览器执行时),那么 Cloudflare 也救不了。

2.3 核心疑点:curl 正常但浏览器跳转

这说明劫持不是发生在 Nginx 配置层面(因为 curl 返回的是原始响应),而是在更上层——要么是浏览器端被注入 JavaScript,要么是网络传输层被篡改。

三、第一轮排查:发现 defunct / iptable6 rootkit

3.1 先看 Nginx 配置

nginx -T 2>/dev/null | grep -i "redirect\|rewrite\|return 302\|sub_filter"

输出中除了正常的 rewrite 规则外,没有发现明显的恶意配置。

3.2 检查进程——发现重大线索

lsof -i :443

输出赫然出现了三个可疑进程:

defunct     812 root    3u   TCP spk.laws.ms:33018->ec2.us-east-2.amazonaws.com:https (ESTABLISHED)
iptable6    817 root    4u   TCP spk.laws.ms:54498->ec2-13-57-38-185.us-west-1.compute.amazonaws.com:https (ESTABLISHED)
iptable6  28789 root    4u   TCP spk.laws.ms:54498->ec2-13-57-38-185.us-west-1.compute.amazonaws.com:https (ESTABLISHED)
  • defunct——这个名字看起来像是进程状态(<defunct> 表示僵尸进程),实则是恶意程序
  • iptable6——伪装成系统工具(正确名称是 ip6tables),拼写故意只差一点点

这两个进程都在向外部的 AWS EC2 服务器建立 HTTPS 连接。

3.3 定位二进制文件

file /usr/bin/defunct /usr/bin/iptable6
ls -la /usr/bin/defunct /usr/bin/iptable6
/usr/bin/defunct: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), static-pie linked, stripped
/usr/bin/iptable6: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, no section header

两个文件都是静态链接strip 去符号,显然是恶意软件标准做法。defunct 的文件日期被伪造为 2003-09-08,而 iptable6 的日期是 2026-04-28,说明是近期才植入的。

lsof -i -P -n | grep -E "defunct|iptable6"
defunct  812  root  TCP 127.0.0.1:33018->212.132.98.170:443 (ESTABLISHED)
iptable6 817  root  TCP 127.0.0.1:54498->13.57.38.185:443 (ESTABLISHED)

两个二进制分别连接不同的 C2 服务器,形成两条指挥通道。

3.4 找到自启动持久化机制

grep -r "iptable6\|defunct" /etc/init.d/ /lib/systemd/ 2>/dev/null

结果令人震惊——几乎每个 /etc/init.d/ 下的脚本都被注入了 /bin/iptable6

/etc/init.d/keyboard-setup.sh:/bin/iptable6
/etc/init.d/apparmor:/bin/iptable6
/etc/init.d/docker:/bin/iptable6
/etc/init.d/open-vm-tools:/bin/iptable6
/etc/init.d/postfix:/bin/iptable6
...(共 20+ 个文件)

更隐蔽的是 systemd 层面:

/lib/systemd/system/defunct.service:
ExecStart=/bin/bash -c "GS_ARGS='-k /lib/systemd/system/defunct.dat -ilq' exec -a '[kswapd0]' '/usr/bin/defunct'"

这里使用了 exec -a '[kswapd0]' 技巧——将进程名伪装成 Linux 内核线程 [kswapd0],用 ps aux 根本看不到它。

3.5 查看登录记录——找到攻击来源

last -10
root     pts/2        212.132.98.170    Mon Jun  1 (02:01)

6月1日凌晨,一个来自 212.132.98.170 的 IP 通过 SSH 登录了这台服务器——这就是攻击者。

3.6 Docker 容器的问题

还发现服务器上运行了两个可疑的 Docker 容器:

docker ps -a
traffmonetizer/cli_v2         ← 带宽贩卖工具
earnfm/earnfm-client:latest   ← 同类流量变现服务

这两个容器将服务器作为代理出口节点,虽然不是导致劫跳转的直接原因,但它们进一步消耗服务器资源且可能引来更多攻击。

第一轮清理

操作详情
停止并删除 defunct.service systemd 服务rm -f /lib/systemd/system/defunct.service /defunct.dat
杀掉 defunct / iptable6 / [kswapd0] 进程
删除 /usr/bin/defunct / /usr/bin/iptable6
清理所有 /etc/init.d/* 中的注入命令sed -i '/\/bin\/iptable6/d' /etc/init.d/*
删除 traffmonetizer / earnfm Docker 容器
修改 root / 面板 / 数据库密码
重启服务器验证✅ 跳转消失

第一阶段判断

当时以为是 defunct/iptable6 这个 rootkit 做的中间人攻击(MITM),在 HTTP 响应中注入 JavaScript 跳转代码。重启后确认跳转消失,认为是彻底解决了。

四、第二轮排查:跳转复发 —— 发现 Nginx Lua 后门

4.1 复发

清理后不到一个小时,手机端再次出现跳转到赌博网站的问题。PC 端访问正常,手机端(Android/iPhone)依然会 302 跳转。这意味着:

  1. 不是 defunct/iptable6 导致的(它们已被清除)
  2. 还有一套独立的、更隐蔽的后门在运行
  3. 这个后门只针对移动设备——说明攻击者很清楚用户群体

4.2 深入排查 Nginx 层

再次检查 Nginx 配置,这次更仔细地看有没有加载 Lua 模块:

nginx -V 2>&1 | grep -i lua

发现 Nginx 编译了 ngx_http_lua_module,说明支持 Lua 处理请求。

检查 nginx.conf,发现一行关键配置:

lua_package_path "/www/server/nginx/lib/lua/?.lua;;";

在 Lua 模块路径中找到一个可疑文件:

ls -la /www/server/nginx/lib/lua/
-rw-r--r--  1 www  www  20887 Mar 19 12:10 ngxd.lua

文件属主是 www(Web 用户),且被 chattr +i 锁定(不可删除)。

4.3 ngxd.lua 后门分析

这是整个攻击中最精巧的部分ngxd.lua(20887 字节)是一个完整的 Nginx Lua 后门模块,具备以下功能:

功能说明
User-Agent 检测根据 UA 判断设备类型(Android / iPhone / PC)并区分处理
比例跳转Android 10%、iPhone 10%、PC 0% 的概率触发跳转,控制感染面不易被察觉
远程配置pull.969a.xyz 拉取配置,可动态调整跳转比例和跳转域名
RSA 签名命令执行通过 X-Nginx-Authorize 请求头传递命令,RSA 验签后执行任意 shell
Bot 伪装Google/Bing/Baidu 爬虫不跳转,避免 SEO 处罚
路径例外/admin//api//login//static/ 等路径不跳转
跳转参数跳转时在 URL 中携带 Base64 编码的 host\machine_id\device_type

核心跳转逻辑:

-- 伪代码示意
function process_request()
    local ua = get_headers("User-Agent")
    if ua matches "Android" then
        if math.random() < 0.10 then  -- 10% 概率
            if not has_cookie("k") then
                set_cookie("k", "1", 86400)
                redirect("https://faradfdsa.anfdnc.xyz/...")
            end
        end
    elseif ua matches "iPhone" then
        -- 相同逻辑,10% 概率
    end
end

4.4 后门加载机制

第一次排查后,恢复 nginx.conf、注释掉 #include luawaf.conf;、删除 waf/ 目录,但没有 reload nginx,所以旧 worker 进程继续运行恶意逻辑。这就是为什么 nginx -T 看到的是干净配置,但实际请求仍然被劫持。

执行 nginx -s reload 后,新 worker 加载干净配置,跳转停止——导致误判为"已经完全修复"。

4.5 真正的持久化机制

清理 ngxd.lua 并 reload nginx 后不久跳转复发。这次检查了 /etc/init.d/nginx 启动脚本,发现被篡改:

# 在 /etc/init.d/nginx 中,攻击者插入了 prepare_nginx_conf() 函数
# 该函数在每次 nginx start/reload 时自动执行

prepare_nginx_conf():
  1. 检测 nginx.conf 中是否有 lua_package_path
  2. 有 → 将 DIR 设为 /www/server/nginx/lib/lua/ngxd.lua
  3. 通过 curl 从 https://pull.969a.xyz/ngxd.lua 下载后门
  4. chattr +i 锁定、chown www:www 伪造 Web 上传痕迹
  5. 向 VHOST_PATH 写入 _.conf,写入内容:
     rewrite_by_lua_block {
         local diversion = require "ngxd"
         diversion.process_request()
     }
  6. nginx 加载配置(_.conf 被 include 进来)
  7. **立刻删除 _.conf** ← 灭迹关键

为什么第一次没发现

原因说明
注意力集中在 nginx 配置层nginx -T、vhost conf、Lua 钩子,没检查 /etc/init.d/
_.conf 转瞬即逝只在 nginx 启动时存在几毫秒,加载完立刻被删
nginx -T 看不到运行时 _.conf 已不存在,dump 的配置是干净的
启动脚本不常被审计相比 nginx.conf 和 PHP 文件,init.d 脚本容易被忽视

正确做法:找到可疑文件后,立即全系统检索其名称或相关字符串:

grep -rn "ngxd\|pull.969a" /etc/ /root/ /usr/local/ 2>/dev/null

4.6 攻击链还原

宝塔面板 RCE(root 权限)
    → 第一阶段:植入 defunct/iptable6 rootkit + 带宽贩卖 Docker 容器
    → 2026-06-13 第一次排查,清除 rootkit

    → 第二阶段:通过 init 脚本注入防删除机制
    → 篡改 /etc/init.d/nginx,插入 prepare_nginx_conf() 函数
    → 上传 ngxd.lua 到模块路径,chown www:www 伪造成 Web 漏洞

    → 第一次排查时,木马恢复 nginx.conf、删除 waf/ 目录
    → 但未执行 nginx reload,旧 worker 继续跳转
    → nginx -s reload 后跳转消失,导致我误以为修复

    → 接着我把宝塔面板自动升级触发 nginx restart
    → init 脚本自动下载 ngxd.lua + _.conf → 跳转复发
    → 第二次排查发现 init 脚本被篡改 → 彻底清除

已知恶意域名

域名用途
212.132.98.170攻击者 SSH 来源 + defunct C2
13.57.38.185iptable6 C2(AWS EC2)
faradfdsa.anfXXc.xyz跳转中间站
dd0a000h4orvt.cloudfXXXt.net最终赌博站(CloudFront CDN)
pull.969a.xyzngxd.lua C2 配置拉取

五、第二轮清理

5.1 清除 Lua 后门

操作状态
删除 /www/server/nginx/lib/lua/ngxd.lua
同时检查并删除其他路径(btwaf / free_waf)
删除 /tmp/.machine_id / timestamp.txt / ngxd_*

5.2 修复 nginx 启动脚本

# 将 /etc/init.d/nginx 替换为干净的系统版本
# 用 chattr +i 锁定,防止再次被篡改
chattr +i /etc/init.d/nginx

5.3 完全重启 nginx

/etc/init.d/nginx stop
sleep 2
/etc/init.d/nginx start
注意:必须 restart(先 stop 再 start),因为 init 脚本的注入点只在 start 阶段执行。用 reload 不会触发 prepare_nginx_conf()。

5.4 验证

# 手机 UA 测试本地
curl -A "Mozilla/5.0 (Linux; Android 13)" http://127.0.0.1
# → 200 OK(无跳转)

# 手机 UA 测试外网
curl -A "Mozilla/5.0 (Linux; Android 13)" http://223.254.130.86
# → 200 OK(无跳转)

# 多轮确认 ngxd.lua 未复现
for i in 1 2 3; do
  [ -f /www/server/nginx/lib/lua/ngxd.lua ] && echo "WARNING" || echo "Check $i: clean"
  sleep 10
done

最终验证结果

检查项结果
rootkit 扫描(chkrootkit / unhide)✅ 无 rootkit
隐藏进程✅ 无
SSH 密钥✅ 仅授权密钥
系统 cron✅ 无恶意任务
面板插件✅ 仅标准插件
ngxd.lua 30 秒内复现检测(3 轮)✅ 未复现
手机 UA 跳转(3 轮)✅ 均返回 200

六、其他安全检查

检查项结果
SSH 配置✅ 密钥登录,禁用密码
Cron 任务✅ 仅宝塔面板 SSL 续签任务
PHP .user.ini✅ 无 auto_prepend_file
.htaccess✅ 无恶意重写规则
PHP 扩展✅ 无可疑 .so
LD_PRELOAD✅ 未设置
Systemd 服务✅ 无恶意服务
PHP webshell✅ 未发现
SUID 二进制✅ 标准系统文件
Docker 容器✅ 已全部清理
iptables NAT✅ 仅 Docker MASQUERADE

七、投毒入口分析

证据链

证据结论
ngxd.lua 目录属主 rootwww 用户无法写入,文件不可能是 Web 漏洞上传
nginx.conf / enable-php-00.conf 均属主 root需 root 权限才能修改
ngxd.luachown www:www人为伪造成 Web 上传痕迹,误导排查方向
宝塔面板版本 11.3.0(存在已知 RCE)宝塔面板 RCE 是最可能的初始入口

结论:宝塔面板 RCE 是最可能的入侵入口

本次感染的攻击面是 Nginx 层面的 Lua 后门 + init 脚本持久化,不涉及 PHP 代码层面。服务端已清理完毕后,本地源码确认干净。

八、经验和教训

  1. 不能只看运行时配置nginx -T 看到的配置可能和实际运行的不一致——_.conf 只在启动瞬间存在
  2. 查文件来源比删文件重要:找到文件后应追溯"谁写进来的",否则会复发。grep -rn "关键词" /etc/ /root/ 应在第一时间执行
  3. 持久化机制常藏在启动脚本/etc/init.d/、systemd units、cron、rc.local 都是需要重点检查的位置
  4. chattr +i 要双向使用:不仅要锁定恶意文件,更要锁定关键系统脚本本身
  5. 进程伪装越来越高级exec -a '[kswapd0]' 把进程名伪装成内核线程,ps 发现不了,必须用 lsof 查网络连接
  6. curl 正常 ≠ 网站正常:服务端本地 curl 看到的是原始响应,但浏览器请求可能被 Lua 层的 302 劫持
  7. 多维度排查顺序:Nginx 配置 → 系统进程 → 网络连接 → 启动脚本 → 登录日志,缺一不可
  8. 宝塔面板是最薄弱环节:面板以 root 运行、暴露在公网、历史漏洞多,安全问题任重道远。

九、建议措施

立即执行

# 修改所有数据库密码、Redis 密码
# 修改宝塔面板密码和密钥
# 更新宝塔面板至最新版
bt upgrade

# 安装 Fail2Ban 防止爆破
apt install fail2ban -y
systemctl enable fail2ban
systemctl start fail2ban

# 锁定关键配置文件
chattr +i /www/server/nginx/conf/nginx.conf

长期建议

  • 定期扫描:安装 rkhunterchkrootkit,每周扫描
  • 文件完整性:对 /www/server/nginx/conf//usr/bin/ 等关键目录启用 tripwireAIDE
  • 日志监控:启用访问日志,监控异常重定向和 SSH 登录
  • 最小权限:检查 www 用户对系统非必要目录的写权限
  • 宝塔面板:限制面板仅内网访问,或绑定域名 + HTTPS 访问
  • SSH 安全:确认 authorized_keys 已配置,关闭密码登录,修改端口

记录于 2026 年 6 月 13 日
PS:真羡慕韩国球迷啊!祝国足本期世界杯“夺冠”!!!

你认为这篇文章怎么样?
  • 0
    点赞
  • 0
  • 0
  • 0
    滑稽
  • 0
    尴尬
  • 0
    睡觉
  • 打赏
    打赏

评论 (1)

取消
头像
邮箱:
I P:
互动: