您现在的位置是:网站首页 > 防御点击劫持的方法(如 X-Frame-Options)文章详情
防御点击劫持的方法(如 X-Frame-Options)
陈川
【
前端安全
】
50305人已围观
3998字
点击劫持是一种恶意攻击手段,攻击者通过透明或不透明的iframe覆盖在合法页面上,诱导用户点击看似无害的元素,实际触发隐藏的恶意操作。防御点击劫持的核心方法包括使用HTTP头X-Frame-Options
、Content-Security-Policy
的frame-ancestors
指令,以及结合JavaScript的防御策略。
X-Frame-Options 的工作原理
X-Frame-Options
是一个HTTP响应头,用于控制页面是否允许被嵌入到<frame>
、<iframe>
或<object>
中。它有三个可选值:
- DENY:禁止任何形式的嵌入,无论域名是否相同。
- SAMEORIGIN:仅允许同源域名下的页面嵌入。
- ALLOW-FROM uri:允许指定URI的页面嵌入(已逐渐被浏览器废弃)。
X-Frame-Options: DENY
服务器配置示例
Nginx 配置
add_header X-Frame-Options "SAMEORIGIN" always;
Apache 配置
Header always set X-Frame-Options "DENY"
Node.js (Express) 示例
app.use((req, res, next) => {
res.setHeader('X-Frame-Options', 'SAMEORIGIN');
next();
});
Content-Security-Policy 的进阶防护
X-Frame-Options
的局限性在于无法指定多个允许的源。现代浏览器更推荐使用Content-Security-Policy
(CSP)的frame-ancestors
指令:
Content-Security-Policy: frame-ancestors 'self' https://trusted.example.com;
动态策略示例
// 根据条件动态设置CSP
app.use((req, res, next) => {
const allowedDomains = [
"'self'",
"https://partner1.com",
"https://partner2.com"
];
res.setHeader("Content-Security-Policy", `frame-ancestors ${allowedDomains.join(' ')}`);
next();
});
JavaScript 防御作为补充
对于不支持HTTP头的旧浏览器,可通过JavaScript进行防御:
基础检测脚本
if (top !== self) {
top.location = self.location;
}
增强版(处理沙盒iframe)
try {
if (top.location.hostname !== window.location.hostname) {
top.location.href = window.location.href;
}
} catch (e) {
document.body.innerHTML = '<h1>此页面禁止被嵌入</h1>';
}
特殊场景处理
允许特定路径的嵌入
location /public-widget/ {
add_header X-Frame-Options "ALLOW-FROM https://embedder.com";
}
与CSP共存时的优先级
当同时存在X-Frame-Options
和frame-ancestors
时,现代浏览器优先采用CSP策略。建议两者同时配置以实现最大兼容性。
测试验证方法
-
手动测试:
<!-- 攻击者测试页面 --> <iframe src="https://your-site.com/sensitive-page" style="opacity:0.5;"></iframe>
-
自动化工具:
curl -I https://your-site.com | grep -i "x-frame-options"
-
浏览器开发者工具: 在Network选项卡中检查响应头是否包含防护头。
常见问题与解决方案
1. 误拦截合法iframe
# 错误配置:过度严格
X-Frame-Options: DENY
# 修正方案:精确控制
Content-Security-Policy: frame-ancestors 'self' https://legitimate-embedder.com
2. 多级iframe的权限传递
父页面需显式允许:
<iframe src="child.html" allow="fullscreen"></iframe>
3. 历史浏览器兼容性
对于IE8等老旧浏览器,需保留JavaScript检测:
// 特征检测
if (!window.postMessage || !window.Proxy) {
// 回退到传统检测方式
}
与其他安全机制的协同
1. 配合CORS使用
Access-Control-Allow-Origin: https://trusted-domain.com
Content-Security-Policy: frame-ancestors https://trusted-domain.com
2. 结合沙盒属性
<iframe sandbox="allow-scripts allow-forms" src="..."></iframe>
实际攻击案例分析
案例1:社交媒体点赞劫持
攻击者构造透明iframe覆盖在"免费抽奖"按钮上,实际点击的是隐藏的"点赞"按钮。有效防御方案:
X-Frame-Options: DENY
Content-Security-Policy: frame-ancestors 'none'
案例2:银行交易页面劫持
恶意网站嵌入银行页面并诱导用户输入密码。解决方案:
// 关键操作前验证上下文
function validateContext() {
if (window.self !== window.top || document.referrer.indexOf('bank.com') === -1) {
abortTransaction();
}
}
性能与安全权衡
1. 全局严格模式
# 全站禁止嵌入(适用于后台管理系统)
add_header X-Frame-Options "DENY" always;
2. 按路径差异化配置
location / {
add_header X-Frame-Options "SAMEORIGIN";
}
location /public/ {
add_header Content-Security-Policy "frame-ancestors *";
}
浏览器支持现状
浏览器 | X-Frame-Options | CSP frame-ancestors |
---|---|---|
Chrome | 4+ | 40+ |
Firefox | 3.6+ | 36+ |
Safari | 4+ | 10+ |
Edge | 12+ | 15+ |
开发环境特殊处理
本地开发时可能需要临时禁用防护:
// 开发环境配置示例
if (process.env.NODE_ENV === 'development') {
app.use((req, res, next) => {
res.removeHeader('X-Frame-Options');
next();
});
}
上一篇: 点击劫持的危害
下一篇: 使用 CSP 防止点击劫持