最近发现博客在手机上浏览时会自动跳转到第三方诈骗网站,经过排查发现是使用的 CDN 遭受了供应链投毒攻击。本文记录整个排查和修复过程。
问题现象
- 手机浏览博客时,页面会自动跳转到诈骗网站
- 主要影响移动端用户
- PC 端偶尔也会出现跳转
问题根因
cdn.staticfile.net 供应链攻击
经过排查,发现博客使用的 cdn.staticfile.net 在 2024 年遭受供应链攻击,这是一起与 Polyfill.io 相关的大规模攻击事件。
攻击者通过控制 CDN 源,在 JavaScript 文件中注入恶意代码,将用户(特别是移动端用户)重定向到诈骗网站。
受影响的 CDN 包括:
cdn.staticfile.net❌bootcdn.net❌polyfill.io❌- 其他多个国内 CDN
本博客受影响的资源
| 资源 | 原 CDN | 风险 |
|---|---|---|
| Highlight.js | cdn.staticfile.net | ⚠️ 高危 |
| Font Awesome | cdn.staticfile.net | ⚠️ 高危 |
| MathJax | cdn.staticfile.net | ⚠️ 高危 |
| Google Fonts | fonts.loli.net | ⚠️ 中危 |
修复方案
1. 替换被投毒的 CDN
将所有 cdn.staticfile.net 替换为安全可靠的 CDN:
- https://cdn.staticfile.net/highlight.js/11.7.0/highlight.min.js
+ https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js
- https://cdn.staticfile.net/font-awesome/6.4.0/css/all.min.css
+ https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css
- https://cdn.staticfile.net/mathjax/3.2.2/es5/tex-mml-chtml.js
+ https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js
2. 智能字体 CDN 切换
为了兼顾国内外用户,实现了智能字体 CDN 切换:
| 用户 | CDN |
|---|---|
| 国内 | google-fonts.mirrors.sjtug.sjtu.edu.cn |
| 国外 | fonts.googleapis.com |
实现逻辑:
- 检查 localStorage 缓存(7 天有效期)
- 无缓存时优先尝试国内 SJTUG 镜像
- 加载失败自动回退到 Google Fonts
- 最后一天后台静默刷新缓存
其他优化
在排查过程中,顺便修复了以下问题:
暗色模式闪烁 (FOUC)
问题:切换页面时先显示白色背景再变暗
原因:localStorage.getItem('theme') 可能返回 'auto',但 CSS 只识别 'light'/'dark'
修复:在 <head> 中立即计算有效主题值:
const saved = localStorage.getItem("theme") || "auto";
const systemPrefersDark = window.matchMedia(
"(prefers-color-scheme: dark)"
).matches;
const effective =
saved === "auto" ? (systemPrefersDark ? "dark" : "light") : saved;
document.documentElement.setAttribute("data-theme", effective);
首页无限滚动失效
问题:滚动到底部无法加载更多文章
原因:search.json 路径缺少 /blog 前缀,在 GitHub Pages 上 404
修复:
- fetch('/search.json')
+ fetch(basePath + '/search.json') // basePath = '/blog'
移动端 Hover 残留
问题:移动端 TOC 和菜单触摸后高亮不消失
原因:触摸屏的 :hover 状态会持续保持
修复:使用 @media (hover: hover) 只在支持鼠标悬浮的设备上应用 hover 效果
经验教训
- 不要盲目使用国内 CDN:很多所谓的"加速"镜像站安全性堪忧
- 定期检查第三方依赖:特别是 CDN 和 npm 包
- 优先使用官方 CDN:如 cdnjs.cloudflare.com、cdn.jsdelivr.net
- 移动端测试:供应链攻击往往只针对移动端用户
有想法?欢迎通过邮件讨论。