网站被投毒

2026-09-17,我发现 colobu.com 的页面上被加载了一个可疑 iframe:https://soduncdn.com/m.html。域名注册于十天前、没有任何 A 记录、被 6/89 个安全引擎标记。查了一圈之后,结论有点出乎意料。

结论

页面本身没被改。被投毒的是页面引用的那个第三方 CDN 脚本。

出问题的是一行看起来再普通不过的写法:

cdn.staticfile.org 会在极低概率下返回一个被追加了 383 字节的篡改版 jQuery(96169 字节,官方版本是 95786 字节)。这 383 字节干的事,就是往页面里塞一个隐藏 iframe。

关键证据

我在一次页面加载中抓到了篡改版,与官方的差异只有末尾追加的这一段:

前面两个 if(!!0) / if(!1) 是永远不会执行的死代码,纯粹用来混淆和改变文件特征。真正干活的是最后一句 document.writeln(atob(...)),解码后是:

0×0 尺寸、left:-1000px 挪到屏幕外、sandbox 却放开了 scripts / popups / forms —— 一个教科书式的隐藏 iframe 挂马。用户看到的 soduncdn.com/m.html 就是这条链上轮换的落地域名之一,当时已经被弃用。

完整的投毒链

隐藏 iframe 加载之后的链条:

落地页都是典型的黑帽引流站,页面上挂着 51.la、cnzz、百度统计的探针——拿正规统计服务来数自己的"业绩"。

顺带一提,这个注入只在移动端 UA 下才完整触发。桌面 UA 访问时页面干干净净,这也是我一开始 curl 页面源码什么都没发现的原因。

基础设施关联(最硬的一条线索)

把域名解析拉出来对比,脉络就很清楚了:

域名解析结果归属
cdn.staticfile.org45.125.35.x / 202.181.25.xCloudie Limited(香港,AS133731)
www.cdnboostcache.com45.125.35.232 / 202.181.25.73 / 103.231.15.135同上
soduncdn.com(用户看到那个)103.231.15.199同上,103.231.15.0/24 同一网段
投毒方和恶意托管方,是同一批基础设施,甚至就在同一个 /24 里。

还有一处破绽:cdn.staticfile.org 现在的响应头是 server: nginx + cache-control: no-store + 带 X-CSRF-TOKEN 的宽松 CORS。这已经不是一个静态 CDN 该有的样子了,背后跑的是某个应用服务器。这个域名当年是七牛提供的公益 CDN,现在经 cdn77.vip(注意不是正经的 cdn77.com)CNAME 指到了这批香港机器上。

排查中排除掉的可能

假设结论
页面源码被注入❌ 源码干净,0 个 iframe、0 处 sodun 引用
GitHub Pages / 服务器被改❌ 响应头正常,HTTP 301 强制跳 HTTPS,无明文劫持
本机 HTTPS 中间人❌ 系统钥匙串里没有任何非 Apple 根证书;直连与经代理拿到的证书完全一致(CN=staticfile.org)
本地 Clash 代理注入❌ 没有 MITM 证书就无法解密 HTTPS;直连和代理拿到的都是干净版本
其它 CDN 被改❌ cdn.bootcss.com、cdnjs、unpkg 逐个取样,哈希全部与官方一致
这里踩过一个坑值得记下来:本机 7890 端口挂着代理,curl 默认不走系统代理、浏览器走。一开始我用 curl 测了几十次都是干净的,差点得出"没问题"的结论,实际上两者的出口 IP 根本不是同一条路。排查这类问题,先确认自己走的是哪条链路。

修复建议

  1. 换掉 cdn.staticfile.org 和 cdn.bootcss.com。这两个同时期的老 CDN 都没有 SRI,现在又托管在可疑网段上。最稳的做法是把 jQuery / lazyload / MathJax 自托管到站点自己的静态目录。
  2. 加 SRI 完整性校验:。这样即使 CDN 再被投毒,浏览器会直接拒绝执行不匹配的脚本——最坏结果是交互功能坏掉,而不是被挂马。
  3. 加 CSP。GitHub Pages 不能自定义响应头,用 限制 frame-src 'self' https://utteranc.es,可以直接掐死这类注入的 iframe。
  4. 页面当前 integrity= 出现次数为 0,也没有任何 CSP —— 这是这次能被挂上的直接原因。

一个必须说清楚的局限

投毒我总共只命中 1 次,之后约 500 次请求(直连 / 经代理、桌面 / 移动 UA、带不带 Referer、带不带查询串)都没能再复现。

所以"投毒发生在 CDN 侧"这个结论,靠的是排除法推理:那次响应的 TLS 校验有效 + 本地无 MITM 证书 + 恶意域与 CDN 同网段。按命中率估算大概在 0.2% 量级,属于低概率选择性下发——这类投毒本来就会刻意控制频率来规避检测。

另外我抓到的样本注入指向 cdnboostcache.com,和当时看到的 soduncdn.com 是同一家族的不同轮换域名。机制一致,但严格说不是同一个 URL。

附:IOC 清单

附:这次用到的排查手法

  1. 别只看源码——现代挂马是运行时注入的,源码干净不代表安全。
  2. CDP 抓 Network.requestWillBeSent 的 initiator.stack,能直接拿到"是哪个脚本发起了这个恶意请求"。
  3. 逐次加载做内容哈希 diff——谁的内容会变,谁就是注入源。这次正是靠这招锁定了 jQuery。
  4. 用 curl 时注意代理——--noproxy '*' 和 -x 是两条完全不同的路,出口 IP 不同,看到的可能是两个世界。
  5. 把域名解析拉出来对比网段——投毒方和托管方经常住在一起,这是最快建立关联的手段。
添加评论
点赞收藏
点踩分享查看原文
评论
?
参与讨论