点击劫持防护加了X-Frame-Options为啥还是被UI覆盖?

Good“珂簪 阅读 13

我在项目里加了 X-Frame-Options: DENY 响应头,但测试时发现攻击者还是能用透明iframe覆盖我的按钮,这是不是说明这个头没生效?

后端确认响应头已经正确返回了,浏览器也显示收到了,但 UI 覆盖攻击依然能触发点击。是不是还得配合其他防护手段?比如 CSP 的 frame-ancestors?

<iframe src="https://my-site.com" style="opacity:0; position:absolute; top:0; left:0"></iframe>
<button style="position:absolute; top:10px; left:20px">假按钮</button>
我来解答 赞 2 收藏
二维码
手机扫码查看
1 条解答
上官亚楠
X-Frame-Options: DENY确实可以防止你的页面被嵌入到其他站点的iframe中,但你遇到的问题是不同类型的点击劫持攻击。这种透明覆盖的方式不依赖于iframe嵌套,而是通过样式覆盖来触发。

要解决这个问题,你需要配合使用CSP(内容安全策略)中的frame-ancestors指令,同时考虑其他防护手段。我来详细说说具体怎么做:

首先在服务器配置里添加CSP响应头,这里以Nginx为例:
add_header Content-Security-Policy "frame-ancestors 'self';";

这段代码的意思是只允许当前域名加载自己,阻止其他域名嵌套显示。

然后针对UI覆盖问题,建议你在前端做些额外防护。可以在重要操作按钮上加个简单的防抖动验证,比如:
let clickFlag = false;
document.getElementById('importantButton').onclick = function() {
if(clickFlag) return; // 如果短时间内重复点击就直接返回
clickFlag = true;
setTimeout(() => clickFlag = false, 1000); // 1秒后重置标志位
// 执行正常业务逻辑
}

原理是这样:如果用户正常点击,这个flag会在1秒后重置。但如果是因为覆盖导致的多次触发,就能有效阻止连续恶意点击。

另外,建议定期检查页面DOM结构是否异常,特别是公共区域是否存在不明来源的元素覆盖。可以用MutationObserver监控DOM变化:
const observer = new MutationObserver((mutationsList) => {
for(let mutation of mutationsList) {
if(mutation.type === 'childList') {
console.log('DOM结构发生变化');
// 可以在这里加入检测和处理逻辑
}
}
});
observer.observe(document.body, { childList: true, subtree: true });

这几个方法结合起来基本能解决常见的点击劫持问题。虽然有点麻烦,但安全问题确实需要多管齐下。
点赞
2026-03-28 06:03