混合内容 (Mixed Content)
定义
混合内容是指通过 HTTPS 加载的页面中,部分脚本、图片、iframe 等子资源仍通过明文 HTTP 加载,削弱了整个页面的安全性。
混合内容指一个通过 HTTPS 交付的页面引用了明文 HTTP 的子资源。浏览器把它分为两类:主动混合内容(脚本、样式表、iframe、fetch/XHR 请求等)能改变整个页面,会被直接拦截;被动混合内容(图片、音频、视频)在当前的 Chrome 和 Firefox 中会被自动改用 HTTPS 重试,失败就不加载。
为什么重要
攻击者只要能篡改其中一个 HTTP 脚本,就能控制加载它的 HTTPS 页面,包括表单和未设置 HttpOnly 的 Cookie。用户看到的是锁形图标消失或出现警告,被拦截的资源加载不出来,页面功能随之出错。常见原因有:模板或 CMS 数据库里写死的 http:// 地址、老旧的第三方组件,以及网站接入 CDN 或 HTTPS 反向代理后,后端仍以为自己跑在 HTTP 上,生成的链接全是 http://。WordPress 站点迁移到 HTTPS 后没有改站点地址,就是典型例子。
例子
查找写死的 HTTP 引用,或者使用混合内容扫描工具:
curl -s https://example.com | grep -oE '(src|href)="http://[^"]+"'
从源头修正链接,再加一道保险,让浏览器自动升级剩余请求:
add_header Content-Security-Policy "upgrade-insecure-requests" always;
常见误区
- 混合内容只影响锁形图标的显示。 对图片来说如今基本如此,因为浏览器会自动升级;但混合的脚本或 iframe 等于把页面控制权交给了链路上的任何人。
- 资源所在服务器加个 HTTPS 跳转就行。 浏览器在发出请求之前就拦截了主动混合内容,根本看不到跳转,必须修改页面里的地址。
- 开了 HSTS 就没有混合内容。 HSTS 只升级发送过该头的主机,第三方的 HTTP 资源不受影响。