乐闻世界logo
搜索文章和话题

如何测试和验证 CSRF 防护措施的有效性?

2月21日 16:11

CSRF 攻击的测试和验证是确保防护措施有效性的重要环节,通过系统化的测试可以发现潜在的安全漏洞。

CSRF 攻击测试方法

1. 手动测试

基本测试步骤

  1. 准备测试环境

    • 登录目标应用
    • 打开浏览器开发者工具
    • 记录 Cookie 和 Session 信息
  2. 构造恶意请求

html
<!-- 测试页面 --> <!DOCTYPE html> <html> <head> <title>CSRF Test</title> </head> <body> <h1>CSRF Attack Test</h1> <form id="csrfForm" action="https://target-site.com/api/transfer" method="POST"> <input type="hidden" name="to" value="attacker"> <input type="hidden" name="amount" value="100"> </form> <button onclick="document.getElementById('csrfForm').submit()">Test CSRF</button> </body> </html>
  1. 验证攻击结果
    • 检查请求是否成功
    • 查看服务器响应
    • 确认是否执行了恶意操作

2. 自动化测试

使用 Burp Suite

python
# Burp Suite CSRF Token 检测脚本 from burp import IBurpExtender from burp import IHttpListener class BurpExtender(IBurpExtender, IHttpListener): def registerExtenderCallbacks(self, callbacks): self._callbacks = callbacks self._helpers = callbacks.getHelpers() callbacks.registerHttpListener(self) def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo): if messageIsRequest: request = messageInfo.getRequest() analyzedRequest = self._helpers.analyzeRequest(request) # 检查是否缺少 CSRF Token headers = analyzedRequest.getHeaders() hasCSRFToken = any('csrf' in header.lower() for header in headers) if not hasCSRFToken and analyzedRequest.getMethod() in ['POST', 'PUT', 'DELETE']: print(f"Potential CSRF vulnerability: {analyzedRequest.getUrl()}")

使用 OWASP ZAP

bash
# 使用 OWASP ZAP 进行 CSRF 扫描 zap-cli quick-scan --self-contained --start-options '-config api.disablekey=true' \ --spider -r csrf_report.html https://target-site.com

3. 单元测试

CSRF Token 验证测试

javascript
// Jest 测试示例 describe('CSRF Protection', () => { let app; let csrfToken; beforeAll(async () => { app = require('./app'); // 获取 CSRF Token const response = await request(app).get('/api/csrf-token'); csrfToken = response.body.csrfToken; }); test('应该拒绝没有 CSRF Token 的 POST 请求', async () => { const response = await request(app) .post('/api/submit') .send({ data: 'test' }); expect(response.status).toBe(403); expect(response.body.error).toContain('CSRF'); }); test('应该拒绝无效的 CSRF Token', async () => { const response = await request(app) .post('/api/submit') .set('X-CSRF-Token', 'invalid-token') .send({ data: 'test' }); expect(response.status).toBe(403); }); test('应该接受有效的 CSRF Token', async () => { const response = await request(app) .post('/api/submit') .set('X-CSRF-Token', csrfToken) .send({ data: 'test' }); expect(response.status).toBe(200); }); });

4. 集成测试

端到端 CSRF 测试

javascript
// Cypress 测试示例 describe('CSRF Protection E2E', () => { beforeEach(() => { cy.login('testuser', 'password'); }); it('应该防止跨站请求伪造', () => { // 访问恶意网站模拟页面 cy.visit('http://malicious-site.com/csrf-test.html'); // 点击触发 CSRF 攻击的按钮 cy.get('button').click(); // 验证请求被阻止 cy.on('window:alert', (str) => { expect(str).to.include('forbidden'); }); }); it('应该允许同站请求', () => { cy.visit('/protected-page'); // 获取 CSRF Token cy.get('meta[name="csrf-token"]').should('have.attr', 'content'); // 提交表单 cy.get('form').submit(); // 验证请求成功 cy.contains('Success').should('be.visible'); }); });

防护措施验证

1. CSRF Token 验证

javascript
// 验证 CSRF Token 的实现 function validateCSRFTokenImplementation(app) { const tests = [ { name: 'Token 应该是随机且不可预测的', test: async () => { const tokens = []; for (let i = 0; i < 100; i++) { const response = await request(app).get('/api/csrf-token'); tokens.push(response.body.csrfToken); } const uniqueTokens = new Set(tokens); return uniqueTokens.size === 100; } }, { name: 'Token 应该有足够的长度', test: async () => { const response = await request(app).get('/api/csrf-token'); return response.body.csrfToken.length >= 32; } }, { name: 'Token 应该有时效性', test: async () => { const response1 = await request(app).get('/api/csrf-token'); const token1 = response1.body.csrfToken; // 等待 Token 过期 await new Promise(resolve => setTimeout(resolve, 3600000)); const response2 = await request(app).get('/api/csrf-token'); const token2 = response2.body.csrfToken; return token1 !== token2; } } ]; return Promise.all(tests.map(async test => { const result = await test.test(); console.log(`${test.name}: ${result ? 'PASS' : 'FAIL'}`); return result; })); }
javascript
// 验证 SameSite Cookie 设置 function validateSameSiteCookie(response) { const cookies = response.headers['set-cookie']; if (!cookies) { return false; } return cookies.some(cookie => { return cookie.includes('SameSite=') && (cookie.includes('SameSite=Strict') || cookie.includes('SameSite=Lax')); }); }

3. Referer 头验证

javascript
// 验证 Referer 头检查 async function testRefererValidation(app) { // 测试没有 Referer 的请求 const response1 = await request(app) .post('/api/submit') .set('Referer', '') .send({ data: 'test' }); if (response1.status !== 403) { console.log('FAIL: Should reject requests without Referer'); return false; } // 测试无效的 Referer const response2 = await request(app) .post('/api/submit') .set('Referer', 'https://malicious-site.com') .send({ data: 'test' }); if (response2.status !== 403) { console.log('FAIL: Should reject requests with invalid Referer'); return false; } // 测试有效的 Referer const response3 = await request(app) .post('/api/submit') .set('Referer', 'https://target-site.com') .send({ data: 'test' }); if (response3.status === 403) { console.log('FAIL: Should accept requests with valid Referer'); return false; } console.log('PASS: Referer validation working correctly'); return true; }

渗透测试工具

1. 使用 Metasploit

bash
# 使用 Metasploit 的 CSRF 模块 msfconsole use auxiliary/http/csrf_test set RHOSTS target-site.com set RPORT 443 set SSL true exploit

2. 使用 CSRFTester

bash
# CSRFTester 工具使用 java -jar CSRFTester.jar # 导出测试报告

测试报告

测试报告模板

markdown
# CSRF 安全测试报告 ## 测试概述 - 测试日期: 2024-01-15 - 测试人员: Security Team - 测试范围: Web Application ## 测试方法 1. 手动测试 2. 自动化扫描 3. 代码审查 4. 渗透测试 ## 测试结果 ### 发现的漏洞 | 漏洞类型 | 严重程度 | 状态 | |---------|---------|------| | 缺少 CSRF Token || 已修复 | | SameSite Cookie 未设置 || 已修复 | | Referer 验证缺失 || 待修复 | ### 防护措施验证 - CSRF Token: ✅ 通过 - SameSite Cookie: ✅ 通过 - Referer 验证: ⚠️ 部分通过 - 双重提交 Cookie: ❌ 未实施 ## 建议 1. 实施双重提交 Cookie 2. 加强 Referer 验证 3. 定期进行安全测试

CSRF 攻击测试应该作为安全开发生命周期(SDLC)的一部分,定期进行以确保防护措施的有效性。

标签:CSRF