B03 内嵌内容与安全

2026-10-31 14:560 阅读约 11 分钟HTML

摘要:iframe 把一个完整的第三方页面嵌进当前文档,代价是同时引入对方的脚本、样式与请求能力。默认配置下,被嵌页面与宿主共享部分能力,一个恶意广告位足以读取宿主页面的输入内容。本文给出 sandbox、allow、referrerpolicy 三项限制的组合方式,并用四步操作演示去掉限制后的后果。
关键词:iframe,sandbox,同源策略,内嵌,跨域

所属:frontend/html / B-进阶 | 上一篇:B02-多媒体与响应式图片 | 下一篇:B04-全局属性与交互元素

1 引言

内嵌内容在真实页面里几乎不可回避:地图、视频、代码片段预览、支付授权页。问题在于,内嵌等于把一段不受控的代码放进当前文档的渲染环境。

本文说明三件事:内嵌内容的默认能力边界、三项限制属性的组合方式、以及验证限制是否生效的方法。范围见表 1-1。

项 本文覆盖 本文不覆盖
内嵌 iframe 的 src、sandbox、allow、loading、referrerpolicy 站点隔离与进程模型
替代方案 object、embed 的适用边界 插件式内容与本地文件预览
安全 同源策略、点击劫持、响应头 X-Frame-Options CSP 完整策略(C 阶段)

2 预备知识

项 要求 核对方式
环境 A02 的本地服务器 能访问 localhost
文件 html-practice/embed.html 与 inner.html 两个文件同目录
浏览器 Chrome 130+,开发者工具 Console 可用 能看到被拦截的报错
前置 A08 能写语义骨架

3 原理与实现

3.1 内嵌带进来的三类能力

被嵌页面默认继承宿主的部分能力,风险集中在三处,如图 3-1 所示。

flowchart TD
    I["iframe 加载第三方页面"] --> A["脚本执行<br/>可在自身文档内运行"]
    I --> T["顶层导航<br/>可把整页跳走"]
    I --> S["弹窗与表单<br/>可触发下载或新窗口"]
    A --> G["sandbox 收紧"]
    T --> G
    S --> G
    G --> OK["按需白名单放行"]

图 3-1 内嵌内容的三类能力与收紧路径

图上可见:sandbox 是白名单机制——不写任何令牌即全部禁用,再按需逐项放开。

3.2 严格模式与按需放行

先写最严格的形式,再逐项放开,是唯一可控的顺序。

<!-- 宿主页面:embed.html -->
<h2>代码片段预览</h2>
<iframe
  src="./inner.html"
  title="代码片段预览"
  width="640"
  height="320"
  loading="lazy"
  sandbox="allow-scripts"
  referrerpolicy="no-referrer"
></iframe>

<h2>地图</h2>
<iframe
  src="https://example.com/map"
  title="位置地图"
  width="640"
  height="320"
  loading="lazy"
  allow="fullscreen"
  referrerpolicy="strict-origin-when-cross-origin"
></iframe>
<!-- 被嵌页面:inner.html -->
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <title>被嵌页面</title>
  </head>
  <body>
    <p>本页试图执行脚本与跳转,用于验证限制是否生效。</p>
    <button id="go">跳转到上级</button>
    <script>
      document.getElementById('go').addEventListener('click', () => {
        window.top.location.href = 'https://example.com/';
      });
    </script>
  </body>
</html>

sandbox 常用令牌与效果见表 3-1。

令牌 放开的能力 是否建议
(不写任何令牌) 脚本、表单、弹窗、同源全部禁用 静态内容首选
allow-scripts 允许执行脚本 按需,慎用
allow-same-origin 保留同源,可与宿主共享存储 与 scripts 同用风险最高
allow-forms 允许提交表单 表单类内嵌需要
allow-popups 允许打开新窗口 按需
allow-presentation 允许进入演讲模式 演示类需要

内嵌方式的选择见表 3-2。

方式 适用场景 优点 风险
iframe 第三方页面、文档、地图 隔离完整、用法稳定 需自行收紧权限
object PDF、SVG 等文档对象 支持类型声明 移动端支持不一致
embed 插件式内容 写法最简单 无回退内容,语义弱
直接链接 内容无需内嵌展示 零风险 打断浏览流程

规则三条:sandbox 一律从空值开始,逐项放开;allow-scripts 与 allow-same-origin 同时出现时限制基本失效,必须同用时需评估来源可信度;每个 iframe 必须写 title,否则朗读软件只念「框架」。

4 验证与讨论

  1. 用本地服务器打开 embed.html,内嵌区域显示被嵌页面。
  2. 点击被嵌页面中的「跳转到上级」按钮,观察整页是否被跳走;带 sandbox="allow-scripts" 时应被阻断,Console 出现导航被拒绝的报错。
  3. 把 sandbox 改为 sandbox="allow-scripts allow-same-origin",重复步骤 2,观察限制失效。
  4. 删除 title,用朗读软件或无障碍面板查看框架的朗读结果。
检查项 预期结果 说明
顶层导航被阻断 整页未被跳走,Console 有报错 sandbox 生效
脚本仍可执行 按钮点击有响应 allow-scripts 生效
同源保留后 脚本可修改上层页面 组合令牌的危险性
新窗口被拦截 弹窗未打开 未放行 allow-popups
框架说明 朗读软件读出 title 文字 title 属性

讨论与局限。 sandbox 只能约束被嵌页面,无法阻止宿主主动向对方发送数据;跨域内嵌的通信需要 postMessage 并校验来源。另 X-Frame-Options 由被嵌方设置,决定自己是否允许被嵌,宿主侧无法覆盖。

5 常见问题

现象 原因 处理
内嵌区域一片空白 对方设置了 X-Frame-Options: DENY 改用直接链接或对方提供的嵌入地址
内嵌页样式错乱 sandbox 未放行所需能力 逐项补令牌,逐次验证
点击内嵌页后整页跳走 未设置 sandbox 从空 sandbox 开始收紧
移动端高度塌陷 只写了 width,未写 height 同时给宽高,或用 CSS 宽高比
内嵌内容拖慢首屏 未加 loading="lazy" 非首屏内嵌一律懒加载

6 结论

序号 结论 依据
1 内嵌等于引入一段不受控代码 图 3-1
2 sandbox 从空值起步,按需放开 表 3-1
3 allow-scripts 与 allow-same-origin 不宜同用 表 3-1
4 能不用内嵌就不用,直接链接风险最低 表 3-2

参考文献

[1] MDN Web Docs · iframe 的 sandbox 属性,https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/iframe(访问于 2026-10-29)
[2] OWASP · Clickjacking Defense Cheat Sheet,https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html(访问于 2026-10-29)

返回文章列表

评论 0

0/2000

还没有评论,快来抢沙发吧~