/** * Sistema de Segurança Avançado * Implementa múltiplas camadas de proteção e monitoramento */ interface SecurityConfig { enableCSP: boolean; enableXSSProtection: boolean; enableRateLimiting: boolean; enableSecurityHeaders: boolean; enableIntegrityChecks: boolean; } interface SecurityThreat { type: string; severity: 'low' | 'medium' | 'high' | 'critical'; details: any; timestamp: number; mitigated: boolean; } export class SecurityEnhanced { private static instance: SecurityEnhanced; private config: SecurityConfig; private threats: SecurityThreat[] = []; private isEnabled = true; private constructor() { this.config = { enableCSP: true, enableXSSProtection: true, enableRateLimiting: true, enableSecurityHeaders: true, enableIntegrityChecks: true }; } static getInstance(): SecurityEnhanced { if (!SecurityEnhanced.instance) { SecurityEnhanced.instance = new SecurityEnhanced(); } return SecurityEnhanced.instance; } /** * Inicializar todas as proteções de segurança */ initialize(): void { if (!this.isEnabled) return; console.log('🛡️ Inicializando sistema de segurança avançado...'); this.setupContentSecurityPolicy(); this.setupSecurityHeaders(); this.setupXSSProtection(); this.setupIntegrityChecks(); this.setupThreatMonitoring(); this.setupSecureStorage(); } private setupContentSecurityPolicy(): void { if (!this.config.enableCSP) return; const csp = { 'default-src': ["'self'"], 'script-src': [ "'self'", "'unsafe-inline'", // Necessário para React em desenvolvimento "'unsafe-eval'", // Necessário para desenvolvimento 'https://servicebus2.caixa.gov.br', 'https://brasilapi.com.br' ], 'style-src': [ "'self'", "'unsafe-inline'", // Necessário para Tailwind CSS 'https://fonts.googleapis.com' ], 'font-src': [ "'self'", 'https://fonts.gstatic.com' ], 'connect-src': [ "'self'", 'https://servicebus2.caixa.gov.br', 'https://brasilapi.com.br', 'https://api.loterias-caixa.com' ], 'img-src': [ "'self'", 'data:', 'https:' ], 'frame-ancestors': ["'none'"], 'base-uri': ["'self'"], 'form-action': ["'self'"] }; const cspString = Object.entries(csp) .map(([directive, sources]) => `${directive} ${sources.join(' ')}`) .join('; '); // Em produção, seria configurado no servidor if (process.env.NODE_ENV === 'development') { console.log('🛡️ CSP configurado:', cspString); } } private setupSecurityHeaders(): void { if (!this.config.enableSecurityHeaders) return; // Headers que seriam configurados no servidor const securityHeaders = { 'X-Content-Type-Options': 'nosniff', 'X-Frame-Options': 'DENY', 'X-XSS-Protection': '1; mode=block', 'Referrer-Policy': 'strict-origin-when-cross-origin', 'Permissions-Policy': 'camera=(), microphone=(), geolocation=()', 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains' }; console.log('🛡️ Security headers configurados:', securityHeaders); } private setupXSSProtection(): void { if (!this.config.enableXSSProtection) return; // Monitorar tentativas de XSS this.monitorDOMChanges(); this.validateUserInputs(); this.sanitizeURLParameters(); } private monitorDOMChanges(): void { if (typeof window === 'undefined') return; const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { mutation.addedNodes.forEach((node) => { if (node.nodeType === Node.ELEMENT_NODE) { const element = node as Element; // Verificar scripts suspeitos if (element.tagName === 'SCRIPT') { const src = element.getAttribute('src'); const inline = element.textContent; if (src && !this.isAllowedScriptSource(src)) { this.recordThreat('unauthorized-script', 'high', { src }); element.remove(); } if (inline && this.containsSuspiciousCode(inline)) { this.recordThreat('suspicious-inline-script', 'high', { code: inline.substring(0, 100) }); element.remove(); } } // Verificar iframes suspeitos if (element.tagName === 'IFRAME') { const src = element.getAttribute('src'); if (src && !this.isAllowedFrameSource(src)) { this.recordThreat('unauthorized-iframe', 'high', { src }); element.remove(); } } } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); console.log('🛡️ Monitoramento de DOM ativo para XSS'); } private validateUserInputs(): void { // Interceptar inputs do usuário document.addEventListener('input', (event) => { const target = event.target as HTMLInputElement; if (target && target.value) { const sanitized = this.sanitizeInput(target.value); if (sanitized !== target.value) { this.recordThreat('xss-attempt', 'medium', { original: target.value.substring(0, 100), sanitized: sanitized.substring(0, 100) }); target.value = sanitized; } } }); console.log('🛡️ Validação de inputs ativa'); } private sanitizeURLParameters(): void { if (typeof window === 'undefined') return; const params = new URLSearchParams(window.location.search); let hasThreats = false; params.forEach((value, key) => { const sanitized = this.sanitizeInput(value); if (sanitized !== value) { this.recordThreat('url-xss-attempt', 'medium', { parameter: key, original: value.substring(0, 100) }); params.set(key, sanitized); hasThreats = true; } }); if (hasThreats) { const newUrl = `${window.location.pathname}?${params.toString()}`; window.history.replaceState({}, '', newUrl); console.log('🛡️ Parâmetros URL sanitizados'); } } private setupIntegrityChecks(): void { if (!this.config.enableIntegrityChecks) return; // Verificar integridade de recursos externos const externalScripts = document.querySelectorAll('script[src]'); const externalStyles = document.querySelectorAll('link[rel="stylesheet"][href]'); Array.from(externalScripts).concat(Array.from(externalStyles)).forEach(element => { if (!element.hasAttribute('integrity')) { const src = element.getAttribute('src') || element.getAttribute('href'); if (src && this.isExternalResource(src)) { this.recordThreat('missing-integrity', 'low', { src }); } } }); console.log('🛡️ Verificação de integridade ativa'); } private setupThreatMonitoring(): void { // Monitorar atividades suspeitas this.monitorConsoleAccess(); this.monitorDevToolsUsage(); this.monitorSuspiciousNetworkActivity(); } private monitorConsoleAccess(): void { // Detectar tentativas de acesso ao console em produção if (process.env.NODE_ENV === 'production') { const originalConsole = { ...console }; ['log', 'warn', 'error', 'debug'].forEach(method => { (console as any)[method] = (...args: any[]) => { // Em produção, log suspeito if (args.some(arg => typeof arg === 'string' && (arg.includes('eval') || arg.includes('Function') || arg.includes('script')) )) { this.recordThreat('suspicious-console-access', 'low', { args: args.slice(0, 3) }); } return (originalConsole as any)[method](...args); }; }); } } private monitorDevToolsUsage(): void { // Detectar abertura do DevTools let devtools = { open: false }; setInterval(() => { const start = performance.now(); debugger; // eslint-disable-line no-debugger const end = performance.now(); if (end - start > 100) { // DevTools likely open if (!devtools.open) { devtools.open = true; this.recordThreat('devtools-opened', 'low', { timestamp: Date.now() }); } } else { devtools.open = false; } }, 1000); } private monitorSuspiciousNetworkActivity(): void { // Interceptar fetch para monitorar requisições suspeitas const originalFetch = window.fetch; window.fetch = async (...args) => { const url = args[0].toString(); // Verificar URLs suspeitas if (this.isSuspiciousURL(url)) { this.recordThreat('suspicious-network-request', 'medium', { url }); throw new Error('Requisição bloqueada por segurança'); } return originalFetch(...args); }; } private setupSecureStorage(): void { // Implementar armazenamento seguro const originalSetItem = localStorage.setItem; const originalGetItem = localStorage.getItem; localStorage.setItem = (key: string, value: string) => { // Criptografar dados sensíveis if (this.isSensitiveData(key)) { value = this.encryptData(value); } return originalSetItem.call(localStorage, key, value); }; localStorage.getItem = (key: string) => { const value = originalGetItem.call(localStorage, key); if (value && this.isSensitiveData(key)) { return this.decryptData(value); } return value; }; console.log('🛡️ Armazenamento seguro configurado'); } private sanitizeInput(input: string): string { return input .replace(/)<[^<]*)*<\/script>/gi, '') .replace(/javascript:/gi, '') .replace(/on\w+=/gi, '') .replace(/eval\(/gi, '') .replace(/Function\(/gi, '') .replace(/setTimeout\(/gi, '') .replace(/setInterval\(/gi, ''); } private containsSuspiciousCode(code: string): boolean { const suspiciousPatterns = [ /eval\s*\(/, /Function\s*\(/, /document\.write/, /innerHTML\s*=/, /outerHTML\s*=/, /javascript:/, /data:text\/html/, /execScript/, /setInterval.*eval/, /setTimeout.*eval/ ]; return suspiciousPatterns.some(pattern => pattern.test(code)); } private isAllowedScriptSource(src: string): boolean { const allowedDomains = [ window.location.origin, 'https://servicebus2.caixa.gov.br', 'https://brasilapi.com.br', 'https://fonts.googleapis.com', 'https://fonts.gstatic.com' ]; return allowedDomains.some(domain => src.startsWith(domain)); } private isAllowedFrameSource(src: string): boolean { // Por padrão, não permitir iframes externos return src.startsWith(window.location.origin); } private isExternalResource(src: string): boolean { return !src.startsWith(window.location.origin) && (src.startsWith('http://') || src.startsWith('https://')); } private isSuspiciousURL(url: string): boolean { const suspiciousPatterns = [ /bit\.ly/, /tinyurl/, /malware/, /phishing/, /\.tk$/, /\.ml$/ ]; return suspiciousPatterns.some(pattern => pattern.test(url)); } private isSensitiveData(key: string): boolean { const sensitiveKeys = ['token', 'password', 'secret', 'key', 'auth']; return sensitiveKeys.some(sensitive => key.toLowerCase().includes(sensitive)); } private encryptData(data: string): string { // Implementação simples de encoding (em produção, usar crypto real) return btoa(encodeURIComponent(data)); } private decryptData(data: string): string { try { return decodeURIComponent(atob(data)); } catch { return data; // Retornar original se não conseguir decodificar } } private recordThreat(type: string, severity: SecurityThreat['severity'], details: any): void { const threat: SecurityThreat = { type, severity, details, timestamp: Date.now(), mitigated: false }; this.threats.push(threat); // Log baseado na severidade const emoji = severity === 'critical' ? '🚨' : severity === 'high' ? '⚠️' : '⚡'; console.warn(`${emoji} Ameaça ${severity}: ${type}`, details); // Auto-mitigar ameaças conhecidas this.mitigateThreat(threat); } private mitigateThreat(threat: SecurityThreat): void { switch (threat.type) { case 'unauthorized-script': case 'unauthorized-iframe': // Já removido no monitoramento threat.mitigated = true; break; case 'xss-attempt': case 'url-xss-attempt': // Já sanitizado threat.mitigated = true; break; default: // Log para investigação manual break; } } /** * Obter relatório de segurança */ getSecurityReport(): { threatsDetected: number; threatsMitigated: number; recentThreats: SecurityThreat[]; recommendations: string[]; } { const recent = this.threats.filter(t => Date.now() - t.timestamp < 24 * 60 * 60 * 1000); // Last 24h const mitigated = this.threats.filter(t => t.mitigated).length; return { threatsDetected: this.threats.length, threatsMitigated: mitigated, recentThreats: recent, recommendations: this.generateSecurityRecommendations() }; } private generateSecurityRecommendations(): string[] { const recommendations = []; if (this.threats.some(t => t.type.includes('xss'))) { recommendations.push('🛡️ Implementar sanitização mais rigorosa de inputs'); } if (this.threats.some(t => t.type.includes('script'))) { recommendations.push('🔒 Revisar Content Security Policy'); } if (this.threats.some(t => t.severity === 'high' || t.severity === 'critical')) { recommendations.push('🚨 Revisar logs de segurança imediatamente'); } if (recommendations.length === 0) { recommendations.push('✅ Sistema seguro - nenhuma ameaça significativa detectada'); } return recommendations; } /** * Limpar dados de segurança */ cleanup(): void { this.threats = []; console.log('🧹 Dados de segurança limpos'); } /** * Ativar/desativar sistema de segurança */ setEnabled(enabled: boolean): void { this.isEnabled = enabled; if (enabled) { this.initialize(); } } } // Singleton instance export const securityEnhanced = SecurityEnhanced.getInstance();