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

How to detect and log CSRF attacks and what are the monitoring strategies?

2月21日 16:11

CSRF attack detection and logging are important components of security protection, helping to timely discover attack behaviors, analyze attack patterns, and improve protection strategies.

CSRF Attack Detection Methods

1. Request Pattern Analysis

javascript
// Detect abnormal request patterns class CSRFAttackDetector { constructor() { this.requestHistory = new Map(); this.suspiciousPatterns = []; } analyzeRequest(req) { const userId = req.user?.id; const ip = req.ip; const userAgent = req.headers['user-agent']; const referer = req.headers.referer; const origin = req.headers.origin; // Detect suspicious patterns const suspicious = { missingReferer: !referer && req.method !== 'GET', mismatchedOrigin: origin && referer && this.extractDomain(origin) !== this.extractDomain(referer), rapidRequests: this.checkRapidRequests(userId, ip), unusualUserAgent: this.checkUnusualUserAgent(userAgent), suspiciousReferer: this.checkSuspiciousReferer(referer) }; return suspicious; } extractDomain(url) { try { return new URL(url).hostname; } catch { return null; } } checkRapidRequests(userId, ip) { const key = `${userId}-${ip}`; const now = Date.now(); const history = this.requestHistory.get(key) || []; // Check number of requests in last 10 seconds const recentRequests = history.filter(time => now - time < 10000); this.requestHistory.set(key, [...recentRequests, now]); return recentRequests.length > 20; // Threshold } checkUnusualUserAgent(userAgent) { // Detect characteristics of automated tools const suspiciousPatterns = [ /bot/i, /crawler/i, /spider/i, /curl/i, /wget/i ]; return suspiciousPatterns.some(pattern => pattern.test(userAgent)); } checkSuspiciousReferer(referer) { if (!referer) return false; // List of known malicious domains const maliciousDomains = [ 'malicious-site.com', 'evil-attacker.net' ]; const domain = this.extractDomain(referer); return maliciousDomains.includes(domain); } }

2. Behavior Analysis

javascript
// User behavior analysis class BehaviorAnalyzer { constructor() { this.userProfiles = new Map(); } analyzeUserBehavior(userId, req) { const profile = this.userProfiles.get(userId) || this.createProfile(userId); // Update user behavior data profile.requestCount++; profile.lastActivity = Date.now(); profile.requestTypes[req.method] = (profile.requestTypes[req.method] || 0) + 1; // Detect abnormal behaviors const anomalies = { suddenActivitySpike: this.checkActivitySpike(profile), unusualRequestPattern: this.checkRequestPattern(profile, req), geographicAnomaly: this.checkGeographicAnomaly(profile, req.ip) }; this.userProfiles.set(userId, profile); return anomalies; } checkActivitySpike(profile) { const timeWindow = 60000; // 1 minute const threshold = 50; // Threshold const recentActivity = profile.activityHistory.filter( time => Date.now() - time < timeWindow ).length; return recentActivity > threshold; } checkRequestPattern(profile, req) { // Detect uncommon request patterns const commonPatterns = ['GET', 'POST']; return !commonPatterns.includes(req.method) && profile.requestTypes[req.method] === 1; } checkGeographicAnomaly(profile, ip) { // Detect geographic anomalies (requires IP geolocation database) const currentLocation = this.getLocationFromIP(ip); if (profile.previousLocations.length > 0) { const distance = this.calculateDistance( profile.previousLocations[profile.previousLocations.length - 1], currentLocation ); // If distance is too large and time is short, may be anomaly const timeDiff = Date.now() - profile.lastLocationCheck; return distance > 1000 && timeDiff < 3600000; // 1000km, 1 hour } return false; } }

Logging System

1. Structured Logging

javascript
// CSRF event logger class CSRFLogger { constructor() { this.logs = []; this.logFile = 'csrf-events.log'; } logCSRFEvent(event) { const logEntry = { timestamp: new Date().toISOString(), eventType: event.type, // 'attempt', 'blocked', 'detected' userId: event.userId, ip: event.ip, userAgent: event.userAgent, request: { method: event.method, path: event.path, headers: this.sanitizeHeaders(event.headers) }, detection: { reason: event.reason, confidence: event.confidence, patterns: event.patterns }, metadata: { sessionId: event.sessionId, referer: event.referer, origin: event.origin } }; this.logs.push(logEntry); this.writeToFile(logEntry); this.sendAlert(logEntry); } sanitizeHeaders(headers) { // Remove sensitive information const sanitized = { ...headers }; delete sanitized.cookie; delete sanitized.authorization; return sanitized; } writeToFile(logEntry) { const logLine = JSON.stringify(logEntry) + '\n'; fs.appendFileSync(this.logFile, logLine); } sendAlert(logEntry) { // Send alert notifications if (logEntry.eventType === 'blocked' || logEntry.detection.confidence > 0.8) { this.notifySecurityTeam(logEntry); } } notifySecurityTeam(logEntry) { // Integrate alert system (e.g., Slack, Email, PagerDuty) console.log('🚨 CSRF Attack Alert:', logEntry); } }

2. Real-time Monitoring

javascript
// Real-time CSRF attack monitoring class CSRFMonitor { constructor() { this.detector = new CSRFAttackDetector(); this.behaviorAnalyzer = new BehaviorAnalyzer(); this.logger = new CSRFLogger(); this.alertThreshold = 10; // More than 10 attacks in 10 minutes } monitorRequest(req, res, next) { const suspicious = this.detector.analyzeRequest(req); // Check if there are suspicious patterns const hasSuspiciousPattern = Object.values(suspicious).some(v => v); if (hasSuspiciousPattern) { this.logger.logCSRFEvent({ type: 'detected', userId: req.user?.id, ip: req.ip, userAgent: req.headers['user-agent'], method: req.method, path: req.path, headers: req.headers, reason: suspicious, confidence: this.calculateConfidence(suspicious), patterns: Object.keys(suspicious).filter(k => suspicious[k]), sessionId: req.sessionID, referer: req.headers.referer, origin: req.headers.origin }); // Decide whether to block request based on confidence if (this.calculateConfidence(suspicious) > 0.7) { return res.status(403).send('Request blocked due to suspicious activity'); } } next(); } calculateConfidence(suspicious) { // Calculate attack confidence const weights = { missingReferer: 0.3, mismatchedOrigin: 0.4, rapidRequests: 0.5, unusualUserAgent: 0.2, suspiciousReferer: 0.8 }; let confidence = 0; for (const [key, value] of Object.entries(suspicious)) { if (value && weights[key]) { confidence += weights[key]; } } return Math.min(confidence, 1.0); } }

Integration into Application

javascript
// Express middleware integration const csrfMonitor = new CSRFMonitor(); // Apply CSRF monitoring middleware app.use(csrfMonitor.monitorRequest.bind(csrfMonitor)); // CSRF protection middleware app.use((req, res, next) => { if (['GET', 'HEAD', 'OPTIONS'].includes(req.method)) { return next(); } // Verify CSRF Token const token = req.body._csrf || req.headers['x-csrf-token']; if (token !== req.session.csrfToken) { csrfMonitor.logger.logCSRFEvent({ type: 'blocked', userId: req.user?.id, ip: req.ip, userAgent: req.headers['user-agent'], method: req.method, path: req.path, headers: req.headers, reason: { invalidToken: true }, confidence: 0.9, patterns: ['invalidToken'], sessionId: req.sessionID, referer: req.headers.referer, origin: req.headers.origin }); return res.status(403).send('Invalid CSRF token'); } next(); });

Log Analysis and Reporting

javascript
// Log analysis tool class CSRFLogAnalyzer { constructor(logger) { this.logger = logger; } generateReport(timeRange = '24h') { const logs = this.filterLogsByTime(timeRange); return { summary: { totalAttempts: logs.length, blockedAttempts: logs.filter(l => l.eventType === 'blocked').length, detectedAttempts: logs.filter(l => l.eventType === 'detected').length, uniqueIPs: new Set(logs.map(l => l.ip)).size, uniqueUsers: new Set(logs.filter(l => l.userId).map(l => l.userId)).size }, topAttackers: this.getTopAttackers(logs), commonPatterns: this.getCommonPatterns(logs), timeline: this.getAttackTimeline(logs) }; } getTopAttackers(logs, limit = 10) { const ipCounts = {}; logs.forEach(log => { ipCounts[log.ip] = (ipCounts[log.ip] || 0) + 1; }); return Object.entries(ipCounts) .sort((a, b) => b[1] - a[1]) .slice(0, limit) .map(([ip, count]) => ({ ip, count })); } getCommonPatterns(logs) { const patternCounts = {}; logs.forEach(log => { log.detection.patterns.forEach(pattern => { patternCounts[pattern] = (patternCounts[pattern] || 0) + 1; }); }); return Object.entries(patternCounts) .sort((a, b) => b[1] - a[1]); } getAttackTimeline(logs) { const timeline = {}; logs.forEach(log => { const hour = new Date(log.timestamp).getHours(); timeline[hour] = (timeline[hour] || 0) + 1; }); return timeline; } }

CSRF attack detection and logging systems should be used in combination with protection measures to form a complete security protection system. Regularly analyzing log data can help improve protection strategies and timely discover new attack patterns.

标签:CSRF