1. 什么是framebuster破坏
framebuster破坏是一种前端安全防御技术,主要用于防止网页被恶意嵌套在iframe框架中。当我们的网页被其他网站通过iframe嵌套时,可能会面临点击劫持(Clickjacking)、界面伪装(UI Redressing)等安全威胁。
我在实际项目中遇到过这样的情况:一个电商网站的支付页面被钓鱼网站嵌套,用户在不知情的情况下完成了支付操作。这种攻击之所以能成功,就是因为原网站没有采取有效的framebuster防御措施。
2. framebuster的核心防御原理
2.1 基础防御机制
最基础的framebuster实现方式是通过JavaScript检测当前页面是否被嵌套在iframe中:
javascript复制if (window.top !== window.self) {
window.top.location = window.self.location;
}
这段代码的原理很简单:比较顶层窗口(top)和当前窗口(self)的location对象。如果不一致,说明当前页面被嵌套了,于是强制将顶层窗口重定向到当前页面的URL。
2.2 防御机制的演进
随着攻击手段的升级,简单的framebuster也面临着被绕过的风险。现代防御方案通常采用以下增强措施:
- 多重检测机制:不仅检查window.top,还检查window.parent
- 沙箱属性检测:检查iframe的sandbox属性设置
- X-Frame-Options头:服务器端设置HTTP响应头
- CSP frame-ancestors指令:内容安全策略的更细粒度控制
3. 实际应用中的实现方案
3.1 纯前端实现
完整的前端framebuster实现应该包含以下要素:
javascript复制(function() {
// 检测是否被嵌套
if (window !== window.top || window !== window.parent) {
try {
// 尝试跳出框架
window.top.location = window.location;
} catch (e) {
// 如果被阻止,创建全屏覆盖层提示用户
document.body.innerHTML = '';
var blocker = document.createElement('div');
blocker.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;background:white;z-index:999999;';
blocker.innerHTML = '<h1>安全提示</h1><p>此页面不应在框架中加载,请<a href="' + window.location.href + '" target="_blank">点击此处</a>在新窗口打开。</p>';
document.body.appendChild(blocker);
}
}
})();
3.2 服务器端配合方案
更完善的防御需要前后端配合:
-
X-Frame-Options响应头:
http复制X-Frame-Options: SAMEORIGIN可选值包括DENY(完全禁止)、SAMEORIGIN(只允许同源嵌套)、ALLOW-FROM uri(指定允许的源)
-
Content-Security-Policy:
http复制Content-Security-Policy: frame-ancestors 'self' example.com可以更灵活地控制允许嵌套的源
4. 常见问题与解决方案
4.1 framebuster被绕过的情况
在实际应用中,我发现framebuster可能被以下方式绕过:
- 沙箱iframe:攻击者使用sandbox属性限制JavaScript执行
html复制<iframe sandbox="allow-forms allow-scripts" src="victim.com"></iframe>
解决方案:检测sandbox属性并提示用户
javascript复制if (window.self !== window.top && 'sandbox' in document.createElement('iframe')) {
// 沙箱环境处理逻辑
}
4.2 浏览器兼容性问题
不同浏览器对framebuster的支持程度不同:
| 浏览器 | X-Frame-Options支持 | CSP支持 | JS framebuster有效性 |
|---|---|---|---|
| Chrome | 完全支持 | 完全支持 | 高 |
| Firefox | 完全支持 | 完全支持 | 高 |
| Safari | 完全支持 | 部分支持 | 中等 |
| IE 8-10 | 部分支持 | 不支持 | 低 |
应对策略:采用分层防御,同时使用多种技术手段。
5. 高级防御技巧
5.1 动态内容保护
对于需要允许特定第三方嵌入的内容,可以采用动态token验证:
javascript复制// 生成一次性token
const embedToken = generateToken();
// 在允许的iframe中通过postMessage传递token
window.addEventListener('message', (event) => {
if (event.data.token === embedToken) {
// 验证通过,允许特定功能
}
});
5.2 视觉欺骗防御
针对通过CSS进行的界面伪装攻击,可以添加以下防御:
css复制body {
/* 防止通过透明度隐藏页面 */
opacity: 1 !important;
/* 防止通过z-index将页面置于底层 */
z-index: 2147483647 !important;
/* 防止通过position固定页面位置 */
position: relative !important;
}
6. 实际项目中的经验总结
在多个金融级Web应用中实施framebuster防御时,我总结了以下经验:
- 防御层级:至少要实施3层防御 - HTTP头、JavaScript检测、视觉保护
- 性能考量:framebuster脚本应该尽早执行,放在顶部
- 用户提示:当检测到框架嵌套时,要给用户明确的指引
- 日志记录:记录框架嵌套尝试,用于安全分析
- 测试覆盖:需要测试各种嵌套场景,包括同源、跨源、沙箱等
一个完整的防御方案应该像这样部署:
javascript复制// 1. 尽早执行框架检测
(function() {
// 检测框架嵌套
const isFramed = window.self !== window.top;
// 检测沙箱属性
const isSandboxed = 'sandbox' in document.createElement('iframe') &&
document.createElement('iframe').sandbox.supports('allow-scripts');
// 处理框架嵌套情况
if (isFramed || isSandboxed) {
try {
// 尝试跳出框架
if (window.top.location.hostname !== window.self.location.hostname) {
window.top.location = window.self.location;
}
} catch (e) {
// 创建安全警告界面
createSecurityWarning();
// 上报安全事件
reportSecurityIncident();
}
}
function createSecurityWarning() {
// 创建全屏警告界面
}
function reportSecurityIncident() {
// 发送安全事件到后端
}
})();
7. 现代Web安全的最佳实践
随着Web技术的发展,framebuster也需要与时俱进:
- 优先使用CSP:Content-Security-Policy的frame-ancestors指令是最可靠的防御方式
- 结合其他安全头:
http复制Content-Security-Policy: frame-ancestors 'none'; X-Frame-Options: DENY - 考虑使用Feature Policy:
http复制Feature-Policy: fullscreen 'none' - 定期安全审计:检查framebuster实现是否被绕过
在最近的一个政府项目中,我们采用了以下完整的安全头配置:
http复制Content-Security-Policy: default-src 'self'; frame-ancestors 'none'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Feature-Policy: fullscreen 'none'; geolocation 'none'
这种配置不仅防止了框架嵌套,还提供了全面的内容安全保护。