Real-Time Security Monitoring

Real-Time Security Monitoring

Real-time monitoring enables rapid detection and response to security incidents. Effective monitoring combines multiple data sources, applies intelligent analysis, and generates actionable alerts without overwhelming security teams with false positives.

// Node.js real-time security monitoring system
const EventEmitter = require('events');
const Redis = require('redis');
const { InfluxDB, Point } = require('@influxdata/influxdb-client');

class SecurityMonitor extends EventEmitter {
    constructor(config) {
        super();
        this.config = config;
        this.redis = Redis.createClient(config.redis);
        this.influx = new InfluxDB(config.influxdb);
        this.writeApi = this.influx.getWriteApi(config.org, config.bucket);
        
        this.patterns = new Map();
        this.alerts = new Map();
        this.initializePatterns();
    }
    
    initializePatterns() {
        // Define security patterns to monitor
        this.patterns.set('brute_force', {
            window: 300, // 5 minutes
            threshold: 10,
            key: (event) => `auth_failure:${event.ip_address}`,
            condition: (event) => event.event_type === 'authentication' && !event.success
        });
        
        this.patterns.set('credential_stuffing', {
            window: 600, // 10 minutes
            threshold: 5,
            key: (event) => `auth_attempt:${event.ip_address}:unique_users`,
            condition: (event) => event.event_type === 'authentication'
        });
        
        this.patterns.set('api_scanning', {
            window: 60, // 1 minute
            threshold: 50,
            key: (event) => `404_errors:${event.ip_address}`,
            condition: (event) => event.status_code === 404
        });
        
        this.patterns.set('privilege_escalation', {
            window: 3600, // 1 hour
            threshold: 3,
            key: (event) => `priv_escalation:${event.user_id}`,
            condition: (event) => event.event_type === 'authorization' && 
                                 !event.granted && 
                                 event.missing_permissions?.includes('admin')
        });
        
        this.patterns.set('data_exfiltration', {
            window: 300, // 5 minutes
            threshold: 1000000, // 1MB
            key: (event) => `data_transfer:${event.user_id}`,
            condition: (event) => event.event_type === 'api_response',
            value: (event) => event.response_size || 0
        });
    }
    
    async processEvent(event) {
        // Enrich event with additional context
        event = await this.enrichEvent(event);
        
        // Check against all patterns
        for (const [patternName, pattern] of this.patterns) {
            if (pattern.condition(event)) {
                await this.updatePattern(patternName, pattern, event);
            }
        }
        
        // Store metrics
        await this.storeMetrics(event);
        
        // Check for anomalies
        await this.detectAnomalies(event);
    }
    
    async updatePattern(patternName, pattern, event) {
        const key = pattern.key(event);
        const value = pattern.value ? pattern.value(event) : 1;
        
        // Update counter in Redis
        const multi = this.redis.multi();
        
        if (patternName === 'credential_stuffing') {
            // Track unique usernames per IP
            multi.sadd(key, event.username);
            multi.expire(key, pattern.window);
            
            const results = await multi.exec();
            const uniqueUsers = await this.redis.scard(key);
            
            if (uniqueUsers >= pattern.threshold) {
                await this.triggerAlert('credential_stuffing', {
                    ip_address: event.ip_address,
                    unique_users_attempted: uniqueUsers,
                    window: pattern.window
                });
            }
        } else {
            // Standard counter pattern
            multi.incrby(key, value);
            multi.expire(key, pattern.window);
            
            const results = await multi.exec();
            const currentValue = results[0][1];
            
            if (currentValue >= pattern.threshold) {
                await this.triggerAlert(patternName, {
                    ...event,
                    current_value: currentValue,
                    threshold: pattern.threshold,
                    window: pattern.window
                });
            }
        }
    }
    
    async detectAnomalies(event) {
        // User behavior anomaly detection
        if (event.user_id) {
            const userProfile = await this.getUserProfile(event.user_id);
            const anomalyScore = this.calculateAnomalyScore(event, userProfile);
            
            if (anomalyScore > 0.8) {
                await this.triggerAlert('behavior_anomaly', {
                    user_id: event.user_id,
                    anomaly_score: anomalyScore,
                    event: event,
                    baseline: userProfile
                });
            }
        }
        
        // Geographic anomaly detection
        if (event.ip_address && event.user_id) {
            const isGeoAnomaly = await this.detectGeographicAnomaly(
                event.user_id, 
                event.ip_address
            );
            
            if (isGeoAnomaly) {
                await this.triggerAlert('geographic_anomaly', {
                    user_id: event.user_id,
                    ip_address: event.ip_address,
                    location: event.geo_location
                });
            }
        }
    }
    
    async triggerAlert(alertType, details) {
        // Deduplication
        const alertKey = `${alertType}:${JSON.stringify(details)}`;
        const recentAlert = this.alerts.get(alertKey);
        
        if (recentAlert && Date.now() - recentAlert < 300000) { // 5 min
            return; // Skip duplicate alerts
        }
        
        this.alerts.set(alertKey, Date.now());
        
        // Emit alert event
        this.emit('security_alert', {
            type: alertType,
            severity: this.getAlertSeverity(alertType),
            details: details,
            timestamp: new Date().toISOString(),
            recommended_actions: this.getRecommendedActions(alertType)
        });
        
        // Store alert
        await this.storeAlert(alertType, details);
        
        // Automated response for critical alerts
        if (this.shouldAutoRespond(alertType)) {
            await this.executeAutoResponse(alertType, details);
        }
    }
    
    async executeAutoResponse(alertType, details) {
        switch (alertType) {
            case 'brute_force':
                // Temporarily block IP
                await this.blockIP(details.ip_address, 3600); // 1 hour
                break;
                
            case 'credential_stuffing':
                // Enable CAPTCHA for IP
                await this.enableCaptcha(details.ip_address);
                break;
                
            case 'api_scanning':
                // Rate limit IP more aggressively
                await this.tightenRateLimit(details.ip_address);
                break;
                
            case 'data_exfiltration':
                // Suspend user account for review
                await this.suspendUser(details.user_id);
                break;
        }
    }
    
    async storeMetrics(event) {
        // Write to InfluxDB for time-series analysis
        const point = new Point('api_security_events')
            .tag('event_type', event.event_type)
            .tag('service', this.config.service_name)
            .tag('environment', this.config.environment);
            
        if (event.user_id) {
            point.tag('user_id', event.user_id);
        }
        
        if (event.status_code) {
            point.intField('status_code', event.status_code);
        }
        
        if (event.response_time_ms) {
            point.floatField('response_time_ms', event.response_time_ms);
        }
        
        if (event.risk_score) {
            point.floatField('risk_score', event.risk_score);
        }
        
        this.writeApi.writePoint(point);
    }
}

// Integration with Express middleware
const securityMonitor = new SecurityMonitor(config);

// Alert handler
securityMonitor.on('security_alert', async (alert) => {
    console.error('Security Alert:', alert);
    
    // Send to SIEM
    await siemClient.sendAlert(alert);
    
    // Notify security team
    if (alert.severity === 'CRITICAL') {
        await notificationService.pageSecurity(alert);
    } else {
        await notificationService.emailSecurity(alert);
    }
});

// Middleware for automatic monitoring
app.use(async (req, res, next) => {
    const startTime = Date.now();
    
    // Capture response data
    const originalSend = res.send;
    res.send = function(data) {
        res.responseData = data;
        originalSend.call(this, data);
    };
    
    res.on('finish', async () => {
        const event = {
            event_type: 'api_request',
            method: req.method,
            path: req.path,
            status_code: res.statusCode,
            response_time_ms: Date.now() - startTime,
            response_size: res.get('content-length'),
            ip_address: req.ip,
            user_id: req.user?.id,
            user_agent: req.get('user-agent')
        };
        
        await securityMonitor.processEvent(event);
    });
    
    next();
});