5月28日 01:41

iframe 有哪些安全漏洞?如何防范?

iframe 嵌入外部页面时,攻击面会显著增大。下面逐个拆解 iframe 的核心安全漏洞和对应防御方案。

点击劫持(Clickjacking)

攻击者用透明 iframe 覆盖在合法页面上,用户以为点击的是可见按钮,实际触发的是隐藏 iframe 里的操作——比如转账、授权、删除账户。

攻击代码示例

html
<style> .overlay { position: absolute; top: 0; left: 0; opacity: 0; z-index: 999; width: 100%; height: 100%; } </style> <h1>点击领取优惠券</h1> <iframe src="https://bank.com/transfer?to=hacker&amount=10000" class="overlay"></iframe>

防御方案(按优先级排列):

  1. CSP frame-ancestors(推荐):现代浏览器标准,替代已弃用的 X-Frame-Options
http
Content-Security-Policy: frame-ancestors 'self'; Content-Security-Policy: frame-ancestors 'self' https://trusted.com; Content-Security-Policy: frame-ancestors 'none';
  1. X-Frame-Options(兼容旧浏览器):
http
X-Frame-Options: DENY X-Frame-Options: SAMEORIGIN
  1. Frame Busting 脚本(兜底方案,可被绕过):
javascript
if (window.top !== window.self) { window.top.location = window.self.location; }

实际部署时,CSP frame-ancestors 和 X-Frame-Options 应同时设置,前者覆盖现代浏览器,后者兜底旧版本。

跨框架脚本攻击(XFS)

XFS 是 XSS 在 iframe 场景下的变体。攻击者在父页面中嵌入受害站点 iframe,利用 iframe 内页面的 DOM 可访问性(同源时)或 postMessage 通信的漏洞,窃取用户数据。

与 XSS 的区别:XSS 是注入恶意脚本执行,XFS 是利用 iframe 的跨框架能力,在父页面与 iframe 之间进行攻击。

防御:与点击劫持防御一致——限制页面被嵌入(frame-ancestors),并严格验证 postMessage 来源。

iframe 内的 XSS 攻击

当 iframe 加载了不受信任的内容源时,恶意脚本可以在 iframe 内执行,影响用户体验甚至窃取数据。

sandbox 属性是核心防御手段

html
<!-- 最严格:禁止一切 --> <iframe src="https://external.com" sandbox></iframe> <!-- 按需开放权限 --> <iframe src="https://external.com" sandbox="allow-scripts"></iframe> <iframe src="https://external.com" sandbox="allow-scripts allow-forms"></iframe>

sandbox 常用权限值:

权限值作用
allow-scripts允许执行 JavaScript
allow-forms允许提交表单
allow-same-origin允许作为同源对待(慎用,与 allow-scripts 组合会削弱安全性)
allow-popups允许弹窗
allow-top-navigation允许导航顶级窗口

关键点sandbox="allow-scripts allow-same-origin" 组合时要格外小心——如果 iframe 内的脚本与父页面同源,sandbox 的限制会被脚本自身绕过。

CSRF 与 iframe 的结合

攻击者在隐藏 iframe 中加载目标站点,利用用户已有的登录态发起伪造请求:

html
<iframe src="https://bank.com/transfer?to=hacker&amount=10000" style="display:none"></iframe>

防御方案

  1. SameSite Cookie:最直接的方案
http
Set-Cookie: session=abc; SameSite=Strict

Strict 阻止所有跨站请求携带 Cookie,Lax 允许顶级导航的 GET 请求携带。

  1. CSRF Token:服务器生成一次性令牌,表单提交时验证

  2. 验证 Referer / Origin 头:服务器检查请求来源

  3. 自定义请求头:AJAX 请求携带 X-Requested-With,跨域请求需预检

postMessage 信息泄露

iframe 与父页面跨域通信依赖 postMessage,使用不当会导致信息泄露。

不安全写法

javascript
// 发送时用 '*' —— 任何域都能收到 iframe.contentWindow.postMessage({ token: 'secret' }, '*'); // 接收时不验证来源 —— 任何域发来的消息都会处理 window.addEventListener('message', (e) => { handleData(e.data); });

安全写法

javascript
// 发送时指定目标域 iframe.contentWindow.postMessage({ type: 'request' }, 'https://trusted.com'); // 接收时严格验证 origin window.addEventListener('message', (e) => { if (e.origin !== 'https://trusted.com') return; if (!e.data || e.data.type !== 'response') return; handleData(e.data); });

防重放攻击:在消息中加入 nonce(一次性随机数),服务端验证 nonce 是否已使用过。

iframe 注入攻击

攻击者通过 XSS 漏洞注入 iframe 标签,在页面中嵌入恶意内容:

javascript
// 危险:直接插入未过滤的用户输入 element.innerHTML = userInput; // userInput 可能包含 <iframe src="恶意站点">

防御

javascript
// 方案1:DOMPurify 过滤 import DOMPurify from 'dompurify'; element.innerHTML = DOMPurify.sanitize(userInput); // 方案2:用 textContent 替代 innerHTML element.textContent = userInput; // 方案3:CSP 限制 frame-src // Content-Security-Policy: frame-src 'self' https://trusted.com;

iframe 网络钓鱼

攻击者通过 iframe 加载与目标站点高度相似的钓鱼页面,利用 allow-top-navigation 将顶层窗口重定向到恶意站点。

防御:sandbox 中不授予 allow-top-navigation,或使用 allow-top-navigation-by-user-activation(仅允许用户触发的导航)。

面试高频追问

Q:sandbox="allow-scripts allow-same-origin" 为什么危险? A:如果 iframe 内页面与父页面同源,脚本可以通过 frameElement.removeAttribute('sandbox') 移除 sandbox 限制,等同于没有 sandbox。只有 iframe 加载跨域内容时,这个组合才相对安全。

Q:X-Frame-Options 和 CSP frame-ancestors 有什么区别? A:X-Frame-Options 是旧标准,只支持 DENY / SAMEORIGIN / ALLOW-FROM 三个值,且 ALLOW-FROM 已被多数浏览器弃用。CSP frame-ancestors 是现代标准,支持多个源的白名单配置,优先级高于 X-Frame-Options。两者应同时部署以兼容旧浏览器。

Q:如何检测自己页面被 iframe 嵌入? A:前端可通过 window.self !== window.top 检测,但可被攻击者绕过(如设置 sandbox 禁止脚本)。服务端可通过 Referer / Sec-Fetch-Dest 头判断请求是否来自 iframe 加载。

Q:iframe 和 frame 有什么区别? A:frame 是 HTML4 的帧框架,必须放在 frameset 内,整个页面由多个 frame 拼成;iframe 是内联框架,可以嵌入到普通 HTML 文档的任意位置。frame 已在 HTML5 中废弃,iframe 仍在使用但需注意安全配置。

标签:Iframe