logo
web
  • Home
  • Pricing
logo
web
Copyright © 2025 web. Ltd.
Links
SubscribeManage Subscription
Powered by Postion - Create. Publish. Own it.
Privacy policy•Terms

Postion

一文读懂点击劫持(Clickjacking)的危害与修复方案

一文读懂点击劫持(Clickjacking)的危害与修复方案

在网络世界中,一个看不见的威胁可能正潜伏在看似无害的按钮或链接之下。用户的一次无心点击,可能导致账户被盗、信息泄露,甚至造成财产损失。这个“隐形杀手”就是——点击劫持(Clickjacking)。
b
by buoooou
•Jul 18, 2025

在网络世界中,一个看不见的威胁可能正潜伏在看似无害的按钮或链接之下。用户的一次无心点击,可能导致账户被盗、信息泄露,甚至造成财产损失。这个“隐形杀手”就是——点击劫持(Clickjacking)。

本文将带你深入了解这个常见的 Web 漏洞,告诉你它是什么,有多危险,以及如何用简单有效的方法彻底防御它。

一、什么是点击劫持?

点击劫持,又称“用户界面补救攻击”(UI Redress Attack),是一种欺骗性的网络攻击技术。攻击者通过巧妙的手段,将一个透明的、看不见的恶意页面覆盖在一个用户想要点击的正常页面之上。

简单来说,想象一下这个场景:

  1. 攻击者创建一个诱人的网页,比如一个“免费领取礼品”的抽奖页面。

  2. 然后,他使用一个完全透明的 <iframe>(内联框架)将你的网站页面(例如,设置页面中的“删除账户”按钮)加载进来,并精确地覆盖在“点击抽奖”按钮的正上方。

  3. 当用户访问这个攻击页面,满心欢喜地去点击“抽奖”时,他们的鼠标实际上点击的是那个看不见的、来自你网站的“删除账户”按钮。

最终,用户在毫不知情的情况下,完成了他们从未打算进行的操作。他们的点击行为被成功“劫持”了。

二、点击劫持的危害有多大?

千万不要小看点击劫持,它可能造成的危害远超想象:

  • 执行非预期操作:诱骗用户在社交媒体上点赞、关注或发布他们不想分享的内容。

  • 账户信息篡改:欺骗用户修改密码、更改邮箱地址,甚至删除自己的账户。

  • 金融资产损失:在网银或电商网站上,诱导用户进行非自愿的转账或购物。

  • 敏感信息泄露:通过精心设计的界面,欺骗用户拖拽或输入敏感信息到攻击者控制的不可见表单中。

  • 凭证窃取:结合其他技术,诱使用户在伪装的登录框中输入用户名和密码。

  • 品牌信誉受损:一旦用户因你的网站安全防护不足而遭受损失,他们对你品牌的信任将荡然无存。

三、如何修复点击劫持漏洞?

修复点击劫持的核心思想非常直接:明确地告诉浏览器,不允许我的网站被不明来源的 <iframe>、<frame> 或 <object> 嵌套。

这需要通过配置服务器的 HTTP 响应头 来实现。以下是两种主流且有效的防御方法,建议同时使用以获得最佳兼容性。

方法一:使用 X-Frame-Options (XFO)

这是一个较早的、专门用于防御点击劫持的响应头,兼容性极好。

它有三个可选值:

  • DENY:最严格,推荐使用。完全禁止任何页面通过框架嵌套你的网站。

  • SAMEORIGIN:只允许来自同源(相同域名、协议和端口)的页面嵌套。

  • ALLOW-FROM uri:(已过时,不推荐) 仅允许在指定的 URI 中嵌套。

在 Nginx 中配置:

Generated nginx

# 在你的 server 或 http 配置块中添加
add_header X-Frame-Options "DENY";

在 Next.js 中配置 (next.config.js):

Generated javascript

module.exports = {
  async headers() {
    return [
      {
        source: '/:path*',
        headers: [
          {
            key: 'X-Frame-Options',
            value: 'DENY',
          },
        ],
      },
    ];
  },
};

方法二:使用 Content-Security-Policy (CSP) 的 frame-ancestors 指令

这是更现代、更强大、更灵活的解决方案,也是 W3C 推荐的最佳实践。它不仅能防御点击劫持,还是一个全面的内容安全策略。

frame-ancestors 指令用于控制哪些来源可以嵌入你的页面:

  • 'none':效果等同于 X-Frame-Options: DENY。最安全,推荐使用。

  • 'self':效果等同于 X-Frame-Options: SAMEORIGIN。

  • https://trusted-site.com:可以指定一个或多个你信任的网站来嵌入你的页面。

在 Nginx 中配置:

Generated nginx

# 推荐同时配置 XFO 以兼容旧浏览器
add_header X-Frame-Options "DENY";
add_header Content-Security-Policy "frame-ancestors 'none';";

在 Next.js 中配置 (next.config.js):

Generated javascript

module.exports = {
  async headers() {
    return [
      {
        source: '/:path*',
        headers: [
          {
            key: 'X-Frame-Options',
            value: 'DENY',
          },
          {
            key: 'Content-Security-Policy',
            value: "frame-ancestors 'none'",
          },
        ],
      },
    ];
  },
};

四、如何验证修复是否成功?

验证是确保安全措施有效落地的最后一步,也是最重要的一步。

1. 手动创建概念验证(PoC)页面

这是最直观的验证方法。

  • 创建一个 HTML 文件,例如 test-clickjacking.html,内容如下:

    Generated html

    <!DOCTYPE html>
    <html>
    <head>
        <title>Clickjacking Test</title>
    </head>
    <body>
        <h1>Clickjacking Test Page</h1>
        <p>如果下面的 iframe 成功加载了你的网站,说明漏洞依然存在。</p>
        <iframe src="https://你的网站地址.com" style="width: 800px; height: 600px;"></iframe>
    </body>
    </html>
  • 验证结果:

    • 修复前:<iframe> 中会成功显示你的网站页面。

    • 修复后:<iframe> 会显示空白,或浏览器提示“连接被拒绝”。同时,打开浏览器开发者工具(F12),在“控制台”(Console)中会看到类似 Refused to frame '...' because an ancestor violates the following Content-Security-Policy directive: "frame-ancestors 'none'" 的错误信息。

2. 检查 HTTP 响应头

  • 访问你的网站,打开开发者工具(F12),切换到“网络”(Network)选项卡。

  • 刷新页面,找到对主文档的请求。

  • 点击该请求,在右侧查看“响应头”(Response Headers),确保你设置的 X-Frame-Options 和 Content-Security-Policy 已经存在并且值是正确的。

3. 使用在线工具

你还可以使用 Security Headers 这类免费的在线工具,输入你的网站 URL,它会自动检测你网站的 HTTP 安全头部配置情况,并给出评分和改进建议。

结语

点击劫持是一个隐蔽而危险的漏洞,但幸运的是,它的防御方法非常成熟和简单。通过正确配置 X-Frame-Options 和 Content-Security-Policy 响应头,你可以轻松地为你的用户和网站加上一把坚固的安全锁。立即行动,检查你的网站配置,别让你的用户成为下一个“被劫持”的受害者。

Comments (0)

Continue Reading

How to Change the Global Background Color in Your Next.js + Tailwind CSS App

When building a modern web application with Next.js and Tailwind CSS, you'll often want to set a custom global background color that aligns with your brand identity. A common mistake is to hardcode the color directly onto the <body> tag, which can break theming capabilities like dark mode.

Published Jul 20, 2025

深入解析 DNS CAA 记录

Published Jul 18, 2025

从“P2024”到稳定运行:我如何解决 Next.js + Prisma + PgBouncer 在生产环境的连接池噩梦

如果你正在使用 Next.js(或任何 Serverless 架构)、Prisma 和 PostgreSQL 构建应用,你很可能在某个深夜,满怀期待地将应用部署到 Vercel 后,看到过这个让你心跳停止的错误: Error: Timed out fetching a new connection from the connection pool. (P2024) 这个错误就像一个幽灵,它在本地开发环境(npm run dev)中从不出现,却在生产环境的流量高峰期(有时甚至只是几个并发用户)将你的应用炸得粉碎。

Published Jul 27, 2025