共计 2124 个字符,预计需要花费 6 分钟才能阅读完成。
攻击原理:透明 iframe 的致命组合拳
当 CSRF Token 遇上 Clickjacking,就像防盗门遇到了隐身术。攻击者会构造一个精心设计的透明 iframe 层:

<!-- 恶意网站代码 -->
<style>
iframe {
opacity: 0.01;
position: absolute;
width: 100%;
height: 100%;
z-index: 999;
}
button {
/* 诱骗按钮与目标按钮重合 */
position: absolute;
left: 100px;
top: 200px;
}
</style>
<button> 点击抽奖 </button>
<iframe src="https://victim.com/transfer?amount=5000"></iframe>
- 攻击流程 :
- 用户登录正常网站,获取有效 CSRF Token
- 访问恶意页面时,透明 iframe 加载真实网站表单
- 用户点击伪装的抽奖按钮,实际触发 iframe 内的转账操作
-
由于请求携带合法 Token,服务器认为是合法操作
-
为何 Token 防护失效 :
- Token 验证机制依然正常工作
- 但用户是在不知情的情况下「自愿」触发了操作
- 这相当于攻击者「借刀杀人」
防御方案三国杀
| 方案 | 优点 | 缺点 | 移动端兼容性 |
|---|---|---|---|
| X-Frame-Options | 简单粗暴,IE8+ 支持 | 不能细粒度控制 | iOS 全支持 /Android4.4+ |
| CSP frame-ancestors | 支持白名单,现代标准 | 旧浏览器需降级处理 | iOS13+/Android4.4+ |
| JavaScript 断帧脚本 | 无兼容性问题 | 可被 CSS 或 XSS 绕过 | 全支持但不可靠 |
双端防御代码实战
Node.js Express 版
const helmet = require('helmet');
app.use(helmet.frameguard({ action: 'deny'})); // X-Frame-Options
app.use(helmet.contentSecurityPolicy({
directives: {frameAncestors: ["'none'"], // CSP 第 2 层防护
defaultSrc: ["'self'"] // 顺带加强其他 CSP 规则
}
}));
// 自定义中间件处理旧浏览器
app.use((req, res, next) => {
// 针对不支持 CSP 的 UA 降级处理
const isLegacyBrowser = /MSIE|Trident/.test(req.headers['user-agent']);
if (isLegacyBrowser) {res.setHeader('X-Frame-Options', 'DENY');
}
next();});
Spring Boot 版
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers()
.frameOptions().deny() // 1. 先设置 X -Frame-Options
.and()
.contentSecurityPolicy("frame-ancestors'none';"); // 2. CSP 补刀
// 针对 API 特殊处理
http.antMatcher("/api/**")
.headers().addHeaderWriter(new StaticHeadersWriter("X-Content-Type-Options", "nosniff")
);
}
}
渗透测试四步曲
- Burp Suite 检测 :
- 使用 Proxy 拦截响应
- 修改 Response 移除防护头
-
通过 Repeater 测试不同 header 组合
-
Selenium 自动化测试 :
from selenium import webdriver def test_clickjacking(url): driver = webdriver.Chrome() driver.get(f""" <html><body> <iframe src="{url}" style="opacity:0.1;"></iframe> </body></html>""") try: driver.switch_to.frame(0) print("漏洞存在!") except: print("防护生效") driver.quit()
生产环境三大坑
-
HTTPS≠安全 :
SSL 只是传输加密,与 Clickjacking 防护完全无关 -
SPA 的 CSP 陷阱 :
Vue/React 等需要配置特殊 CSP 规则:script-src 'self' 'unsafe-inline'; connect-src 'self' api.example.com; -
移动端幽灵点击 :
部分移动浏览器会预加载 iframe 内容,即使未显示也需要防护
思考题
如果攻击者发现你的网站同时使用了:
1. X-Frame-Options: DENY
2. CSP: frame-ancestors ‘none’
3. 传统的 framebusting 脚本
你认为还有可能通过哪些意想不到的方式突破防御?试试在本地环境构造 PoC 验证你的猜想。
正文完
发表至: 网络安全
五天前
