iframe 安全
iframe(内嵌框架)允许在一个页面中嵌入另一个页面,但也引入了多种安全风险:点击劫持、跨域信息泄露和恶意代码注入。本节将介绍 iframe 的 sandbox 属性、allow 属性、CSP frame-ancestors 指令和 X-Frame-Options 响应头的安全配置方法。
前置知识
阅读本节前,建议先了解:CSP 内容安全策略
iframe 安全风险
| 风险 | 说明 |
|---|---|
| 点击劫持 | 透明 iframe 覆盖在正常内容上,诱导用户点击 |
| 跨域信息泄露 | iframe 中的页面可能通过 window.parent 访问父页面信息 |
| 恶意代码 | iframe 中的第三方页面可能包含恶意脚本 |
| 资源消耗 | 恶意 iframe 可能消耗带宽和 CPU |
sandbox 属性
sandbox 属性为 iframe 施加安全限制:
html
<!-- 完全沙箱(最严格) -->
<iframe src="https://example.com/embed" sandbox></iframe>
<!-- 允许特定功能 -->
<iframe
src="https://example.com/embed"
sandbox="allow-scripts allow-same-origin allow-forms"
></iframe>sandbox 值
| 值 | 允许的操作 |
|---|---|
| (空) | 最严格,禁止所有功能 |
allow-scripts | 允许执行 JavaScript |
allow-same-origin | 允许同源访问(谨慎使用) |
allow-forms | 允许提交表单 |
allow-popups | 允许打开新窗口 |
allow-popups-to-escape-sandbox | 允许弹出的窗口脱离沙箱 |
allow-modals | 允许模态对话框(alert、confirm) |
allow-top-navigation | 允许导航到顶层窗口 |
allow-downloads | 允许下载文件 |
allow-presentation | 允许嵌入演示 |
allow-scripts + allow-same-origin 的风险
同时使用 allow-scripts 和 allow-same-origin 可能允许 iframe 中的脚本移除自身沙箱限制。仅在你完全信任 iframe 内容时使用。
allow 属性
allow 属性为 iframe 配置权限策略(Permissions Policy):
html
<!-- 使用 allow 属性配置特定权限 -->
<iframe
src="https://example.com/embed"
allow="camera; microphone; fullscreen"
allowfullscreen
></iframe>常用 allow 值
| 权限 | 说明 |
|---|---|
camera | 使用摄像头 |
microphone | 使用麦克风 |
geolocation | 获取地理位置 |
fullscreen | 全屏显示 |
autoplay | 自动播放音视频 |
encrypted-media | 加密媒体 |
picture-in-picture | 画中画模式 |
clipboard-write | 写入剪贴板 |
gyroscope | 使用陀螺仪 |
accelerometer | 使用加速度计 |
CSP frame-ancestors
frame-ancestors 指令控制哪些页面可以嵌入当前页面:
# 禁止任何页面嵌入
Content-Security-Policy: frame-ancestors 'none';
# 仅允许同源页面嵌入
Content-Security-Policy: frame-ancestors 'self';
# 允许特定域名嵌入
Content-Security-Policy: frame-ancestors 'self' https://partner.example.com;X-Frame-Options
X-Frame-Options 是 CSP frame-ancestors 的旧版替代,但仍被广泛支持:
# 禁止任何页面嵌入(推荐)
X-Frame-Options: DENY
# 仅允许同源页面嵌入
X-Frame-Options: SAMEORIGIN
# 允许指定域名嵌入
X-Frame-Options: ALLOW-FROM https://partner.example.comCSP frame-ancestors vs X-Frame-Options
| 特性 | X-Frame-Options | CSP frame-ancestors |
|---|---|---|
| 支持 | 所有浏览器 | 现代浏览器 |
| 多域名 | 不支持(ALLOW-FROM 非标准) | 支持 |
| 规范 | 过时 | 推荐使用 |
| 并用 | 可以同时使用 | 优先级更高 |
点击劫持防护
html
<!-- 方法 1:X-Frame-Options(服务器响应头) -->
<!-- X-Frame-Options: DENY -->
<!-- 方法 2:CSP frame-ancestors -->
<meta http-equiv="Content-Security-Policy" content="frame-ancestors 'none';">
<!-- 方法 3:JavaScript 防护(辅助手段) -->
<script>
if (window.top !== window.self) {
window.top.location = window.self.location;
}
</script>
<!-- 方法 4:CSS 防护(辅助手段) -->
<style>
/* 防止页面被透明 iframe 覆盖 */
body {
display: none !important;
}
</style>
<noscript>
<style>body { display: block !important; }</style>
</noscript>实战示例
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>iframe 安全示例</title>
<!-- 禁止页面被 iframe 嵌入 -->
<meta http-equiv="Content-Security-Policy" content="frame-ancestors 'none'">
</head>
<body>
<h1>安全嵌入第三方内容</h1>
<!-- 安全的 iframe 配置 -->
<iframe
src="https://trusted-partner.com/widget"
sandbox="allow-scripts allow-forms allow-popups"
allow="fullscreen"
allowfullscreen
width="600"
height="400"
loading="lazy"
title="第三方内容"
referrerpolicy="no-referrer-when-downgrade"
></iframe>
<!-- 视频嵌入 -->
<iframe
src="https://www.youtube.com/embed/dQw4w9WgXcQ"
sandbox="allow-scripts allow-same-origin allow-popups allow-forms"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen
loading="lazy"
title="YouTube 视频嵌入"
></iframe>
</body>
</html>注意事项
- 始终使用 sandbox:即使是可信的内容也应限制权限
- 不要同时使用 allow-scripts 和 allow-same-origin:除非完全信任
- 设置 title 属性:为 iframe 提供无障碍标签
- 使用 referrerpolicy:控制引荐信息泄露
- 测试嵌入内容:确保第三方 iframe 不会影响页面安全
最佳实践
- 对所有 iframe 使用 sandbox 限制
- 使用 CSP frame-ancestors 或 X-Frame-Options 防止点击劫持
- 使用 allow 属性按需授予权限
- 为 iframe 提供 title 属性
- 使用 referrerpolicy 限制引荐信息
- 加载不可信 iframe 时使用 loading="lazy"
下一节
继续学习:表单安全