网络安全防护:点击劫持
目录
1、概念
2、攻击原理:视觉欺骗与层叠控制
3、点击劫持的危害
4、防御点击劫持
4.1 X-Frame-Options HTTP 响应头 (最直接有效)
4.2 Content-Security-Policy (CSP) HTTP 响应头 (现代、更强大)
4.3 客户端 JavaScript 防御 (Frame Busting)
1、概念
点击劫持(Clickjacking),也被称为“UI 覆盖攻击”或“UI 伪装攻击”,是一种恶意技术,攻击者通过欺骗用户在不知情的情况下点击看似无害的网页元素(如按钮、链接),但实际上点击的是攻击者精心隐藏的、位于诱饵页面透明层下方的另一个页面的敏感元素(如转账按钮、权限授权按钮、删除按钮等)。
跨域限制的绕过: 同源策略限制了 JavaScript 跨域读取 iframe 内容,但无法阻止 iframe 的嵌入和接收用户输入事件(如点击)。这是点击劫持能发生的根本技术基础。
2、攻击原理:视觉欺骗与层叠控制
攻击的关键在于利用 HTML 的 iframe
元素和 CSS 的层叠(z-index)、透明度(opacity)和定位(positioning)属性:
-
创建透明框架: 攻击者将目标网站(例如用户的银行页面、社交媒体设置页面、管理员后台等)嵌入到一个透明的
iframe
中。 -
设计诱饵页面: 攻击者精心设计一个看起来无害、有吸引力的页面(例如一个有趣的游戏、一个免费赠品的领取页面、一个引人注目的视频缩略图等)。这个页面就是用户实际看到并与之交互的页面。
-
覆盖与定位: 攻击者使用 CSS 将透明的目标网站
iframe
精确地覆盖在诱饵页面的特定可点击元素(如“开始游戏”、“领取奖品”、“播放视频”按钮)之上。通常,诱饵按钮会被做得很大或很诱人,而透明的iframe
中的敏感按钮(如“确认转账”、“授权访问”、“删除账户”)则被定位到恰好位于诱饵按钮的下方。 -
用户交互: 用户被诱骗访问这个恶意页面。用户看到的是诱饵页面上的按钮(例如“点击赢大奖”),并毫无戒心地点击它。
-
恶意操作执行: 由于透明的
iframe
覆盖在诱饵按钮之上,用户的点击实际上落在了iframe
内目标网站的那个敏感按钮上。如果用户已经在目标网站登录(例如浏览器保存了登录状态),那么这个操作(如转账、授权、删除)就会以用户的身份成功执行,而用户对此毫不知情,以为自己只是在玩一个游戏或领取奖品。
3、点击劫持的危害
-
未经授权的资金转移: 劫持银行网站的转账操作。
-
账户接管: 劫持更改密码、邮箱或安全设置的按钮。
-
隐私泄露: 劫持“授权应用访问”按钮,将账户权限授予恶意应用。
-
社交媒体滥用: 劫持“点赞”、“关注”、“分享”甚至“发布”按钮,在用户不知情下发布垃圾信息或不当内容。
-
数据删除: 劫持“删除邮件”、“删除文件”、“删除账户”按钮。
-
传播恶意软件: 劫持“下载”或“安装”按钮。
-
窃取敏感信息: 通过拖拽劫持等方式。
4、防御点击劫持
防御主要依靠网站所有者在服务器端设置 HTTP 响应头,告诉浏览器该页面是否允许被嵌入到 iframe 中,以及谁可以嵌入:
4.1 X-Frame-Options
HTTP 响应头 (最直接有效)
-
DENY
: 页面绝对不允许被嵌入到任何 iframe 中。 -
SAMEORIGIN
: 页面只允许被同源网站(相同协议、域名、端口)的页面嵌入。
4.2 Content-Security-Policy
(CSP) HTTP 响应头 (现代、更强大)
-
使用
frame-ancestors
指令来指定哪些页面可以嵌入该页面。 -
例如:
-
Content-Security-Policy: frame-ancestors 'none';
(等同于X-Frame-Options: DENY
) -
Content-Security-Policy: frame-ancestors 'self';
(等同于X-Frame-Options: SAMEORIGIN
) -
Content-Security-Policy: frame-ancestors https://trusted.example.com;
(只允许特定可信域名嵌入)
-
-
CSP 提供了比
X-Frame-Options
更细粒度的控制。
4.3 客户端 JavaScript 防御 (Frame Busting)
-
在页面中加入脚本,检测自己是否被嵌套在 iframe 中,如果是,则尝试跳出框架(如
if (top != self) top.location = self.location;
)。 -
局限性: 现代浏览器有多种方式可以被攻击者利用来绕过 Frame Busting 脚本(如使用
sandbox
属性限制脚本执行、使用XSS
先破坏页面本身等)。因此,这只能作为辅助手段,不能替代服务端设置 HTTP 头。