CSRF attack testing and verification are important steps to ensure the effectiveness of protection measures. Through systematic testing, potential security vulnerabilities can be discovered.
CSRF Attack Testing Methods
1. Manual Testing
Basic Testing Steps
-
Prepare Test Environment:
- Log in to target application
- Open browser developer tools
- Record Cookie and Session information
-
Construct Malicious Request:
html<!-- Test page --> <!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>
- Verify Attack Results:
- Check if request succeeded
- View server response
- Confirm if malicious operation was executed
2. Automated Testing
Using Burp Suite
python# Burp Suite CSRF Token detection script 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) # Check if CSRF Token is missing 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()}")
Using OWASP ZAP
bash# Use OWASP ZAP for CSRF scanning zap-cli quick-scan --self-contained --start-options '-config api.disablekey=true' \ --spider -r csrf_report.html https://target-site.com
3. Unit Testing
CSRF Token Verification Test
javascript// Jest test example describe('CSRF Protection', () => { let app; let csrfToken; beforeAll(async () => { app = require('./app'); // Get CSRF Token const response = await request(app).get('/api/csrf-token'); csrfToken = response.body.csrfToken; }); test('should reject POST requests without CSRF Token', async () => { const response = await request(app) .post('/api/submit') .send({ data: 'test' }); expect(response.status).toBe(403); expect(response.body.error).toContain('CSRF'); }); test('should reject invalid 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('should accept valid 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. Integration Testing
End-to-End CSRF Test
javascript// Cypress test example describe('CSRF Protection E2E', () => { beforeEach(() => { cy.login('testuser', 'password'); }); it('should prevent cross-site request forgery', () => { // Visit malicious website simulation page cy.visit('http://malicious-site.com/csrf-test.html'); // Click button to trigger CSRF attack cy.get('button').click(); // Verify request is blocked cy.on('window:alert', (str) => { expect(str).to.include('forbidden'); }); }); it('should allow same-site requests', () => { cy.visit('/protected-page'); // Get CSRF Token cy.get('meta[name="csrf-token"]').should('have.attr', 'content'); // Submit form cy.get('form').submit(); // Verify request succeeded cy.contains('Success').should('be.visible'); }); });
Protection Measure Verification
1. CSRF Token Verification
javascript// Verify CSRF Token implementation function validateCSRFTokenImplementation(app) { const tests = [ { name: 'Token should be random and unpredictable', 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 should have sufficient length', test: async () => { const response = await request(app).get('/api/csrf-token'); return response.body.csrfToken.length >= 32; } }, { name: 'Token should have time validity', test: async () => { const response1 = await request(app).get('/api/csrf-token'); const token1 = response1.body.csrfToken; // Wait for Token to expire 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; })); }
2. SameSite Cookie Verification
javascript// Verify SameSite Cookie settings 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 Header Verification
javascript// Verify Referer header check async function testRefererValidation(app) { // Test request without 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; } // Test invalid 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; } // Test valid 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; }
Penetration Testing Tools
1. Using Metasploit
bash# Use Metasploit's CSRF module msfconsole use auxiliary/http/csrf_test set RHOSTS target-site.com set RPORT 443 set SSL true exploit
2. Using CSRFTester
bash# CSRFTester tool usage java -jar CSRFTester.jar # Export test report
Test Report
Test Report Template
markdown# CSRF Security Test Report ## Test Overview - Test Date: 2024-01-15 - Testers: Security Team - Test Scope: Web Application ## Test Methods 1. Manual Testing 2. Automated Scanning 3. Code Review 4. Penetration Testing ## Test Results ### Vulnerabilities Found | Vulnerability Type | Severity | Status | |-------------------|----------|--------| | Missing CSRF Token | High | Fixed | | SameSite Cookie Not Set | Medium | Fixed | | Referer Validation Missing | Medium | Pending Fix | ### Protection Measure Verification - CSRF Token: ✅ Passed - SameSite Cookie: ✅ Passed - Referer Validation: ⚠️ Partially Passed - Double Submit Cookie: ❌ Not Implemented ## Recommendations 1. Implement Double Submit Cookie 2. Strengthen Referer Validation 3. Conduct regular security testing
CSRF attack testing should be part of the Secure Development Lifecycle (SDLC) and conducted regularly to ensure the effectiveness of protection measures.