视频加载失败

一次 Nginx Lua 木马应急响应实录:从移动端跳转博彩站到 root 级入侵溯源

3752 字
19 分钟
一次 Nginx Lua 木马应急响应实录:从移动端跳转博彩站到 root 级入侵溯源
微信二维码

联系方式 & 交流群

  • 微信: gzs-47

进微信群请联系博主,各位觉得文章对你有帮助的话可否打赏一些呀~


事件等级:🔴 严重 — 已确认 root 级入侵
攻击链:root SSH 认证登录 → Nginx Lua 木马植入 → 服务脚本持久化 → 日志清洗
持久化方式:init.d 服务脚本回灌 + chattr +i 文件锁定 + 时间戳伪造
处置结果:活跃链路已切断,已知残留已隔离,证据已归档


一、事件概述#

某电商站点运维人员收到用户反馈:移动端访问站点时偶发跳转到博彩风格的外部页面,桌面端访问正常。同时该站点通过 CDN 访问时频繁出现 520 错误。

初步排查后发现,这不是前端 Bug,也不是支付插件异常,而是一次已经落证的服务器侧入侵事件。攻击者通过已认证的 root SSH 会话进入系统,在 Nginx 层植入 Lua 恶意模块实现流量劫持,并配合了服务脚本持久化、文件不可变属性锁定和日志清洗等全套反取证手段。

本文脱敏后完整记录此次应急响应的全流程,包括排查思路、取证方法、处置步骤和经验教训。


二、事件影响#

  • 业务层面:移动端用户访问站点时被服务端重定向到外部博彩风格域名,直接影响用户体验和业务信誉。
  • CDN 层面:CDN 出现间歇性 520 错误,并非单纯的 CDN 问题,而是叠加了 Nginx worker 进程崩溃风险。
  • 支付链路:排查期间发现支付反代服务偶发超时,经分析属于 Docker 网络桥接配置问题,与 Lua 木马无直接关联。
  • 运维安全:root 密码登录仍处于开放状态,且系统日志被清洗,导致部分入侵入口无法百分百回溯。

三、核心时间线#

3.1 首次入侵(约一个月前)#

HIDS 记录到一条真实的 root SSH 会话,该会话执行了以下操作:

动作说明
修改 Nginx 配置文件操作 proxy.conf 等反向代理配置
植入恶意 Lua 文件将恶意 WAF 脚本写入 Nginx 相关目录
锁定文件对植入文件执行 chattr +i 使其不可变
伪造时间戳修改文件修改时间,掩盖植入时间点
重启 Nginx执行 nginx -t && /etc/init.d/nginx restart 使木马生效
清洗日志清空 /var/log/auth.logwtmpbtmp、审计日志
清除痕迹执行 history -clastlog 清除命令历史和登录记录

关键判断:这不是端口扫描或爆破尝试,而是「已认证」的入侵行为——攻击者拥有合法的 root 凭据。

3.2 第二次落地(事发当天凌晨)#

系统出现第二段落地行为:

  • 服务启动脚本 /etc/init.d/nginx 被植入恶意回灌逻辑
  • 出现可疑的 .so 动态库文件
  • 出现隐藏标记文件,内容为木马版本标识
  • 内核日志出现 Nginx worker 进程的段错误

关键判断:这不是临时文件误报,而是服务重启级的持久化链路——即使当前恶意文件被删除,重启 Nginx 后木马会自动复活。

3.3 应急响应窗口#

从用户反馈到完整处置,应急响应推进路径如下:

  1. 复现移动端 UA 与桌面端访问表现差异
  2. 对比应用层日志和 Nginx 访问日志
  3. 确认异常 302 重定向出现在 Nginx 层而非 PHP 应用层
  4. 通过 nginx -T 导出全量配置,顺 Lua 加载路径定位恶意模块
  5. 先备份证据,再替换为 no-op 空壳
  6. 深挖持久化点,确认 init.d 脚本回灌逻辑
  7. 清理认证面、隔离残留样本、打包证据并记录哈希
  8. 复测移动端、桌面端、支付接口和关键服务状态

四、排查分析过程#

4.1 区分问题层级#

用户报障后,首先要判断异常发生在哪一层:

层级如果是这层的问题实际表现
前端 / CDN 缓存服务端日志仍返回正常 HTML❌ 服务端日志存在异常 302
PHP 应用层应用代码、路由或日志中能找到跳转逻辑❌ 应用层无异常
Nginx 请求入口层访问日志出现应用无感知的 302✅ 命中了

本次通过移动端 UA 请求复现了 302,并发现跳转参数中包含原始域名和设备类型,说明跳转逻辑在 HTTP 请求入口层——也就是 Nginx 层被劫持。

4.2 访问日志分析#

访问日志中出现了关键特征:

正常路径如 /、/item/1、/products → 间歇性 302,与正常 200 混杂

这个特征非常关键:

  • 正常业务跳转通常有稳定规则(如未登录跳登录页)
  • 恶意流量劫持常按设备类型、流量比例、来源 Referer 或时间随机触发
  • 本次恶意 Lua 中确实存在移动端比例控制逻辑——只在部分移动端请求中触发跳转

4.3 定位 Nginx Lua 加载链#

审计 nginx -T 全量配置后,重点排查以下位置:

  • lua_package_path — Lua 模块搜索路径
  • rewrite_by_lua / access_by_lua — 请求阶段 Lua 钩子
  • include luawaf.conf — WAF 配置文件
  • Nginx Lua 库目录
  • WAF 脚本目录
  • 反向代理配置文件

最终确认活跃恶意模块是一个伪装成正常模块名的 .lua 文件,内容包含:

  • 外部博彩风格跳转域名
  • 移动端 UA 识别和比例触发逻辑
  • 远程配置拉取功能
  • ngx.redirect() 跳转实现

与线上表现完全一致。

4.4 先取证再处置#

本次没有直接删除任何可疑文件。 原因:

  1. 直接删除会破坏法证链,无法回溯入侵过程
  2. 直接删除 Lua 文件可能导致仍存在的调用点把 Nginx 打挂
  3. 攻击者使用了 chattr +i、时间戳伪造和重启回灌,单点删除不能解决持久化

处置策略:

  • 将恶意原件保留到证据备份目录
  • 生产路径中的恶意 Lua 替换为同名 no-op 空壳模块
  • 保留导出函数签名,避免隐藏调用点异常
  • 执行 nginx -t 验证配置后再 reload

4.5 追踪持久化机制#

仅替换当前活跃恶意模块后,不能认为修复完成。后续检查发现 init.d 服务脚本已被改造:

  • 从外部 URL 拉取远程载荷
  • 向 Nginx 配置文件写入 Lua 钩子
  • 操作 lua_package_path 确保模块加载
  • 操作 ld.so.preload 预加载共享库
  • 配合 chattr +i 保护植入文件

这就是木马的复活机制——只要 Nginx 服务重启,远程载荷会重新落地,配置会被重新注入。清理当前文件而不处理服务脚本,等于什么都没修。

4.6 用 HIDS 建立根因证据链#

系统日志和 shell history 被清空后,常规取证手段失效。本次的关键证据来自 HIDS(主机入侵检测系统)的日志:

  • HIDS 中保留了 root SSH 会话记录及命令样本
  • 能证明约一个月前已发生真实入侵
  • 这个证据比猜测 IP 来源、猜测插件漏洞有价值得多

教训:HIDS 日志是日志清洗后唯一可信的证据源,必须保证不被同机单点覆盖,最好外送或异地备份。

4.7 扩展扫描残留#

切断已知攻击链后,继续检查:

检查项内容
进程当前进程列表、高 CPU 进程
端口监听端口和对应进程
服务systemd 启用服务和 timer
定时任务root 与系统级 crontab
预加载/etc/ld.so.preload
启动脚本shell profile、自启动脚本
认证文件authorized_keys、uid=0 账户
SUIDSUID 提权文件
Nginx worker当前加载的动态库映射
近期变更最近修改的系统文件
IOC 搜索恶意模块名、可疑域名、隐藏标记文件

最终确认并隔离了三个残留工件:隐藏标记文件、恶意动态库、异常数据文件。

4.8 认证面收敛(避免自锁)#

发现 root 已泄露后,凭据轮换必须做,但不能为了「看起来更安全」直接关闭当前唯一的远程入口。

本次策略:

  1. 清空 root 的 authorized_keys
  2. 隔离未确认但仍需使用的 SSH 密钥
  3. 确认没有其他 uid=0 账户或异常用户的认证文件
  4. 暂时保留 root 密码登录,等待新管理员入口就绪后再关闭

这是安全和可运维之间的必要取舍——没有替代入口时直接关闭 root 登录,只会把正常运维锁在外面。

4.9 四层验证#

验证层次检查内容结论
配置层nginx -tnginx -T 全量导出✅ 无语法错误,无恶意 include
运行层进程、端口、worker 映射库、内核日志✅ 无崩溃,无异常动态库加载
业务层移动端 UA / 桌面端 UA 访问核心页面✅ 200 正常,无跳转
支付层支付配置接口、支付回调日志✅ 200 正常

只看服务状态 active 不等于业务可用;只看页面返回 200 也不等于木马已清理。必须四层同时验证。


五、处置措施总结#

已执行操作#

  • 将恶意 Lua 模块替换为 no-op 安全空壳
  • 将恶意 WAF 脚本替换为安全空壳
  • 移除 init.d 服务脚本中的恶意回灌逻辑
  • 移除 Nginx 全局配置中的异常 lua_package_path
  • 去除攻击者遗留在相关文件上的 immutable 属性
  • 隔离隐藏标记文件、恶意动态库、异常数据文件
  • 清理 root 本机 SSH 私钥驻留
  • 归档完整事件证据并生成 SHA256 校验值
  • 恢复 Docker bridge 网关,修复支付反代超时问题

后续动作#

24 小时内:

  • 持续观察 Nginx 访问日志中的异常状态码
  • 持续观察内核日志中的 worker 崩溃
  • 观察支付链路的稳定性
  • 保存 CDN 安全事件和访问日志

1-3 天内:

  • 新建非 root 管理员用户并配置公钥
  • 验证新入口可用后,关闭 root 密码直接登录
  • 轮换面板密码、API key、部署密钥和数据库密码
  • 将关键日志外送或定时同步到异地

中期:

  • 评估系统重装和业务迁移窗口
  • 用干净系统重新部署服务栈
  • 只迁移业务数据,不迁移旧系统脚本和二进制
  • 建立上线后基线:端口清单、文件哈希、日志保留策略

六、经验教训#

1. 偶发跳转必须优先怀疑请求入口层#

移动端跳转博彩站、桌面端偶发正常——这是典型的按 UA 或比例触发的流量劫持特征。不能只从前端缓存或应用路由找原因,必须第一时间查 Nginx 层的异常。

2. CDN 520 可能是源站进程崩溃#

CDN 的 520 错误表示源站连接异常。本次 520 与恶意 .so 文件导致的 Nginx worker 进程崩溃直接相关。排查 CDN 错误时必须同时看源站内核日志和 worker 状态。

3. 单点删除木马不等于修复#

攻击者使用了:

  • 服务脚本持久化(重启复活)
  • chattr +i 文件不可变属性(防删除)
  • 时间戳伪造(掩盖时间线)
  • 日志清洗(销毁证据)

只替换一个恶意文件会留下重启复活的风险,必须深挖持久化链。

4. 证据保存必须早于清理#

先打包证据、记录哈希、保留备份,再清理生产路径。否则后续无法解释完整的入侵链,也无法判断是否存在第二阶段攻击。

5. 安全加固不能盲目锁死#

关闭 root 密码登录是正确方向,但前提是有可验证的新管理员入口。没有替代入口就直接关闭,等于把自己也锁在门外。

6. HIDS 是日志清洗后唯一的可信证据源#

系统日志被清空后,HIDS 日志成为了唯一能证明入侵时间点和攻击行为的关键证据。后续必须保证 HIDS 日志异地存储,不能被同机攻击者一并清理。

7. 运行态问题要和入侵事件分层处理#

本次排查中发现的支付反代超时问题,经分析是 Docker 网络配置问题,与 Lua 木马无关。应急响应中必须严格区分:

  • 安全事件(入侵、木马、持久化)
  • 运行态故障(网络、配置漂移、资源耗尽)
  • 业务 Bug(代码逻辑、支付流程)

混为一谈会误导排查方向,浪费时间。


七、应急响应检查清单#

以下模板可直接复用于类似事件的排查:

1. 复现用户侧异常
记录 UA、URL、时间、响应码、跳转目标
2. 分层对比日志
CDN → Nginx → 应用 → 系统日志,定位异常发生层级
3. 审计 Web 服务器配置
导出全量配置,检查 Lua/WAF/include/proxy/rewrite/动态模块
4. 搜索 IOC
关键词搜索,但不要在取证前删除任何文件
5. 取证归档
对可疑文件做 stat、lsattr、sha256sum、备份归档
6. 检查持久化点
systemd、init.d、cron、profile、ld.so.preload、Docker entrypoint
7. 检查认证面
uid=0 账户、authorized_keys、私钥、面板用户、API key
8. 检查运行态
进程、端口、worker 映射库、内核崩溃日志
9. 最小化清理
先切断活跃链路,再处理持久化机制和残留文件
10. 重新验证
配置层 → 运行层 → 业务层 → 支付层,四层全部验证
11. 归档与复盘
归档证据和哈希,记录回滚点与剩余风险

八、判断边界#

可以确认的:

  • 存在已认证的 root SSH 入侵行为
  • 存在 Nginx 服务脚本级持久化机制
  • 移动端博彩跳转来自服务端 Nginx Lua 恶意模块
  • 恶意动态库与 Nginx worker 进程崩溃相关
  • 已知活跃链路已切断,已知残留已隔离

不能百分百确认的:

  • 最初 root 凭据是如何泄露的
  • 是否还存在未知 rootkit 或内核级隐藏组件
  • 不同时间点的两次操作是否完全同源
  • 不重装系统的情况下机器是否永远可信

因此后续安全策略不应停留在「已清理木马」,而应按「已发生 root 级入侵后的恢复流程」推进——最终闭环仍是重装系统、重建凭据、重新部署业务。


本文由真实应急响应案例脱敏整理,涉及域名、IP、路径等信息已做匿名化处理。

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

相关文章智能推荐
1
虚拟发卡系统回调伪造漏洞全链路拆解 — 从备份文件泄露到批量盗取卡密
漏洞分析深度分析一起针对 ACG-Faka + BEpusdt 的真实攻击事件:攻击者通过两条路径窃取支付密钥——下载 Web 根目录残留的备份文件,或利用 Nginx 配置错误直读 Config.php 源码——进而伪造合法回调通知批量盗取卡密。附官方安全公告、五站实测审计结果与完整防御方案。
2
CVE-2026-33032:Nginx UI MCP 未授权访问漏洞详解 (CVSS 9.8)
漏洞分析CVE-2026-33032 是 Nginx UI 的严重未授权访问漏洞,CVSS 评分 9.8。攻击者可通过/mcp_message 端点无需认证调用所有 MCP 工具,实现 Nginx 服务完全接管。本文详解漏洞原理、复现步骤和临时缓解方案。
3
Stripe 协议支付自动化深度拆解:从 HAR 抓包到纯 API 全链路实现
技术分析完整拆解 Stripe 协议支付的技术实现:从浏览器 HAR 抓包逆向 Stripe Checkout Session 全流程,到纯 API 无浏览器实现 ConfirmationToken 创建、PaymentIntent 确认、3DS 验证挑战,再到 TLS 指纹对抗、代理池架构和反欺诈绕过。附 5 套不同技术栈的完整实现源码下载。
4
GPT-5.6-Sol 隐藏模型无限调用指南 - 任意付费账号不消耗额度(2026 年 8 月实测)
AI 工具2026 年 8 月实测,任意 ChatGPT 付费账号(Plus/Pro/Team)通过 Codex 调用隐藏的 gpt-5.6-sol-wm 模型,不消耗额度、不计入消费明细,附完整配置教程
5
Gmail Sanitizer 深度拆解:8 步全链路凭据切断的自动化实现
技术分析从 DrissionPage 浏览器自动化到 AES-256-GCM 加密冷库,从 Sudo Gate 循环挑战到 Cloudflare Email Worker 极速接码——完整解析一款 Google 账号全链路凭据切断系统的技术内幕。
随机文章随机推荐
Profile Image of the Author
47工作室
47工作室:记录技术实践与安全研究。
公告
欢迎来到 47工作室!微信:gzs-47
分类
标签
最新动态
站点统计
文章
39
分类
16
标签
165
总字数
121,285
运行时长
0
最后活动
0 天前
站点信息
构建平台
Local
博客版本
站点 vunknown
文章许可
CC BY-NC-SA 4.0