/** * ═══════════════════════════════════════════════════════════════════════════ * ADVANCED PENTESTING TOOLKIT - REAL TOOLS * ═══════════════════════════════════════════════════════════════════════════ * ✅ NMAP - Port scanning real * ✅ SQLMAP - SQL injection real * ✅ Hydra - Password cracking * ✅ Nuclei - Vulnerability scanning * ✅ Masscan - Fast port scanner * ✅ Nikto - Web server scanner * * TODAS AS FERRAMENTAS SÃO REAIS E OPENSOURCE DO GITHUB * ═══════════════════════════════════════════════════════════════════════════ */ const { spawn, execSync } = require('child_process'); const fs = require('fs'); const path = require('path'); class AdvancedPentestingToolkit { constructor(config = {}) { this.config = config; this.tools = { nmap: '/usr/bin/nmap', sqlmap: '/opt/sqlmap/sqlmap.py', hydra: '/usr/bin/hydra', nuclei: '/usr/local/bin/nuclei', masscan: '/usr/bin/masscan', nikto: '/usr/bin/nikto' }; this.resultsDir = config.resultsDir || '/tmp/pentest_results'; // Criar diretório de resultados if (!fs.existsSync(this.resultsDir)) { fs.mkdirSync(this.resultsDir, { recursive: true }); } console.log('✅ AdvancedPentestingToolkit inicializado com ferramentas REAIS'); } /** * ═════════════════════════════════════════════════════════════════════ * 🔍 NMAP - Port Scanning REAL * GitHub: https://github.com/nmap/nmap * ═════════════════════════════════════════════════════════════════════ */ async nmapScan(target, opcoes = '-sV -A -O') { try { if (!this._isTargetValid(target)) { return { sucesso: false, erro: 'Alvo inválido' }; } console.log(`🔍 Iniciando NMAP scan em: ${target}`); return new Promise((resolve, reject) => { const args = opcoes.split(' ').concat(target); const nmap = spawn('nmap', args); let output = ''; let error = ''; nmap.stdout.on('data', (data) => output += data.toString()); nmap.stderr.on('data', (data) => error += data.toString()); nmap.on('close', (code) => { if (code === 0) { const resultado = { sucesso: true, tipo: 'nmap_scan', target, comando: `nmap ${opcoes} ${target}`, output: output, parsado: this._parseNmapOutput(output), timestamp: new Date().toISOString(), risco: this._calculateNmapRisk(output) }; // Salvar resultado this._saveResult('nmap', target, resultado); resolve(resultado); } else { reject({ sucesso: false, erro: error || 'NMAP failed', code, target }); } }); // Timeout de 10 minutos setTimeout(() => { nmap.kill(); reject({ erro: 'NMAP timeout', target }); }, 600000); }); } catch (e) { console.error('Erro em nmapScan:', e); return { sucesso: false, erro: e.message }; } } /** * ═════════════════════════════════════════════════════════════════════ * 💾 SQLMAP - SQL Injection REAL * GitHub: https://github.com/sqlmapproject/sqlmap * ═════════════════════════════════════════════════════════════════════ */ async sqlmapTest(url, parametro = 'id', opcoes = '--risk=1 --level=1 --batch') { try { if (!this._isUrlValid(url)) { return { sucesso: false, erro: 'URL inválida' }; } console.log(`💾 Iniciando SQLMAP test em: ${url}`); return new Promise((resolve, reject) => { const args = [ 'sqlmap.py', '-u', url, '-p', parametro, '--dbs', ...opcoes.split(' ') ]; // Se não encontrar em /opt, tenta git clone const sqlmapPath = this._findSqlmap(); const sqlmap = spawn('python3', [sqlmapPath, ...args]); let output = ''; let error = ''; sqlmap.stdout.on('data', (data) => output += data.toString()); sqlmap.stderr.on('data', (data) => error += data.toString()); sqlmap.on('close', (code) => { const resultado = { sucesso: code === 0, tipo: 'sqlmap_test', target: url, parametro, vulneravel: output.includes('vulnerable'), output: output, parsado: this._parseSqlmapOutput(output), timestamp: new Date().toISOString(), risco: output.includes('vulnerable') ? 'CRÍTICO' : 'BAIXO' }; // Salvar resultado this._saveResult('sqlmap', url, resultado); resolve(resultado); }); // Timeout de 15 minutos setTimeout(() => { sqlmap.kill(); resolve({ sucesso: false, erro: 'SQLMAP timeout', target: url }); }, 900000); }); } catch (e) { console.error('Erro em sqlmapTest:', e); return { sucesso: false, erro: e.message }; } } /** * ═════════════════════════════════════════════════════════════════════ * 🔐 HYDRA - Password Cracking REAL * GitHub: https://github.com/vanhauser-thc/thc-hydra * ═════════════════════════════════════════════════════════════════════ */ async hydraBrute(target, servico = 'ssh', usuario = 'admin', senhas = ['password', 'admin', '123456']) { try { console.log(`🔐 Iniciando Hydra brute force: ${servico}://${target}`); return new Promise((resolve, reject) => { // Criar arquivo temporário com senhas const passwordFile = path.join(this.resultsDir, `passwords_${Date.now()}.txt`); fs.writeFileSync(passwordFile, senhas.join('\n')); const args = [ '-l', usuario, '-P', passwordFile, '-o', path.join(this.resultsDir, `hydra_${target}_${servico}.txt`), target, servico, '-f' // Sair após primeira tentativa bem-sucedida ]; const hydra = spawn('hydra', args); let output = ''; hydra.stdout.on('data', (data) => output += data.toString()); hydra.on('close', (code) => { const resultado = { sucesso: code === 0, tipo: 'hydra_brute', target, servico, usuario, output: output, encontrado: output.includes('password found') || output.includes('[*] Trying'), timestamp: new Date().toISOString() }; // Limpar arquivo temporário try { fs.unlinkSync(passwordFile); } catch (e) {} // Salvar resultado this._saveResult('hydra', `${servico}://${target}`, resultado); resolve(resultado); }); setTimeout(() => { hydra.kill(); resolve({ sucesso: false, erro: 'Hydra timeout', target, servico }); }, 600000); // 10 minutos }); } catch (e) { console.error('Erro em hydraBrute:', e); return { sucesso: false, erro: e.message }; } } /** * ═════════════════════════════════════════════════════════════════════ * 🎯 NUCLEI - Vulnerability Scanning REAL * GitHub: https://github.com/projectdiscovery/nuclei * ═════════════════════════════════════════════════════════════════════ */ async nucleiScan(target, templates = 'cves') { try { if (!this._isTargetValid(target)) { return { sucesso: false, erro: 'Alvo inválido' }; } console.log(`🎯 Iniciando Nuclei scan em: ${target}`); return new Promise((resolve, reject) => { const args = [ '-target', target, '-templates', templates, '-severity', 'critical,high,medium', '-json', '-o', path.join(this.resultsDir, `nuclei_${target}_${Date.now()}.json`) ]; const nuclei = spawn('nuclei', args); let output = ''; let jsonOutput = ''; nuclei.stdout.on('data', (data) => { const chunk = data.toString(); output += chunk; try { jsonOutput += chunk; } catch (e) {} }); nuclei.on('close', (code) => { try { const parsedOutput = jsonOutput.trim().split('\n') .filter(line => line.trim()) .map(line => { try { return JSON.parse(line); } catch (e) { return null; } }) .filter(x => x !== null); const resultado = { sucesso: code === 0, tipo: 'nuclei_scan', target, templates, vulnerabilidadesEncontradas: parsedOutput.length, vulnerabilidades: parsedOutput.slice(0, 10), // Top 10 timestamp: new Date().toISOString(), risco: parsedOutput.length > 5 ? 'CRÍTICO' : parsedOutput.length > 0 ? 'MÉDIO' : 'BAIXO' }; // Salvar resultado this._saveResult('nuclei', target, resultado); resolve(resultado); } catch (e) { resolve({ sucesso: false, erro: e.message, target, output: output.substring(0, 500) }); } }); setTimeout(() => { nuclei.kill(); resolve({ sucesso: false, erro: 'Nuclei timeout', target }); }, 900000); // 15 minutos }); } catch (e) { console.error('Erro em nucleiScan:', e); return { sucesso: false, erro: e.message }; } } /** * ═════════════════════════════════════════════════════════════════════ * ⚡ MASSCAN - Fast Port Scanner REAL * GitHub: https://github.com/robertdavidgraham/masscan * ═════════════════════════════════════════════════════════════════════ */ async masscanScan(target, portas = '1-65535') { try { if (!this._isTargetValid(target)) { return { sucesso: false, erro: 'Alvo inválido' }; } console.log(`⚡ Iniciando Masscan em: ${target}`); return new Promise((resolve, reject) => { const args = [ '-p', portas, target, '--rate', '1000', '-oX', path.join(this.resultsDir, `masscan_${target}_${Date.now()}.xml`) ]; const masscan = spawn('masscan', args); let output = ''; masscan.stdout.on('data', (data) => output += data.toString()); masscan.on('close', (code) => { const resultado = { sucesso: code === 0, tipo: 'masscan_scan', target, portas, output: output, parsado: this._parseMasscanOutput(output), timestamp: new Date().toISOString() }; // Salvar resultado this._saveResult('masscan', target, resultado); resolve(resultado); }); setTimeout(() => { masscan.kill(); resolve({ sucesso: false, erro: 'Masscan timeout', target }); }, 600000); // 10 minutos }); } catch (e) { console.error('Erro em masscanScan:', e); return { sucesso: false, erro: e.message }; } } /** * ═════════════════════════════════════════════════════════════════════ * 🕷️ NIKTO - Web Server Scanner REAL * ═════════════════════════════════════════════════════════════════════ */ async niktoScan(url, opcoes = '') { try { if (!this._isUrlValid(url)) { return { sucesso: false, erro: 'URL inválida' }; } console.log(`🕷️ Iniciando Nikto scan em: ${url}`); return new Promise((resolve, reject) => { const args = [ '-h', url, '-o', path.join(this.resultsDir, `nikto_${url.replace(/[^a-z0-9]/g, '_')}_${Date.now()}.txt`), ...opcoes.split(' ').filter(x => x) ]; const nikto = spawn('nikto', args); let output = ''; nikto.stdout.on('data', (data) => output += data.toString()); nikto.on('close', (code) => { const resultado = { sucesso: code === 0, tipo: 'nikto_scan', target: url, output: output, parsado: this._parseNiktoOutput(output), timestamp: new Date().toISOString(), vulnerabilidades: this._extractNiktoIssues(output) }; // Salvar resultado this._saveResult('nikto', url, resultado); resolve(resultado); }); setTimeout(() => { nikto.kill(); resolve({ sucesso: false, erro: 'Nikto timeout', target: url }); }, 600000); // 10 minutos }); } catch (e) { console.error('Erro em niktoScan:', e); return { sucesso: false, erro: e.message }; } } /** * ═════════════════════════════════════════════════════════════════════ * FUNÇÕES AUXILIARES PRIVADAS * ═════════════════════════════════════════════════════════════════════ */ _parseNmapOutput(output) { const portas = []; const lines = output.split('\n'); for (const line of lines) { const match = line.match(/(\d+)\/tcp\s+(\w+)\s+(.+)/); if (match) { portas.push({ porta: match[1], protocolo: 'tcp', estado: match[2], servico: match[3], risco: ['open', 'filtered'].includes(match[2]) ? 'MÉDIO' : 'BAIXO' }); } } return { totalPortas: portas.length, portasAbertas: portas.filter(p => p.estado === 'open').length, portas }; } _calculateNmapRisk(output) { const lines = output.split('\n'); const portasAbertas = lines.filter(line => line.includes('open')).length; if (portasAbertas > 10) return 'CRÍTICO'; if (portasAbertas > 5) return 'ALTO'; if (portasAbertas > 0) return 'MÉDIO'; return 'BAIXO'; } _parseSqlmapOutput(output) { return { vulneravel: output.includes('vulnerable'), bancoDados: output.includes('database') ? this._extractDatabase(output) : null, parametrosVulneraveis: this._extractVulnerableParams(output) }; } _extractDatabase(output) { const match = output.match(/database:\s*(\w+)/i); return match ? match[1] : 'unknown'; } _extractVulnerableParams(output) { const params = []; const lines = output.split('\n'); for (const line of lines) { if (line.includes('Parameter') && line.includes('vulnerable')) { const match = line.match(/Parameter:\s*([^,\s]+)/); if (match) params.push(match[1]); } } return params; } _parseMasscanOutput(output) { const portas = []; const lines = output.split('\n'); for (const line of lines) { const match = line.match(/host:\s*([\d.]+)\s+Ports:\s*([\d,\s/tcp/]+)/); if (match) { portas.push({ host: match[1], portas: match[2] }); } } return { portas }; } _parseNiktoOutput(output) { const issues = []; const lines = output.split('\n'); for (const line of lines) { if (line.includes('OSVDB') || line.includes('CVE')) { issues.push(line.trim()); } } return { totalIssues: issues.length, issues }; } _extractNiktoIssues(output) { const issues = []; const lines = output.split('\n'); for (const line of lines) { if (line.includes('+') && line.includes('Server')) { issues.push({ tipo: 'Server Detection', descricao: line.trim() }); } if (line.includes('OSVDB')) { issues.push({ tipo: 'OSVDB Issue', descricao: line.trim() }); } } return issues.slice(0, 10); // Top 10 } _isTargetValid(target) { return /^[\d.]+$/.test(target) || /^[\w.-]+$/.test(target); } _isUrlValid(url) { try { new URL(url); return true; } catch (e) { return false; } } _findSqlmap() { const possiblePaths = [ '/opt/sqlmap/sqlmap.py', '/usr/local/bin/sqlmap.py', './sqlmap/sqlmap.py', 'sqlmap.py' ]; for (const path of possiblePaths) { try { execSync(`test -f ${path}`); return path; } catch (e) {} } return 'sqlmap.py'; // Assume está no PATH } _saveResult(tool, target, resultado) { try { const filename = path.join( this.resultsDir, `${tool}_${target.replace(/[^a-z0-9]/g, '_')}_${Date.now()}.json` ); fs.writeFileSync(filename, JSON.stringify(resultado, null, 2)); console.log(`✅ Resultado salvo: ${filename}`); } catch (e) { console.warn(`⚠️ Erro ao salvar resultado: ${e.message}`); } } /** * ═════════════════════════════════════════════════════════════════════ * 📊 RELATÓRIO COMBINADO * ═════════════════════════════════════════════════════════════════════ */ async generateComprehensiveReport(target) { try { console.log(`\n📊 Gerando relatório completo para: ${target}\n`); const relatorio = { alvo: target, dataInicio: new Date().toISOString(), ferramentas: {}, resumo: {}, recomendacoes: [] }; // 1. NMAP console.log('1️⃣ Executando NMAP...'); try { const nmapResult = await this.nmapScan(target, '-sV -A'); relatorio.ferramentas.nmap = nmapResult; } catch (e) { relatorio.ferramentas.nmap = { erro: e.message }; } // 2. MASSCAN (mais rápido) console.log('2️⃣ Executando Masscan...'); try { const masscanResult = await this.masscanScan(target, '1-10000'); relatorio.ferramentas.masscan = masscanResult; } catch (e) { relatorio.ferramentas.masscan = { erro: e.message }; } relatorio.dataFim = new Date().toISOString(); relatorio.resumo = this._generateSummary(relatorio); console.log('\n✅ Relatório Completo Gerado!\n'); return relatorio; } catch (e) { console.error('Erro ao gerar relatório:', e); return { erro: e.message, alvo: target }; } } _generateSummary(relatorio) { const ferramentas = relatorio.ferramentas || {}; const sucessos = Object.values(ferramentas).filter(f => f && f.sucesso).length; let totalVulns = 0; for (const ferramenta of Object.values(ferramentas)) { if (ferramenta && ferramenta.vulnerabilidades && Array.isArray(ferramenta.vulnerabilidades)) { totalVulns += ferramenta.vulnerabilidades.length; } } return { totalFerramentas: Object.keys(ferramentas).length, sucessos: sucessos, vulnerabilidades: totalVulns }; } } module.exports = AdvancedPentestingToolkit;