frame-buster代码被绕过的具体原因是什么?
在项目里用了常见的frame-busting代码,但测试时发现还是能被嵌套到iframe里。明明加了self !== top && top.location.href = self.location.href这种判断,为啥还能被绕过呢?
具体场景是用户页面被嵌入到恶意站点的iframe里,对方用了这样的结构:
<iframe src="https://my-secure-page.com" sandbox>
结果我的frame-buster代码根本没执行,这是为什么?
试过在body里加脚本:
if (top !== self) {
top.location.href = location.href;
}
但用Chrome测试时发现控制台报错:”Blocked script execution in ‘my-page.html’ because the document’s frame is sandboxed and the ‘allow-scripts’ flag is not set.”
难道沙箱模式会直接阻止frame-buster脚本运行?应该怎样既保持安全性又能有效防止点击劫持?
首先说原因。当恶意站点给iframe加上了sandbox属性,默认情况下会禁止执行JavaScript,这就是为什么你的frame-busting代码根本没运行。即使你写了类似
if (top !== self) { top.location.href = location.href; }的逻辑,但因为沙箱限制了脚本执行权限,浏览器直接拦截了这段代码的运行。控制台报错信息已经说明得很清楚了:"Blocked script execution" 是由于沙箱没有设置allow-scripts标志。这里需要注意的是,
sandbox属性设计的初衷就是为了增强安全性,防止嵌套页面执行危险操作。所以就算你加了各种JavaScript防护逻辑,只要对方不给iframe开启脚本权限,这些逻辑就完全无效。那么怎么解决这个问题呢?单纯依赖JavaScript来做frame-busting显然是不够的,我们需要用更底层、更可靠的方式来防止点击劫持。推荐的方法是使用HTTP响应头中的
X-Frame-Options或者Content-Security-Policy。先说
X-Frame-Options,它的作用很简单,就是告诉浏览器这个页面是否允许被嵌套到iframe里。你可以在服务器端配置这个响应头,比如:或者如果你希望只允许同源的页面嵌套,可以改成:
这样配置后,浏览器会直接在加载页面时检查这个响应头,如果发现不符合规则,就会拒绝渲染iframe里的内容。这个机制比JavaScript靠谱得多,因为它是由浏览器强制执行的,恶意站点没办法绕过。
不过
X-Frame-Options已经有点老了,现在更推荐用Content-Security-Policy(简称CSP)。CSP提供了更细粒度的控制,比如你可以指定只允许某些域名嵌套你的页面。示例配置如下:这行配置的意思是:只有同源的页面可以嵌套这个页面。如果你想允许特定的第三方域名,比如
example.com,可以写成:这里再强调一下,CSP的优先级高于
X-Frame-Options,所以如果你同时设置了这两个响应头,浏览器只会遵循CSP的规则。最后提一句,如果你的应用部署在多个环境(比如开发、测试、生产),记得在所有环境中都加上这些安全头。很多开发者容易忽略这一点,结果在某些环境下还是会被嵌套。
总结一下解决方案:
1. 在服务器端添加
X-Frame-Options或Content-Security-Policy响应头。2. 推荐优先使用CSP的
frame-ancestors指令。3. 确保所有环境都正确配置了这些安全头。
这样就能有效防止点击劫持问题了,也不用担心沙箱模式绕过你的JavaScript防护逻辑了。