UNPKG

aimless-security

Version:

Enhanced Runtime Application Self-Protection (RASP) and API Fuzzing Engine with advanced threat detection, behavioral analysis, and intelligent response scoring for Node.js applications

135 lines (134 loc) • 4.85 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RequestFingerprintEngine = void 0; class RequestFingerprintEngine { constructor() { this.knownBotPatterns = [ /bot|crawler|spider|scraper|curl|wget|postman|insomnia/i, /python-requests|go-http-client|java|okhttp/i, /headless|phantom|selenium|puppeteer|playwright/i, /scanner|nikto|nmap|sqlmap|burp|zap/i ]; this.suspiciousHeaders = [ 'x-scanner', 'x-forwarded-host', 'x-original-url', 'x-rewrite-url' ]; } analyzeRequest(headers) { const userAgent = headers['user-agent'] || ''; const acceptLanguage = headers['accept-language']; const acceptEncoding = headers['accept-encoding']; const connection = headers['connection']; // Calculate bot score (0-100) let botScore = 0; // Check user agent if (!userAgent) { botScore += 40; // No user agent = very suspicious } else { for (const pattern of this.knownBotPatterns) { if (pattern.test(userAgent)) { botScore += 60; break; } } } // Check for browser characteristics if (!acceptLanguage) botScore += 15; if (!acceptEncoding) botScore += 15; // Check for suspicious headers for (const header of this.suspiciousHeaders) { if (headers[header]) { botScore += 10; } } // Check for missing common browser headers if (!headers['accept']) botScore += 10; if (!headers['accept-language']) botScore += 10; // Check connection header if (connection && connection.toLowerCase() === 'close') { botScore += 5; // Bots often close connections } // Check if user agent matches typical browser pattern if (userAgent && !this.looksLikeBrowser(userAgent)) { botScore += 20; } // Generate browser fingerprint (simplified) const browserFingerprint = this.generateFingerprint(headers); return { userAgent, acceptLanguage, acceptEncoding, connection, isBot: botScore >= 50, botScore: Math.min(100, botScore), browserFingerprint }; } looksLikeBrowser(userAgent) { const browserIndicators = [ 'Mozilla/', 'Chrome/', 'Safari/', 'Firefox/', 'Edge/', 'Opera/' ]; return browserIndicators.some(indicator => userAgent.includes(indicator)); } generateFingerprint(headers) { // Simple fingerprint based on header combination const components = [ headers['user-agent'] || '', headers['accept-language'] || '', headers['accept-encoding'] || '', headers['accept'] || '' ]; const fingerprintString = components.join('|'); // Simple hash function let hash = 0; for (let i = 0; i < fingerprintString.length; i++) { const char = fingerprintString.charCodeAt(i); hash = ((hash << 5) - hash) + char; hash = hash & hash; // Convert to 32-bit integer } return Math.abs(hash).toString(36); } isSuspicious(fingerprint) { return fingerprint.isBot || fingerprint.botScore >= 60; } getRecommendedAction(fingerprint) { if (fingerprint.botScore >= 80) return 'block'; if (fingerprint.botScore >= 50) return 'challenge'; return 'allow'; } generateReport(fingerprint) { const action = this.getRecommendedAction(fingerprint); const risk = fingerprint.botScore >= 80 ? 'HIGH' : fingerprint.botScore >= 50 ? 'MEDIUM' : 'LOW'; return ` šŸ” Request Fingerprint Analysis ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Bot Score: ${fingerprint.botScore}/100 Risk Level: ${risk} Is Bot: ${fingerprint.isBot ? 'Yes' : 'No'} Recommended Action: ${action.toUpperCase()} User Agent: ${fingerprint.userAgent || 'N/A'} Accept-Language: ${fingerprint.acceptLanguage || 'N/A'} Accept-Encoding: ${fingerprint.acceptEncoding || 'N/A'} Connection: ${fingerprint.connection || 'N/A'} Fingerprint ID: ${fingerprint.browserFingerprint || 'N/A'} ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ `.trim(); } } exports.RequestFingerprintEngine = RequestFingerprintEngine; //# sourceMappingURL=request-fingerprint.js.map