欢迎光临
我们一直在努力

02-CSRF与Clickjacking:前端交互的隐形威胁

CSRF与Clickjacking:前端交互的隐形威胁

大家好,我是十六咲子。

上一篇文章我们探讨了XSS攻击的原理与防护,今天我们来聊聊前端交互中另外两个常见的安全威胁:CSRF(跨站请求伪造)和Clickjacking(点击劫持)。这两种攻击虽然不如XSS那么为人熟知,但同样能造成严重的安全问题,甚至导致用户资产损失。

什么是CSRF攻击?

CSRF(Cross-Site Request Forgery,跨站请求伪造)是指攻击者诱导用户访问恶意网站,该网站会发送一个请求到目标网站(如银行、电商),利用用户在目标网站的登录状态,执行未授权的操作。

CSRF攻击的攻击流程

  • 用户登录目标网站:如https://bank.com,获取登录凭证(cookie)
  • 攻击者构造恶意网站:如https://attacker.com,包含指向目标网站的恶意请求
  • 用户访问恶意网站:由于浏览器会自动携带cookie,恶意请求会被目标网站识别为用户的合法请求
  • 目标网站执行恶意操作:如转账、修改密码等
  • 真实案例

    某银行网站的转账接口为https://bank.com/transfer?to=123456&amount=1000,攻击者构造恶意页面:

    <!– 恶意网站页面 –>
    <img src="https://bank.com/transfer?to=999999&amount=10000" style="display:none" />

    当用户登录银行网站后访问该恶意页面,浏览器会自动发送转账请求,导致用户资金被转走。

    实战:CSRF攻击演示

    场景:修改用户密码

    假设有一个社交网站,修改密码的接口为POST /api/change-password,请求体为{"newPassword": "123456"}。

    攻击步骤
  • 攻击者构造恶意表单:
  • <!– 恶意网站的CSRF表单 –>
    <form action="https://social.com/api/change-password" method="POST" id="csrfForm">
    <input type="hidden" name="newPassword" value="hacker123" />
    </form>
    <script>
    // 自动提交表单
    document.getElementById('csrfForm').submit();
    </script>

  • 诱导用户访问:通过邮件、聊天工具等发送恶意链接
  • 攻击成功:用户密码被修改为hacker123
  • CSRF防护策略

    1. 同步令牌模式(CSRF Token)

    核心原理:服务器为每个会话生成一个唯一的token,嵌入到表单或页面中,提交请求时验证token的有效性。

    实现步骤:

  • 服务器生成token:
  • // Node.js + Express示例
    app.use(session({ secret: 'keyboard cat', resave: false, saveUninitialized: true }));

    app.get('/profile', (req, res) => {
    // 生成CSRF token
    const csrfToken = crypto.randomBytes(32).toString('hex');
    req.session.csrfToken = csrfToken;
    res.render('profile', { csrfToken });
    });

  • 前端使用token:
  • <!– 表单中嵌入token –>
    <form action="/api/change-password" method="POST">
    <input type="hidden" name="csrfToken" value="<%= csrfToken %>" />
    <input type="password" name="newPassword" placeholder="新密码" />
    <button type="submit">修改密码</button>
    </form>

    <!– AJAX请求携带token –>
    <script>
    fetch('/api/change-password', {
    method: 'POST',
    headers: {
    'Content-Type': 'application/json',
    'X-CSRF-Token': '<%= csrfToken %>' // 或从meta标签获取
    },
    body: JSON.stringify({ newPassword: '123456' })
    });
    </script>

  • 服务器验证token:
  • app.post('/api/change-password', (req, res) => {
    const { csrfToken, newPassword } = req.body;

    // 验证token
    if (!csrfToken || csrfToken !== req.session.csrfToken) {
    return res.status(403).json({ error: 'CSRF token验证失败' });
    }

    // 执行密码修改
    // …

    res.json({ success: true });
    });

    2. SameSite Cookie

    核心原理:通过设置cookie的SameSite属性,限制cookie只在同源请求中携带。

    属性值:

    • Strict:完全禁止跨站携带cookie
    • Lax:允许GET请求跨站携带cookie(如链接跳转)
    • None:允许所有跨站请求携带cookie(需要同时设置Secure)

    设置示例:

    // Express设置SameSite cookie
    app.use(session({
    secret: 'keyboard cat',
    resave: false,
    saveUninitialized: true,
    cookie: {
    sameSite: 'strict', // 或 'lax'
    secure: true // HTTPS环境下使用
    }
    }));

    3. Referer和Origin头检查

    核心原理:验证请求的来源,只接受来自可信域名的请求。

    实现:

    app.post('/api/change-password', (req, res) => {
    const referer = req.headers.referer;
    const origin = req.headers.origin;

    // 检查来源
    const trustedDomain = 'https://social.com';
    if (!referer || !referer.startsWith(trustedDomain) ||
    (origin && !origin === trustedDomain)) {
    return res.status(403).json({ error: '来源验证失败' });
    }

    // 执行操作
    // …
    });

    什么是Clickjacking攻击?

    Clickjacking(点击劫持)是指攻击者通过将目标网站嵌入到iframe中,覆盖透明或伪装的元素,诱导用户点击恶意按钮,从而执行未授权的操作。

    Clickjacking攻击的攻击流程

  • 攻击者构造恶意页面:将目标网站嵌入iframe,设置为透明
  • 覆盖伪装元素:在iframe上方放置看起来无害的按钮(如下载、点赞)
  • 用户点击伪装元素:实际点击的是iframe中的目标网站按钮
  • 执行恶意操作:如购买商品、关注账号等
  • 真实案例

    某社交媒体网站的关注按钮被攻击者通过Clickjacking攻击,诱导用户点击伪装的"下载壁纸"按钮,实际上执行了关注恶意账号的操作。

    实战:Clickjacking攻击演示

    场景:诱导用户关注恶意账号

    <!– 恶意页面 –>
    <!DOCTYPE html>
    <html>
    <head>
    <title>免费壁纸下载</title>
    <style>
    /* 目标网站iframe */
    #targetFrame {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    opacity: 0.01; /* 几乎透明 */
    z-index: 2;
    }

    /* 伪装按钮 */
    #fakeButton {
    position: absolute;
    top: 200px;
    left: 100px;
    width: 200px;
    height: 50px;
    background: #4CAF50;
    color: white;
    font-size: 18px;
    border: none;
    cursor: pointer;
    z-index: 1;
    }
    </style>
    </head>
    <body>
    <h1>免费高清壁纸下载</h1>
    <button id="fakeButton">点击下载壁纸</button>

    <!– 嵌入目标网站(假设关注按钮位置与伪装按钮重合) –>
    <iframe id="targetFrame" src="https://social.com/profile/123456" frameborder="0"></iframe>
    </body>
    </html>

    当用户点击"点击下载壁纸"按钮时,实际点击的是iframe中的关注按钮,从而关注了攻击者的账号。

    Clickjacking防护策略

    1. X-Frame-Options头

    核心原理:通过HTTP头告诉浏览器是否允许页面被嵌入到iframe中。

    取值:

    • DENY:禁止所有网站嵌入
    • SAMEORIGIN:只允许同源网站嵌入
    • ALLOW-FROM uri:只允许指定网站嵌入(已被CSP取代)

    设置示例:

    # Nginx配置
    add_header X-Frame-Options "SAMEORIGIN" always;

    // Express配置
    app.use((req, res, next) => {
    res.setHeader('X-Frame-Options', 'SAMEORIGIN');
    next();
    });

    2. Content-Security-Policy(CSP)frame-ancestors指令

    核心原理:CSP的frame-ancestors指令更灵活地控制哪些网站可以嵌入当前页面。

    配置示例:

    # Nginx配置
    add_header Content-Security-Policy "frame-ancestors 'self' https://trusted.com;" always;

    // Express配置
    app.use((req, res, next) => {
    res.setHeader('Content-Security-Policy', "frame-ancestors 'self' https://trusted.com;");
    next();
    });

    3. JavaScript防护

    核心原理:通过JavaScript检测页面是否被嵌入到iframe中,若被嵌入则拒绝显示或跳转到安全页面。

    实现:

    // 检测iframe嵌入
    if (window.top !== window.self) {
    // 页面被嵌入
    window.top.location.href = window.location.href;
    // 或显示警告
    document.body.innerHTML = '<h1>安全警告:此页面不能在iframe中打开</h1>';
    }

    实战:完整防护方案

    步骤1:集成CSRF Token

    • 前端:使用axios拦截器自动添加CSRF token
    • 后端:使用中间件统一验证CSRF token

    // 前端axios拦截器
    axios.interceptors.request.use(config => {
    // 从meta标签获取token
    const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
    if (csrfToken) {
    config.headers['X-CSRF-Token'] = csrfToken;
    }
    return config;
    });

    // 后端中间件
    const csrfProtection = (req, res, next) => {
    const token = req.headers['x-csrf-token'] || req.body.csrfToken;
    if (!token || token !== req.session.csrfToken) {
    return res.status(403).json({ error: 'CSRF验证失败' });
    }
    next();
    };

    app.post('/api/*', csrfProtection, (req, res) => {
    // 处理API请求
    });

    步骤2:配置安全头部

    • SameSite Cookie:防止CSRF攻击
    • X-Frame-Options:防止Clickjacking攻击
    • CSP:增强整体安全

    // Express统一头部配置
    app.use((req, res, next) => {
    // CSRF防护
    res.cookie('session', req.sessionID, {
    sameSite: 'strict',
    secure: process.env.NODE_ENV === 'production',
    httpOnly: true
    });

    // Clickjacking防护
    res.setHeader('X-Frame-Options', 'SAMEORIGIN');
    res.setHeader('Content-Security-Policy', "frame-ancestors 'self';");

    next();
    });

    安全检查清单

    CSRF防护检查

    • 是否使用了CSRF Token?
    • 是否设置了SameSite Cookie?
    • 是否验证了Referer/Origin头?
    • 敏感操作是否需要二次验证?

    Clickjacking防护检查

    • 是否设置了X-Frame-Options头?
    • 是否配置了CSP frame-ancestors指令?
    • 是否添加了JavaScript iframe检测?
    • 关键操作是否有防误触机制?

    安全小贴士

  • 不要依赖单一防护:组合使用多种防护策略,如CSRF Token + SameSite Cookie
  • 定期安全测试:使用工具(如OWASP ZAP)扫描CSRF和Clickjacking漏洞
  • 保持框架更新:使用最新版本的前端/后端框架,它们通常包含内置的安全防护
  • 用户教育:提醒用户不要随意点击来源不明的链接,定期检查账户活动

  • 通过本文的学习,相信你对CSRF和Clickjacking攻击有了更深入的了解。这两种攻击虽然隐蔽,但只要我们采取正确的防护措施,就能有效降低风险。

    下一篇文章,我们将探讨前端数据安全的相关问题,包括localStorage加密、API请求安全等,敬请期待!

    赞(0)
    未经允许不得转载:171主机测评 » 02-CSRF与Clickjacking:前端交互的隐形威胁
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址