什么是点击劫持 (Clickjacking)?如何防御?
点击劫持 (Clickjacking),又称为界面伪装攻击 (UI Redressing),是一种视觉欺骗手段。
简单来说,攻击者使用一个透明的、不可见的 <iframe>(内嵌框架),覆盖在一个诱导性的网页按钮或链接之上。用户以为自己点击的是网页上可见的“播放视频”或“领取奖品”按钮,但实际上点击的是上方透明层里那个被嵌入的(受害者已登录的)目标网站的敏感按钮(如“转账”、“关注”、“删除账号”等)。
点击劫持是如何工作的?
想象一下这就像是一个三明治:
- 底层(诱饵层): 攻击者搭建的恶意网页,上面有一个很吸引人的按钮(例如:“点击赢取 iPhone”)。
- 顶层(目标层): 攻击者通过
<iframe>标签嵌入了目标网站(例如:你的网银页面或社交媒体页面)。 - 伪装: 攻击者通过 CSS 将顶层的
<iframe>设置为全透明 (opacity: 0),并将其中的敏感按钮(如“确认转账”)精确地定位在底层诱饵按钮的正上方。
结果: 用户在毫不知情的情况下,以为自己在点诱饵,实际上是在操作目标网站。
如何防御点击劫持?
防御点击劫持的核心思路是:不允许第三方网站通过 <iframe> 嵌入你的网页,或者严格限制哪些网站可以嵌入。
目前主要有以下几种防御方案,通常建议组合使用:
1. 使用 CSP: frame-ancestors (推荐,最现代的方案)
内容安全策略 (Content Security Policy, CSP) 是防御此类攻击最有效、最标准的方法。通过设置 HTTP 响应头中的 frame-ancestors 指令,可以控制哪些父页面可以嵌入当前页面。
- 完全禁止嵌入:plaintext
Content-Security-Policy: frame-ancestors 'none'; - 只允许同源域名嵌入(即自己嵌入自己):plaintext
Content-Security-Policy: frame-ancestors 'self'; - 允许特定的信任域名嵌入:plaintext
Content-Security-Policy: frame-ancestors https://partner-site.com;
2. 使用 X-Frame-Options 响应头 (经典方案)
这是一个较老的 HTTP 响应头,虽然功能不如 CSP 强大,但浏览器兼容性极好。它主要有三个值:
DENY:无论任何情况,该页面都不允许被嵌入 iframe 中(最安全)。SAMEORIGIN:该页面仅允许被相同域名的页面嵌入。ALLOW-FROM uri:(已废弃,不建议使用) 仅允许指定 URI 嵌入。
最佳实践: 在服务器配置中同时设置 CSP 和 X-Frame-Options,以确保新老浏览器都能受到保护。
3. 设置 Cookie 的 SameSite 属性
虽然这不是专门针对点击劫持的防御,但它能起到很好的辅助作用。
将 Session Cookie 的属性设置为 SameSite=Strict 或 SameSite=Lax。
- 这意味着,如果你的网页被嵌入在第三方恶意网站的 iframe 中,浏览器在发送请求时不会携带用户的登录 Cookie。
- 因此,即使用户点击了那个透明按钮,由于没有 Cookie,服务器会认为用户未登录,操作也就无法执行。
4. JavaScript 防御 (Frame Busting) - (不推荐作为唯一手段)
在旧时代,开发者会在网页中加入一段 JS 代码,检测当前页面是否被嵌入在 iframe 中,如果是,则强制跳出。
if (top.location != self.location) {
top.location = self.location;
}
缺点: 这种方法很容易被攻击者绕过(例如使用 iframe 的 sandbox 属性禁用脚本),因此只能作为一种极其有限的补充手段,不能依赖它。
总结
要彻底防御点击劫持,请在你的 Web 服务器(Nginx, Apache, IIS 等)或应用代码中配置 HTTP 响应头:
- 首选:
Content-Security-Policy: frame-ancestors 'self'; - 兼容:
X-Frame-Options: SAMEORIGIN - 辅助: 确保 Cookie 设置了
SameSite=Lax或Strict。