Sandbox属性能防点击劫持吗?为什么加了还是被嵌入iframe?
我最近在做安全加固,听说用 iframe 的 sandbox 属性可以防止点击劫持,就在我们 React 项目的主页面加了 allow-same-origin 和 allow-scripts,但测试时发现别的网站还是能用 iframe 嵌入我们的页面,这不就还是有点击劫持风险吗?
我试过只加 sandbox 不带任何 allow,但页面直接白屏跑不起来。现在很困惑,到底该怎么正确配置才能既保证功能又防嵌入?
function App() {
return (
<iframe
src="https://myapp.com/dashboard"
sandbox="allow-same-origin allow-scripts"
title="secure-frame"
/>
);
}
你现在加的 sandbox 是在说"我这个 iframe 里的页面要受限",但问题是别人嵌入你的时候,人家压根不会给你加这些限制,人家直接
<iframe src="你的网站">就完事了。要防点击劫持,正确姿势是在响应头里配置,让服务端告诉浏览器"我不允许被嵌入"。
两个方案,二选一或者一起上都行:
方案一,X-Frame-Options,简单粗暴:
方案二,CSP 的 frame-ancestors,更灵活,性能上也更现代:
如果你用的是 Nginx,直接加到配置里:
如果你是 Express 后端,用 helmet 中间件一把梭:
顺便说一句,CSP 的 frame-ancestors 会覆盖 X-Frame-Options,现代浏览器优先看 CSP,但为了兼容老浏览器,两个都加也不费事。
你 React 代码里那个 sandbox 可以删了,跟防点击劫持半毛钱关系没有。
你现在代码里是在自己的页面里放了一个 iframe,给这个 iframe 加 sandbox,这当然防不了别人嵌入你的页面。sandbox 是"我嵌别人时,限制别人的权限",不是"防止别人嵌我"。
要防点击劫持,正确做法是在响应头里设置。
最简单高效的是 X-Frame-Options,设成 DENY 直接禁止所有 iframe 嵌入,或者 SAMEORIGIN 只允许同源嵌入。Nginx 配置一行就搞定:
更灵活的方案是用 CSP 的 frame-ancestors,能精确控制哪些域名可以嵌你:
如果你只有前端权限改不了服务器配置,可以用 JS 做兜底检测,虽然效率不如响应头高,但能用:
这个方案会强制跳转到你自己的页面,但有个问题,如果对方用了 sandbox 且没加 allow-top-navigation,跳转会失败。所以还是响应头方案最靠谱,一劳永逸,性能也最好,浏览器在收到响应时直接拦截,连页面渲染都省了。
总结一下,sandbox 是用来限制你嵌的别人的,要防止被嵌得用 X-Frame-Options 或 CSP。