跳到正文
>_ITDITDWeb 安全平台

术语表

什么是点击劫持 — 用透明陷阱让你按下「看不见的按钮」的攻击

点击劫持是把真实页面变透明后叠加到另一个站点上,诱导用户点击「看不见的按钮」的攻击。本文用图解说明其原理,并从防御视角讲解核心防御手段(用 CSP frame-ancestors、X-Frame-Options 让自己的站点无法被他站嵌入),不公开攻击步骤。

发布于 2026-06-10 更新于 2026-06-10 1 分钟阅读

「我以为按下的是这个按钮,实际却是背后另一个页面的按钮」——这就是点击劫持。本文讲解其原理与可靠的防御方法(不公开攻击步骤)。

什么会被盯上

「一键即可完成、而且有价值的操作」是攻击目标。

容易被盯上的操作为什么会被盯上
转账、购买的确认一键即可让金钱发生流动
修改设置(可见范围、授权许可)之后会导致账号被接管或信息被获取
OAuth/权限的「允许」按钮被擅自批准账号关联授权
社交媒体的关注、点赞、发帖被滥用于擅自传播、刷赞

为什么会成立(原理)

浏览器可以用 iframe 加载另一个站点并叠加显示。攻击者把这个 iframe 设为透明(不透明度为 0),用户看到的只有放在下方的假 UI。用户按下「假按钮」时,从坐标上看,正叠加在其上方的真实按钮就被按下了。

攻击者的页面「您中奖了!请按下方按钮」
= 叠加着透明的 iframe(真实的银行/设置页面)
↓ 用户按下「看得见的假按钮」
实际被按下的是正上方真实的「执行」按钮
↓ 在本人已登录的状态下
转账、修改设置、授权作为「本人的操作」完成
在攻击者的页面上把真实站点透明叠加,看得见的只有假 UI。点击被吸入透明的真实页面。

它与 CSRF 相似,但 CSRF 是「在背后发送请求」,而点击劫持是让本人去操作真实的画面,因此仅靠一次性令牌等 CSRF 对策无法防御。

防御:核心是「不让被嵌入」

1

设置 CSP frame-ancestors(最优先)

在响应头中加入 Content-Security-Policy: frame-ancestors 'self'(仅允许自己的站点框架化)。如果不需要让第三方嵌入,用 'none' 最安全。只有在确有需要允许的对象时才逐一列出域名。

2

同时使用 X-Frame-Options(向后兼容)

为了照顾老旧环境,也加上 X-Frame-Options: DENY(或 SAMEORIGIN)。这是兼顾新旧浏览器的多层防御。

3

对重要操作要求「再加一道」

转账、授予权限等致命操作,要插入二次认证、确认对话框、操作前的意图确认。这样透明叠加就更难突破。

4

把会话 Cookie 设为 SameSite

SameSite=Lax/Strict 抑制来自其他站点的自动发送。它对点击劫持本身并非万能,但能削弱相关的各类「源自他站的操作」。

本站的观点:一行响应头最有效。先来测自己的站点

点击劫持的对策不是花哨的代码,而是用一到两行响应头夺走其叠加基础,这是最短路径。在框架或反向代理(Caddy/nginx)上对所有页面统一加上,杜绝遗漏,才是实战做法。你的站点上 frame-ancestors 是否生效,可以用本站的工具中的安全响应头诊断来确认。「自以为已经设置好了」其实却漏掉了,才是最常见的事故。

接下来阅读

FAQ

Q点击劫持会让人遭受什么?
A

用户「自以为」按下的点击,实际落在了叠加于背后那个真实页面的按钮上。一键转账、修改设置、授予权限、在社交媒体上关注/点赞、同意按钮等「一键即可完成的重要操作」都会被滥用。它的特点不是窃取密码,而是让已登录的用户本人去执行操作。

Q最有效的防御是什么?
A

就是「不让自己的站点被嵌入到他站的框架(iframe)里」。在响应头中把 CSP 的 frame-ancestors 设为 'self'(或仅允许指定域名),并为了向后兼容同时使用 X-Frame-Options: DENY。这样就能直接夺走可供叠加的基础。

Q只靠 JavaScript 的 frame busting(跳出框架)够吗?
A

不够。老式的「如果发现自己在 iframe 内就跳出去」的 JS 有很多绕过手法,且在 JS 被禁用时无法防护。核心做法是用服务器端的响应头(frame-ancestors / X-Frame-Options),让浏览器直接拒绝被嵌入。