"Você pode escolher continuar testando JavaScript de forma fragmentada e inconsistente, ou pode escolher seguir este caminho estruturado que transformará você em um especialista completo. A jornada começa agora."
Este MANUAL foi projetado como uma jornada progressiva de aprendizado. Cada parte constrói sobre a anterior, mas você também pode usá-lo como referência rápida durante pentests reais.
INICIANTE COMPLETO
- Leia Parte I (Fundamentos) completamente
- Pratique Parte II (Técnicas Básicas) com laboratórios
- Complete pelo menos 2 cenários do Parte VI (Laboratório Prático)
- Avance gradualmente pelas outras partes
PROFISSIONAL EXPERIENTE
- Revise rapidamente Parte I para alinhar terminologia
- Foque em Parte III (Técnicas Avançadas) e Parte IV (Especialização)
- Use Parte V (Maestria) como referência para cenários complexos
CONSULTA DURANTE PENTEST
- Use os Apêndices para checklists rápidos
- Consulte capítulos específicos conforme necessário
- Siga as Quick Reference Cards do Apêndice A
- Leitura completa: 12-15 horas
- Prática incluída: 25-30 horas
- Maestria: 50+ horas de experiência prática
- Capítulo 1: Por que JavaScript é Crítico em Security Testing
- Capítulo 2: Mindset e Ética do Ethical Hacker JavaScript
- Capítulo 3: Ambiente de Trabalho e Ferramentas Essenciais
- Capítulo 4: Metodologia e Processo de Análise
- Capítulo 5: Descoberta de Parâmetros e Assets Ocultos
- Capítulo 6: Análise Básica de Arquivos JavaScript
- Capítulo 7: Identificação de Vulnerabilidades Comuns
- Capítulo 8: Documentação e Relatórios Profissionais
- Capítulo 9: Reconhecimento Avançado e Inteligência
- Capítulo 10: Análise de Frameworks Específicos
- Capítulo 11: Reverse Engineering e Deofuscation
- Capítulo 12: Automação e Desenvolvimento de Scripts
- Capítulo 13: Aplicações Web Modernas (SPAs, PWAs)
- Capítulo 14: APIs e Microserviços
- Capítulo 15: Mobile e Aplicações Híbridas
- Capítulo 16: Análise Forense de Incidentes JavaScript
- Capítulo 17: Metodologias Avançadas de Teste
- Capítulo 18: Cenários Complexos e Edge Cases
- Capítulo 19: Zero-day Research e Vulnerability Discovery
- Capítulo 20: Liderando Assessments de Segurança JavaScript
- Capítulo 21: Laboratório Iniciante - E-commerce Vulnerável
- Capítulo 22: Laboratório Intermediário - Banking Application
- Capítulo 23: Laboratório Avançado - Zero-day Hunting
- Capítulo 24: Projetos Reais e Case Studies
- Apêndice A: Quick Reference Cards
- Apêndice B: Checklists e Templates
- Apêndice C: Ferramentas e Recursos
- Apêndice D: Referências Legais e Éticas
Antes de mergulhar em técnicas, você precisa entender completamente por que JavaScript é tão importante na segurança moderna e como ele se tornou uma superfície de ataque crítica.
JavaScript não é mais apenas "uma linguagem de script do navegador". Ele se tornou o coração pulsante da aplicação web moderna:
ESTATÍSTICAS QUE IMPORTAM:
- 98% das aplicações web usam JavaScript no client-side
- JavaScript representa 65% das vulnerabilidades web em aplicações modernas
- Tempo médio para explorar uma vulnerabilidade JavaScript: 2.3 horas
- Impacto médio de uma vulnerabilidade JS crítica: $3.86 milhões por breach
// O JavaScript moderno está em TODOS os lugares
const javascriptEverywhere = {
// Client-side (tradicional)
browser: {
dom: "Manipulação direta do DOM",
storage: "localStorage, sessionStorage, IndexedDB",
communication: "WebSockets, Server-Sent Events",
workers: "Service Workers, Web Workers"
},
// Server-side (Node.js)
server: {
apis: "APIs REST e GraphQL",
microservices: "Arquiterura distribuída",
database: "Queries e conexões diretas",
authentication: "JWT, OAuth, sessões"
},
// Mobile (Híbrido)
mobile: {
cordova: "Aplicações híbridas",
reactNative: "Apps nativos em JavaScript",
ionic: "Cross-platform development"
},
// Desktop (Electron)
desktop: {
electron: "Apps desktop em JavaScript",
systemAccess: "Acesso ao sistema operacional",
fileSystem: "Manipulação de arquivos"
}
};1. ACESSO PRIVILEGIADO
// JavaScript tem acesso a:
const privilegedAccess = {
userSession: "Cookies, tokens, dados de sessão",
personalData: "Informações pessoais e financeiras",
businessLogic: "Regras de negócio e validações",
systemResources: "APIs do sistema, rede, arquivos"
};2. CONFIANÇA IMPLÍCITA
- Usuários confiam no JavaScript "porque vem da aplicação"
- Desenvolvedores assumem que JavaScript client-side é "seguro"
- Organizações não auditam adequadamente código JavaScript
3. COMPLEXIDADE CRESCENTE
- Aplicações SPA (Single Page Application) com milhares de linhas JS
- Dependências de terceiros não auditadas
- Frameworks complexos com superfície de ataque ampla
class EthicalJavaScriptHacker {
constructor() {
this.mindset = {
// Tudo é superfície de ataque até prova em contrário
trustNothing: "Validar todas as suposições",
// JavaScript executa com privilégios do usuário
privilegeAwareness: "Entender contexto de execução",
// Lado client e server são igualmente importantes
fullStack: "Analisar toda a cadeia de execução",
// Negócio sempre vem primeiro
businessFirst: "Impacto no negócio define prioridades"
};
}
analyze(target) {
return {
surface: this.mapAttackSurface(target),
risks: this.assessBusinessRisks(target),
impact: this.calculateRealWorldImpact(target),
recommendations: this.prioritizeByBusiness(target)
};
}
}FUNDAMENTO 1: Execution Context Security
// Entender onde e como o JavaScript executa
const executionContexts = {
browserMainThread: {
privileges: "DOM access, storage, network",
restrictions: "Same-origin policy, CSP",
attacks: ["XSS", "CSRF", "Clickjacking"]
},
serviceWorker: {
privileges: "Background processing, caching, push",
restrictions: "Limited DOM access",
attacks: ["Cache poisoning", "Background persistence"]
},
nodeJSServer: {
privileges: "File system, network, databases",
restrictions: "OS-level permissions",
attacks: ["Code injection", "Path traversal", "Deserialization"]
}
};Não é apenas conhecimento técnico. É a combinação de:
COMPETÊNCIA TÉCNICA + ÉTICA INABALÁVEL + MINDSET DE PROTETOR
class EthicalJavaScriptTester {
constructor() {
this.ethicalPrinciples = {
// SEMPRE proteger, nunca prejudicar
primaryObjective: "PROTECT_AND_SECURE",
// Autorização SEMPRE vem primeiro
authorization: {
written: "Autorização escrita obrigatória",
scope: "Testar apenas o que foi autorizado",
emergency: "Protocolo de emergência definido"
},
// Responsabilidade total pelas ações
accountability: {
logging: "Documentar todas as ações",
disclosure: "Seguir responsible disclosure",
transparency: "Ser transparente sobre métodos"
}
};
}
validateEthicalCompliance(action) {
const checks = [
this.hasWrittenAuthorization(action),
this.isWithinScope(action),
this.willNotCauseDamage(action),
this.followsResponsibleDisclosure(action)
];
return checks.every(check => check === true);
}
}MENTAL MODEL 1: O Ciclo OODA para Security Testing
Observe → Orient → Decide → Act
↑ ↓
←←←←← Learn & Adapt ←←←←←
APLICAÇÃO PRÁTICA:
- Observe: "O que vejo no código JavaScript?"
- Orient: "O que isso significa para segurança?"
- Decide: "Que teste devo executar?"
- Act: "Como executo de forma ética e segura?"
MENTAL MODEL 2: Árvore de Decisão Ética
Tenho autorização? ──┬── NÃO → PARAR IMEDIATAMENTE
└── SIM → Continuar
Está no escopo? ─────┬── NÃO → Confirmar com stakeholder
└── SIM → Continuar
Pode causar dano? ───┬── SIM → Buscar método mais seguro
└── NÃO → Executar com documentação
VOCÊ NÃO É UM ATACANTE. VOCÊ É UM PROTETOR.
const protectorMindset = {
// Sua motivação principal
motivation: "Tornar sistemas mais seguros",
// Sua abordagem
approach: {
constructive: "Focar em soluções, não apenas problemas",
educational: "Ensinar e capacitar times de desenvolvimento",
collaborative: "Trabalhar COM a equipe, não CONTRA",
preventive: "Antecipar problemas futuros"
},
// Seu objetivo final
success: "Quando o sistema está mais seguro depois do seu trabalho"
};FAIL SECURELY
// Se algo der errado durante o teste, falhe de forma segura
try {
const testResult = executeSecurityTest(target);
return testResult;
} catch (error) {
// NUNCA deixe o sistema em estado vulnerável
this.cleanupTestArtifacts();
this.logError(error);
throw new SafeTestError("Test failed securely");
}LEAST PRIVILEGE
// Use apenas as permissões mínimas necessárias
const testingScope = {
readOnly: "Quando possível, apenas leia dados",
isolatedEnvironment: "Prefira ambientes de teste",
minimalImpact: "Minimize impacto nos sistemas",
cleanAfter: "Limpe tudo após os testes"
};Seu ambiente é sua arma. Um ambiente mal configurado pode:
- Causar falsos positivos
- Perder vulnerabilidades reais
- Violar escopo autorizado
- Causar danos não intencionais
graph TB
A[Ambiente Físico Isolado] --> B[VM/Container Testing]
B --> C[Proxy/Interceptor Layer]
C --> D[Target Application]
A --> E[Backup & Recovery]
A --> F[Monitoring & Logging]
subgraph "Ferramentas Essenciais"
G[Burp Suite Professional]
H[Browser DevTools]
I[Static Analysis Tools]
J[Custom Scripts]
end
C --> G
C --> H
B --> I
B --> J
INTERCEPTAÇÃO E PROXY
const proxyTools = {
burpSuite: {
purpose: "Interceptação HTTP/HTTPS completa",
strengths: "Extensibility, repeatability, collaboration",
cost: "Profissional (~$400/ano)",
essential: true
},
owasp_zap: {
purpose: "Proxy gratuito com automação",
strengths: "Open source, CI/CD integration",
cost: "Gratuito",
essential: "Para orçamentos limitados"
},
mitmproxy: {
purpose: "Proxy programável",
strengths: "Scripting, automation, lightweight",
cost: "Gratuito",
essential: "Para automação avançada"
}
};ANÁLISE ESTÁTICA
#!/bin/bash
# Setup de ferramentas de análise estática JavaScript
# ESLint com regras de segurança
npm install -g eslint
npm install -g eslint-plugin-security
# Semgrep (análise semântica)
python3 -m pip install semgrep
# RetireJS (vulnerabilidades em dependências)
npm install -g retire
# JSHint (análise de código)
npm install -g jshint
echo "Ferramentas de análise estática configuradas!"BROWSER SETUP PROFISSIONAL
// Configuração browser para testing
const browserSetup = {
// Chrome/Chromium para testing
chrome: {
proxy: "127.0.0.1:8080", // Burp proxy
disableSecurity: "--disable-web-security --disable-features=VizDisplayCompositor",
extensions: [
"Wappalyzer", // Tech stack identification
"EditThisCookie", // Cookie manipulation
"User-Agent Switcher", // Request modification
"React Developer Tools", // Framework analysis
"Vue.js devtools" // Framework analysis
]
},
// Firefox para testes alternativos
firefox: {
proxy: "Manual proxy configuration",
addons: [
"HackBar", // Manual testing
"FoxyProxy", // Proxy management"
]
}
};# Estrutura recomendada para projetos de security testing
mkdir -p js-security-project/{
reconnaissance/{assets,endpoints,configs},
vulnerabilities/{xss,injection,logic},
exploits/{pocs,payloads},
reports/{findings,evidence,recommendations},
tools/{custom,configs},
logs/{traffic,analysis,errors}
}
# Template de documentação
touch js-security-project/README.md
touch js-security-project/SCOPE.md
touch js-security-project/METHODOLOGY.md# docker-compose.yml para ambiente isolado
version: '3.8'
services:
# Aplicação alvo vulnerável para prática
vulnerable-js-app:
image: vulnerables/web-dvwa
ports:
- "3000:80"
networks:
- isolated-lab
# Proxy/interceptor
burp-proxy:
image: portswigger/burp-suite
ports:
- "8080:8080"
networks:
- isolated-lab
# Análise estática
static-analysis:
image: returntocorp/semgrep
volumes:
- ./target-code:/src
networks:
- isolated-lab
networks:
isolated-lab:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16#!/bin/bash
# Script de validação do ambiente de testing
echo "🔧 Validando ambiente JavaScript Security Testing..."
# Verificar conectividade proxy
curl -x http://127.0.0.1:8080 http://httpbin.org/ip 2>/dev/null
if [ $? -eq 0 ]; then
echo "✅ Proxy funcionando corretamente"
else
echo "❌ Problema com proxy - verificar configuração"
fi
# Verificar ferramentas estáticas
command -v eslint >/dev/null && echo "✅ ESLint instalado" || echo "❌ ESLint não encontrado"
command -v semgrep >/dev/null && echo "✅ Semgrep instalado" || echo "❌ Semgrep não encontrado"
command -v retire >/dev/null && echo "✅ RetireJS instalado" || echo "❌ RetireJS não encontrado"
# Verificar isolamento de rede
ping -c 1 8.8.8.8 >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "✅ Ambiente isolado corretamente"
else
echo "⚠️ Ambiente tem acesso à internet - verificar isolamento"
fi
echo "🎯 Validação completa!"S - Scouting (Reconhecimento)
E - Enumeration (Enumeração)
C - Classification (Classificação)
U - Understanding (Compreensão)
R - Risk Assessment (Avaliação de Risco)
E - Execution (Execução de Testes)
class JavaScriptSecurityMethodology {
async executeFullAssessment(target) {
const assessment = {
// Fase 1: SCOUTING (15-20% do tempo)
scouting: await this.performReconnaissance(target),
// Fase 2: ENUMERATION (20-25% do tempo)
enumeration: await this.enumerateAssets(target),
// Fase 3: CLASSIFICATION (15-20% do tempo)
classification: await this.classifyFindings(target),
// Fase 4: UNDERSTANDING (20-25% do tempo)
understanding: await this.analyzeBusinessLogic(target),
// Fase 5: RISK ASSESSMENT (10-15% do tempo)
riskAssessment: await this.assessRisks(target),
// Fase 6: EXECUTION (10-15% do tempo)
execution: await this.validateVulnerabilities(target)
};
return this.generateComprehensiveReport(assessment);
}
}OBJETIVO: Mapear o terreno antes de avançar
#!/bin/bash
# Script de reconhecimento básico
TARGET_URL="https://target.example.com"
echo "🔍 Iniciando reconhecimento de $TARGET_URL"
# 1. Identificação de tecnologias
curl -s -I $TARGET_URL | grep -E "(Server|X-Powered|X-Framework)"
# 2. Descoberta de assets JavaScript
curl -s $TARGET_URL | grep -oP 'src="[^"]*\.js[^"]*"' | sort -u
# 3. Robots.txt e sitemap
curl -s $TARGET_URL/robots.txt
curl -s $TARGET_URL/sitemap.xml
# 4. Wayback Machine (se permitido)
curl -s "http://web.archive.org/cdx/search/cdx?url=$TARGET_URL&output=json" | head -10// Framework para enumeração sistemática
class AssetEnumerator {
async enumerateJavaScriptAssets(baseUrl) {
const assets = {
// Scripts diretos
inlineScripts: await this.findInlineScripts(baseUrl),
// Arquivos externos
externalScripts: await this.findExternalScripts(baseUrl),
// Source maps
sourceMaps: await this.findSourceMaps(baseUrl),
// Service workers
serviceWorkers: await this.findServiceWorkers(baseUrl),
// WebAssembly modules
wasmModules: await this.findWasmModules(baseUrl)
};
return this.catalogAssets(assets);
}
}const vulnerabilityTaxonomy = {
// Categoria OWASP
inputValidation: {
xss: ["Reflected", "Stored", "DOM-based"],
injection: ["SQL", "NoSQL", "Command", "LDAP"],
deserialization: ["Object", "JSON", "XML"]
},
// Categoria lógica de negócio
businessLogic: {
authentication: ["Bypass", "Enumeration", "Brute force"],
authorization: ["Privilege escalation", "IDOR", "Path traversal"],
workflow: ["Race conditions", "State manipulation"]
},
// Categoria configuração
configuration: {
exposure: ["Source maps", "Debug info", "API keys"],
headers: ["Missing CSP", "CORS misconfiguration"],
dependencies: ["Outdated libraries", "Known CVEs"]
}
};COMPREENDER O NEGÓCIO PRIMEIRO
class BusinessLogicAnalyzer {
analyzeBusinessContext(application) {
return {
// Qual é o propósito da aplicação?
purpose: this.identifyCoreBusiness(application),
// Quais dados são críticos?
criticalData: this.identifyCriticalAssets(application),
// Quais fluxos são importantes?
criticalFlows: this.identifyKeyWorkflows(application),
// Qual é o modelo de ameaças?
threatModel: this.generateThreatModel(application)
};
}
}class RiskCalculator {
calculateRisk(vulnerability, businessContext) {
const impact = this.assessImpact(vulnerability, businessContext);
const likelihood = this.assessLikelihood(vulnerability);
const exploitability = this.assessExploitability(vulnerability);
// Fórmula OWASP Risk Rating
const riskScore = (impact + likelihood) / 2;
return {
score: riskScore,
rating: this.getRiskRating(riskScore),
businessImpact: this.calculateBusinessImpact(impact, businessContext),
recommendations: this.generateRecommendations(vulnerability, riskScore)
};
}
}A descoberta é onde tudo começa. 80% das vulnerabilidades críticas estão escondidas em assets JavaScript que a maioria dos pentesters nunca encontra. Este capítulo ensina as 5 técnicas essenciais que separam iniciantes de profissionais.
Ao final deste capítulo, você será capaz de:
- Descobrir source maps expostos em aplicações production
- Encontrar endpoints de API não documentados no código JavaScript
- Identificar parâmetros ocultos em formulários e requests
- Mapear completamente a superfície de ataque JavaScript
- Automatizar descoberta em escala
O QUE SÃO SOURCE MAPS E POR QUE IMPORTAM
Source maps são arquivos que mapeiam código minificado de volta ao código original. Desenvolvedores frequentemente os deixam expostos em produção, revelando:
- Código fonte completo da aplicação
- Estrutura interna de diretórios
- Comentários com informações sensíveis
- Bibliotecas e dependências não públicas
IMPLEMENTAÇÃO PRÁTICA:
// Automated Source Map Discovery
class SourceMapDiscoverer {
async discoverSourceMaps(baseUrl) {
console.log(`🔍 Buscando source maps em ${baseUrl}`);
// Padrão 1: Comentários no final dos arquivos JS
const jsFiles = await this.findJavaScriptFiles(baseUrl);
const sourceMaps = [];
for (const jsFile of jsFiles) {
const content = await this.fetchFile(jsFile.url);
const sourceMapPattern = /\/\/# sourceMappingURL=(.+)/;
const match = content.match(sourceMapPattern);
if (match) {
const sourceMapUrl = this.resolveUrl(match[1], jsFile.url);
console.log(`📁 Source map encontrado: ${sourceMapUrl}`);
const sourceMapData = await this.analyzeSourceMap(sourceMapUrl);
sourceMaps.push(sourceMapData);
}
}
return sourceMaps;
}
async analyzeSourceMap(sourceMapUrl) {
const sourceMapContent = await this.fetchFile(sourceMapUrl);
const sourceMap = JSON.parse(sourceMapContent);
return {
url: sourceMapUrl,
originalSources: sourceMap.sources || [],
sensitiveFiles: this.identifySensitiveFiles(sourceMap.sources),
secretsFound: this.extractSecrets(sourceMapContent),
riskLevel: this.calculateRisk(sourceMap)
};
}
identifySensitiveFiles(sources) {
const sensitivePatterns = [
/config\.(js|ts)$/i,
/secret/i,
/admin/i,
/test/i,
/debug/i,
/\.env/i
];
return sources.filter(source =>
sensitivePatterns.some(pattern => pattern.test(source))
);
}
}EXEMPLO PRÁTICO REAL:
#!/bin/bash
# Script para descoberta rápida de source maps
TARGET_URL="https://example.com"
echo "🔍 Descobrindo source maps em $TARGET_URL"
# 1. Listar todos os arquivos JavaScript
curl -s "$TARGET_URL" | grep -oP 'src="[^"]*\.js[^"]*"' | sed 's/src="//;s/"//' > js_files.txt
# 2. Verificar source maps em cada arquivo
while IFS= read -r js_file; do
# Resolver URL relativa
full_url="$TARGET_URL/$js_file"
# Buscar comentário de source map
source_map=$(curl -s "$full_url" | grep -oP '//# sourceMappingURL=\K[^\s]+')
if [ -n "$source_map" ]; then
echo "📁 Source map encontrado: $TARGET_URL/$source_map"
# Baixar e analisar source map
curl -s "$TARGET_URL/$source_map" | jq '.sources[]' 2>/dev/null || echo "Erro ao parsear source map"
fi
done < js_files.txtCONCEITO: APIs não documentadas frequentemente estão expostas no código JavaScript client-side.
class APIEndpointDiscoverer {
async discoverAPIEndpoints(codeContent) {
const endpoints = new Set();
// Padrões de descoberta de endpoints
const patterns = [
// Fetch API
/fetch\s*\(\s*["']([^"]+)["']/g,
// XMLHttpRequest
/\.open\s*\(\s*["'](?:GET|POST|PUT|DELETE)["']\s*,\s*["']([^"]+)["']/g,
// Axios
/axios\.(get|post|put|delete|patch)\s*\(\s*["']([^"]+)["']/g,
// jQuery AJAX
/\$\.(?:get|post|ajax)\s*\(\s*["']([^"]+)["']/g,
// URLs em strings
/["'](\/api\/[^"]+)["']/g,
// GraphQL endpoints
/["'](\/graphql[^"]*)["']/g
];
patterns.forEach(pattern => {
let match;
while ((match = pattern.exec(codeContent)) !== null) {
const endpoint = match[1] || match[2];
if (endpoint && this.isValidEndpoint(endpoint)) {
endpoints.add(endpoint);
}
}
});
return Array.from(endpoints);
}
isValidEndpoint(endpoint) {
// Filtrar false positives
const excludePatterns = [
/^https?:\/\/[^\/]+\/?$/, // URLs base apenas
/\.(css|png|jpg|gif|ico)$/, // Assets estáticos
/^mailto:/, // Links de email
/^tel:/ // Links de telefone
];
return !excludePatterns.some(pattern => pattern.test(endpoint));
}
}
// Uso prático
const discoverer = new APIEndpointDiscoverer();
const jsContent = await fetch('/app.js').then(r => r.text());
const endpoints = await discoverer.discoverAPIEndpoints(jsContent);
console.log('🛣️ Endpoints descobertos:', endpoints);CONCEITO: Formulários e requests frequentemente têm parâmetros ocultos ou comentados que podem ser explorados.
class HiddenParameterDiscoverer {
discoverHiddenParameters(htmlContent, jsContent) {
const parameters = new Set();
// 1. Inputs ocultos em HTML
const hiddenInputs = htmlContent.match(/<input[^>]*type=["']hidden["'][^>]*>/g) || [];
hiddenInputs.forEach(input => {
const nameMatch = input.match(/name=["']([^"]+)["']/);
if (nameMatch) {
parameters.add({
name: nameMatch[1],
type: 'hidden_input',
context: input
});
}
});
// 2. Parâmetros em JavaScript
const jsPatterns = [
// Objetos de dados
/data\s*:\s*\{([^}]+)\}/g,
// Parâmetros de URL
/[?&]([^=&\s]+)=/g,
// FormData append
/\.append\s*\(\s*["']([^"]+)["']/g,
// Parâmetros comentados
/\/\/.*["']([^"]+)["']\s*:\s*["'][^"]*["']/g
];
jsPatterns.forEach(pattern => {
let match;
while ((match = pattern.exec(jsContent)) !== null) {
parameters.add({
name: match[1],
type: 'javascript_parameter',
context: match[0]
});
}
});
return Array.from(parameters);
}
}CONCEITO: Crawlers tradicionais podem perder assets dinamicamente carregados ou referenciados de forma não óbvia. Um crawler inteligente analisa o conteúdo da página (HTML, CSS, JS) para extrair URLs e paths adicionais.
IMPLEMENTAÇÃO PRÁTICA:
class IntelligentCrawler {
constructor(baseUrl) {
this.baseUrl = baseUrl;
this.discovered = new Set();
this.queue = [baseUrl];
this.maxDepth = 3; // Limite de profundidade para evitar loops infinitos
}
async crawlForAssets() {
while (this.queue.length > 0) {
const currentUrl = this.queue.shift();
if (this.discovered.has(currentUrl)) continue;
this.discovered.add(currentUrl);
console.log(`🕷️ Crawling: ${currentUrl}`);
try {
const content = await this.fetchContent(currentUrl);
const assets = this.extractAssets(content);
// Adicionar novos assets à queue
assets.forEach(asset => {
const fullUrl = this.resolveUrl(asset, currentUrl);
if (!this.discovered.has(fullUrl)) {
this.queue.push(fullUrl);
}
});
} catch (error) {
console.warn(`❌ Erro ao acessar ${currentUrl}:`, error.message);
}
}
return Array.from(this.discovered);
}
async fetchContent(url) {
// Implementação simplificada para fins de exemplo
// Em um ambiente real, usaria uma biblioteca HTTP robusta
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.text();
}
resolveUrl(path, baseUrl) {
try {
return new URL(path, baseUrl).href;
} catch (e) {
return null; // Lidar com URLs inválidas
}
}
extractAssets(content) {
const assets = [];
// JavaScript files
const jsMatches = content.match(/src=["']([^"]*\.js[^"]*)["']/g) || [];
assets.push(...jsMatches.map(m => m.match(/src=["']([^"]+)["']/)[1]));
// CSS files
const cssMatches = content.match(/href=["']([^"]*\.css[^"]*)["']/g) || [];
assets.push(...cssMatches.map(m => m.match(/href=["']([^"]+)["']/)[1]));
// Links internos
const linkMatches = content.match(/href=["']([^"]*)["']/g) || [];
assets.push(...linkMatches
.map(m => m.match(/href=["']([^"]+)["']/)[1])
.filter(link => this.isInternalLink(link))
);
return assets;
}
isInternalLink(link) {
// Verifica se o link é interno ao domínio base
try {
const url = new URL(link, this.baseUrl);
return url.hostname === new URL(this.baseUrl).hostname;
} catch (e) {
return false;
}
}
}CONCEITO: Service Workers são scripts JavaScript que o navegador executa em segundo plano, separados da página web. Eles podem interceptar requisições de rede, gerenciar caches e até mesmo enviar notificações push. Sua lógica pode conter vulnerabilidades como cache poisoning, bypass de segurança ou exposição de dados sensíveis.
IMPLEMENTAÇÃO PRÁTICA:
class ServiceWorkerAnalyzer {
async discoverServiceWorkers(baseUrl) {
console.log('🔍 Buscando Service Workers...');
// 1. Verificar manifest.json (indicador de PWA e possível SW)
try {
const manifestUrl = new URL('/manifest.json', baseUrl).href;
const manifest = await fetch(manifestUrl).then(r => r.json());
if (manifest.start_url || manifest.scope) {
console.log('📱 PWA detectado via manifest.json');
}
} catch (e) {
// Manifest não encontrado ou erro de parse
}
// 2. Verificar registros de service worker em arquivos JS
// (Reutiliza a lógica de descoberta de JS files do Capítulo 5)
const jsFiles = await this.findJavaScriptFiles(baseUrl); // Supondo que esta função existe
const serviceWorkers = [];
for (const jsFile of jsFiles) {
const content = await fetch(jsFile).then(r => r.text());
// Procurar registros de service worker
const swRegistrations = content.match(/navigator\.serviceWorker\.register\(["']([^"]+)["']/g) || [];
for (const registration of swRegistrations) {
const swPath = registration.match(/register\(["']([^"]+)["']/)[1];
const swUrl = new URL(swPath, baseUrl).href;
console.log(`👷 Service Worker encontrado: ${swUrl}`);
const swContent = await fetch(swUrl).then(r => r.text());
const analysis = await this.analyzeServiceWorker(swContent);
serviceWorkers.push({
url: swUrl,
analysis: analysis
});
}
}
return serviceWorkers;
}
async analyzeServiceWorker(swContent) {
return {
// Cache strategies: Como o SW gerencia o cache (e.g., cache-first, network-first)
cacheStrategies: this.extractCacheStrategies(swContent),
// Network requests: Padrões de requisições interceptadas e manipuladas
networkRequests: this.extractNetworkRequests(swContent),
// Event listeners: Eventos que o SW escuta (fetch, install, activate, push)
eventListeners: this.extractEventListeners(swContent),
// Potential vulnerabilities: Lógica insegura (e.g., cache de dados sensíveis, bypass de CORS)
vulnerabilities: this.identifyVulnerabilities(swContent)
};
}
extractCacheStrategies(content) {
const strategies = [];
if (content.includes('cache.put') && content.includes('fetch')) {
strategies.push('Cache-First or Network-First');
}
if (content.includes('self.addEventListener(\'fetch\',')) {
strategies.push('Fetch Interception');
}
return strategies;
}
extractNetworkRequests(content) {
const requests = [];
const fetchMatches = content.match(/fetch\s*\(\s*["']([^"]+)["']/g) || [];
requests.push(...fetchMatches.map(m => m.match(/fetch\s*\(\s*["']([^"]+)["']/)[1]));
return requests;
}
extractEventListeners(content) {
const listeners = [];
const listenerMatches = content.match(/self\.addEventListener\(["']([^"']+)["']/g) || [];
listeners.push(...listenerMatches.map(m => m.match(/self\.addEventListener\(["']([^"']+)["']/)[1]));
return listeners;
}
identifyVulnerabilities(content) {
const vulns = [];
if (content.includes('cache.put') && content.includes('response.clone()') && !content.includes('no-store')) {
vulns.push('Potential Cache Poisoning');
}
if (content.includes('postMessage') && !content.includes('event.origin')) {
vulns.push('Insecure postMessage usage');
}
return vulns;
}
}#!/bin/bash
# Descoberta automatizada completa de JavaScript assets
TARGET_URL="$1"
OUTPUT_DIR="js_discovery_$(date +%Y%m%d_%H%M%S)"
if [ -z "$TARGET_URL" ]; then
echo "Uso: $0 <URL_ALVO>"
exit 1
fi
echo "🎯 Iniciando descoberta completa em: $TARGET_URL"
mkdir -p "$OUTPUT_DIR"
# 1. Source Maps
echo "📁 Descobrindo Source Maps..."
curl -s "$TARGET_URL" | grep -oP 'src="[^"]*\.js[^"]*"' | while read -r js_file; do
js_url="${TARGET_URL}${js_file//src=\"/}"
js_url="${js_url//\"/}"
source_map=$(curl -s "$js_url" 2>/dev/null | tail -1 | grep -oP '//# sourceMappingURL=\K[^\s]+')
if [ -n "$source_map" ]; then
echo "Found: $js_url -> $source_map" >> "$OUTPUT_DIR/source_maps.txt"
fi
done
# 2. API Endpoints
echo "🛣️ Descobrindo API Endpoints..."
curl -s "$TARGET_URL" | grep -oP 'src="[^"]*\.js[^"]*"' | while read -r js_file; do
js_url="${TARGET_URL}${js_file//src=\"/}"
js_url="${js_url//\"/}"
curl -s "$js_url" 2>/dev/null | grep -oP "(fetch\s*\(\s*['\"][^'\"]+['\"]|\.open\s*\([^)]*['\"][^'\"]+['\"])" >> "$OUTPUT_DIR/api_endpoints.txt"
done
# 3. Service Workers
echo "👷 Descobrindo Service Workers..."
curl -s "$TARGET_URL" | grep -oP "navigator\.serviceWorker\.register\(['\"][^'\"]+['\"]" | grep -oP "['\"][^'\"]+['\"]" >> "$OUTPUT_DIR/service_workers.txt"
# 4. Gerar relatório
echo "📊 Gerando relatório..."
cat > "$OUTPUT_DIR/report.md" << EOF
# JavaScript Discovery Report
**Target**: $TARGET_URL
**Date**: $(date)
## Source Maps Found
\`\`\`
$(cat "$OUTPUT_DIR/source_maps.txt" 2>/dev/null || echo "None found")
\`\`\`
## API Endpoints Found
\`\`\`
$(cat "$OUTPUT_DIR/api_endpoints.txt" 2>/dev/null || echo "None found")
\`\`\`
## Service Workers Found
\`\`\`
$(cat "$OUTPUT_DIR/service_workers.txt" 2>/dev/null || echo "None found")
\`\`\`
EOF
echo "✅ Descoberta completa! Resultados em: $OUTPUT_DIR/"FALSOS POSITIVOS COMUNS:
- URLs de CDNs externos (filtrar por domínio)
- Paths de assets estáticos (CSS, imagens)
- URLs de exemplo em comentários
- Template strings não resolvidas
OTIMIZAÇÃO DE PERFORMANCE:
- Use conexões paralelas com limite
- Implemente cache local
- Configure timeouts apropriados
- Monitore uso de memória
Uma vez que você descobriu os assets JavaScript (Capítulo 5), o próximo passo é analisá-los sistematicamente. Este capítulo ensina como ler código JavaScript como um hacker ético - identificando padrões inseguros, lógica de negócio vulnerável e pontos de entrada para ataques.
class JavaScriptCodeAnalyzer {
analyzeFile(jsContent, fileUrl) {
return {
// Análise estática básica
staticAnalysis: this.performStaticAnalysis(jsContent),
// Identificação de padrões perigosos
securityPatterns: this.identifySecurityPatterns(jsContent),
// Análise de fluxo de dados
dataFlow: this.analyzeDataFlow(jsContent),
// Identificação de secrets e configurações
secrets: this.extractSecrets(jsContent),
// Avaliação de complexidade e manutenibilidade
codeQuality: this.assessCodeQuality(jsContent)
};
}
}IDENTIFIQUE IMEDIATAMENTE ESTES PADRÕES:
class SecurityPatternDetector {
identifyDangerousPatterns(code) {
const patterns = {
// Execução de código dinâmico
codeExecution: [
/eval\s*\(/g,
/Function\s*\(/g,
/setTimeout\s*\(\s*["'][^"']*["']/g,
/setInterval\s*\(\s*["'][^"']*["']/g
],
// Manipulação DOM perigosa
domManipulation: [
/innerHTML\s*=\s*[^;]+/g,
/outerHTML\s*=\s*[^;]+/g,
/document\.write\s*\(/g,
/insertAdjacentHTML\s*\(/g
],
// Validação de input inadequada
inputValidation: [
/req\.query\.[^;\s]+/g,
/req\.body\.[^;\s]+/g,
/window\.location\.[^;\s]+/g,
/document\.referrer/g
],
// Gerenciamento de sessão
sessionHandling: [
/localStorage\.(setItem|getItem)/g,
/sessionStorage\.(setItem|getItem)/g,
/document\.cookie/g,
/jwt\.|JSON\.parse\(/g
]
};
const findings = {};
Object.entries(patterns).forEach(([category, regexList]) => {
findings[category] = [];
regexList.forEach(regex => {
let match;
while ((match = regex.exec(code)) !== null) {
findings[category].push({
match: match[0],
line: this.getLineNumber(code, match.index),
context: this.getContext(code, match.index, 50)
});
}
});
});
return findings;
}
getLineNumber(code, index) {
return code.substring(0, index).split('\n').length;
}
getContext(code, index, length) {
const start = Math.max(0, index - length);
const end = Math.min(code.length, index + length);
return code.substring(start, end);
}
}CONCEITO: Rastrear como dados não confiáveis fluem pela aplicação até pontos perigosos. Isso é crucial para identificar vulnerabilidades como XSS, injeção de comandos e outras falhas de injeção.
IMPLEMENTAÇÃO PRÁTICA:
class DataFlowAnalyzer {
traceDataFlow(code) {
const sources = this.identifyDataSources(code);
const sinks = this.identifyDataSinks(code);
const flows = [];
// Tentar conectar sources com sinks
sources.forEach(source => {
sinks.forEach(sink => {
// Simplificação: Em um analisador real, isso seria um grafo de fluxo de dados
// Aqui, apenas verificamos se o texto da fonte aparece perto do sink
const pathExists = code.substring(source.index, sink.index).includes(source.match);
if (pathExists) {
flows.push({
source: source,
sink: sink,
path: 'Direct flow (simplified)',
riskLevel: this.assessFlowRisk(source, sink)
});
}
});
});
return flows;
}
identifyDataSources(code) {
// Fontes de dados não confiáveis (controladas pelo usuário ou externas)
const sourcePatterns = [
// URL parameters
{ pattern: /window\.location\.(search|hash|href)/g, type: 'url_param', risk: 'HIGH' },
{ pattern: /URLSearchParams/g, type: 'url_param', risk: 'HIGH' },
// User input
{ pattern: /document\.forms\[[^\]]+\]/g, type: 'form_input', risk: 'MEDIUM' },
{ pattern: /\.value\s*$/g, type: 'input_value', risk: 'MEDIUM' },
// External data (e.g., de APIs)
{ pattern: /fetch\s*\(/g, type: 'api_response', risk: 'MEDIUM' },
{ pattern: /XMLHttpRequest/g, type: 'xhr_response', risk: 'MEDIUM' },
// Storage (pode ser manipulado via XSS)
{ pattern: /localStorage\.getItem/g, type: 'local_storage', risk: 'LOW' },
{ pattern: /sessionStorage\.getItem/g, type: 'session_storage', risk: 'LOW' }
];
return this.extractMatches(code, sourcePatterns);
}
identifyDataSinks(code) {
// Pontos onde dados podem causar impacto (execução de código, manipulação DOM)
const sinkPatterns = [
// Code execution
{ pattern: /eval\s*\(/g, type: 'eval', risk: 'CRITICAL' },
{ pattern: /Function\s*\(/g, type: 'function_constructor', risk: 'CRITICAL' },
// DOM manipulation
{ pattern: /innerHTML\s*=/g, type: 'inner_html', risk: 'HIGH' },
{ pattern: /outerHTML\s*=/g, type: 'outer_html', risk: 'HIGH' },
{ pattern: /document\.write/g, type: 'document_write', risk: 'HIGH' },
// Navigation (redirecionamento malicioso)
{ pattern: /location\.(href|assign|replace)/g, type: 'navigation', risk: 'MEDIUM' },
{ pattern: /window\.open/g, type: 'popup', risk: 'MEDIUM' }
];
return this.extractMatches(code, sinkPatterns);
}
extractMatches(code, patterns) {
const matches = [];
patterns.forEach(({ pattern, type, risk }) => {
let match;
while ((match = pattern.exec(code)) !== null) {
matches.push({
match: match[0],
index: match.index,
type: type,
risk: risk,
line: this.getLineNumber(code, match.index),
context: this.getContext(code, match.index, 50)
});
}
});
return matches;
}
assessFlowRisk(source, sink) {
// Lógica para combinar riscos da fonte e do sink
const riskOrder = { 'LOW': 1, 'MEDIUM': 2, 'HIGH': 3, 'CRITICAL': 4 };
if (riskOrder[sink.risk] > riskOrder[source.risk]) {
return sink.risk;
} else {
return source.risk;
}
}
getLineNumber(code, index) {
return code.substring(0, index).split('\n').length;
}
getContext(code, index, length) {
const start = Math.max(0, index - length);
const end = Math.min(code.length, index + length);
return code.substring(start, end);
}
}CONCEITO: Credenciais, chaves de API, tokens e outras informações sensíveis são frequentemente codificadas diretamente em arquivos JavaScript, seja por erro ou por conveniência. Identificar e validar esses secrets é uma prioridade.
IMPLEMENTAÇÃO PRÁTICA:
class SecretsExtractor {
extractSecrets(code) {
const secretPatterns = [
// API Keys
{ pattern: /api[_-]?key\s*[:=]\s*["']([a-zA-Z0-9]{20,})["']/gi, type: 'api_key' },
{ pattern: /access[_-]?token\s*[:=]\s*["']([a-zA-Z0-9\-_.]{20,})["']/gi, type: 'access_token' },
// Database credentials
{ pattern: /password\s*[:=]\s*["']([^"]{6,})["']/gi, type: 'password' },
{ pattern: /db[_-]?pass\s*[:=]\s*["']([^"]+)["']/gi, type: 'db_password' },
// JWT tokens (padrão base64.base64.signature)
{ pattern: /["'](eyJ[a-zA-Z0-9\-_]+\.eyJ[a-zA-Z0-9\-_]+\.[a-zA-Z0-9\-_]+)["']/g, type: 'jwt_token' },
// URLs sensíveis (admin panels, internal APIs)
{ pattern: /["'](https?:\/\/[^"']+\/admin[^"]*)["']/gi, type: 'admin_url' },
{ pattern: /["'](https?:\/\/[^"']+\/api\/v?\d*\/[^"']*)["']/gi, type: 'api_url' },
// Chaves de criptografia
{ pattern: /private[_-]?key\s*[:=]\s*["']([^"]{50,})["']/gi, type: 'private_key' },
{ pattern: /secret[_-]?key\s*[:=]\s*["']([a-zA-Z0-9+/]{32,})["']/gi, type: 'secret_key' }
];
const secrets = [];
secretPatterns.forEach(({ pattern, type }) => {
let match;
while ((match = pattern.exec(code)) !== null) {
secrets.push({
type: type,
value: match[1] || match[0], // Captura o grupo ou o match completo
line: this.getLineNumber(code, match.index),
context: this.getContext(code, match.index, 30),
severity: this.assessSecretSeverity(type, match[1])
});
}
});
return secrets;
}
assessSecretSeverity(type, value) {
const severityMap = {
'api_key': 'HIGH',
'access_token': 'HIGH',
'jwt_token': 'MEDIUM',
'password': 'CRITICAL',
'private_key': 'CRITICAL',
'secret_key': 'HIGH',
'admin_url': 'MEDIUM',
'api_url': 'LOW'
};
return severityMap[type] || 'LOW';
}
getLineNumber(code, index) {
return code.substring(0, index).split('\n').length;
}
getContext(code, index, length) {
const start = Math.max(0, index - length);
const end = Math.min(code.length, index + length);
return code.substring(start, end);
}
}CONCEITO: A lógica de negócio implementada no JavaScript client-side pode ser vulnerável a bypasses, manipulação de estado ou escalonamento de privilégios. Entender como a aplicação funciona é crucial para encontrar essas falhas.
IMPLEMENTAÇÃO PRÁTICA:
class BusinessLogicAnalyzer {
analyzeBusinessLogic(code) {
return {
// Autenticação e autorização: Como a aplicação gerencia sessões e permissões
authMechanisms: this.identifyAuthMechanisms(code),
// Validações de entrada: Onde e como os dados são validados (ou não)
inputValidations: this.identifyInputValidations(code),
// Fluxos críticos de negócio: Operações sensíveis (e.g., compra, transferência)
criticalFlows: this.identifyCriticalFlows(code),
// Estados e transições: Como a aplicação gerencia seu estado (e.g., carrinho de compras)
stateManagement: this.analyzeStateManagement(code)
};
}
identifyAuthMechanisms(code) {
const authPatterns = [
// JWT handling
/jwt\.verify\(|jwt\.sign\(/g,
/jsonwebtoken/g,
// Session management
/req\.session\./g,
/express-session/g,
// Authorization headers
/authorization\s*[:=]/gi,
/bearer\s+token/gi,
// Login/logout patterns
/login|logout|authenticate/gi,
// Permission checks (e.g., if (user.isAdmin))
/\.isAdmin|\.hasPermission/g
];
return this.extractMatches(code, authPatterns);
}
identifyInputValidations(code) {
const validationPatterns = [
// Common validation libraries/methods
/validator\.isEmail|validator\.isURL/g,
/\.test\(/g, // Regex validation
/\.length\s*</g, // Length checks
/typeof\s*[^=]+\s*===/g // Type checks
];
return this.extractMatches(code, validationPatterns);
}
identifyCriticalFlows(code) {
const flowPatterns = [
// Payment/transaction
/checkout|payment|transaction|purchase/g,
// User management
/createUser|updateUser|deleteUser|changePassword/g,
// Data export/import
/exportData|importData/g
];
return this.extractMatches(code, flowPatterns);
}
analyzeStateManagement(code) {
const statePatterns = [
// State management libraries (React Context, Redux, Vuex)
/createContext|useReducer|createStore|Vuex\.Store/g,
// Direct state manipulation
/this\.state\.|setState\(/g,
/data\s*:\s*\{/g // Vue.js data properties
];
return this.extractMatches(code, statePatterns);
}
extractMatches(code, patterns) {
const matches = [];
patterns.forEach(({ pattern }) => {
let match;
while ((match = pattern.exec(code)) !== null) {
matches.push({
match: match[0],
line: this.getLineNumber(code, match.index),
context: this.getContext(code, match.index, 50)
});
}
});
return matches;
}
getLineNumber(code, index) {
return code.substring(0, index).split('\n').length;
}
getContext(code, index, length) {
const start = Math.max(0, index - length);
const end = Math.min(code.length, index + length);
return code.substring(start, end);
}
}Este capítulo é o coração da exploração. Você aprenderá a identificar e, mais importante, a explorar as vulnerabilidades mais prevalentes em aplicações JavaScript. Não se trata apenas de teoria, mas de passos práticos para transformar uma falha em um impacto real.
flowchart TB
A["Vulnerabilidades JavaScript"] --> B["Injeção de Código"]
A --> C["Manipulação de Dados"]
A --> D["Lógica de Negócio"]
A --> E["Configuração Insegura"]
B --> B1["Cross-Site Scripting (XSS)"]
B --> B2["Prototype Pollution (injeção)"]
B --> B3["Injeção de Comandos (Node.js)"]
C --> C1["IDOR (Insecure Direct Object Reference)"]
C --> C2["Exposição de Dados Sensíveis"]
D --> D1["Bypass de Autenticação e Autorização"]
D --> D2["Race Conditions"]
E --> E1["Exposição de Source Map"]
E --> E2["Dependências Vulneráveis"]
E --> E3["CORS Misconfiguration"]
CONCEITO: O DOM XSS ocorre quando uma aplicação web escreve dados controlados pelo atacante diretamente no DOM sem sanitização adequada. O payload nunca chega ao servidor; a vulnerabilidade reside inteiramente no lado do cliente.
FONTES (SOURCES) E SINKS:
Para entender o DOM XSS, é crucial conhecer os conceitos de fontes (sources) e sinks:
-
Fontes (Sources): Propriedades ou funções JavaScript que podem ler dados controlados pelo atacante (e.g.,
document.URL,location.href,location.search,location.hash,document.referrer,window.name,localStorage.getItem(),sessionStorage.getItem(),postMessagedata). -
Sinks: Propriedades ou funções JavaScript que podem executar código ou manipular o DOM de forma perigosa, e para onde os dados da fonte são enviados (e.g.,
innerHTML,outerHTML,document.write(),eval(),setTimeout(),setInterval(),script.src,location.href(para redirecionamento JS),jQuery.html()).
METODOLOGIA DE CAÇA AO DOM XSS (PASSO A PASSO):
-
Identifique Fontes Potenciais: Comece procurando no código JavaScript por onde a aplicação lê dados de fontes controláveis pelo usuário. Use as técnicas de análise estática (Capítulo 6) e dinâmica (DevTools, aba
Sources,Console) para isso.// Exemplo de código vulnerável lendo de location.hash const data = location.hash.substring(1); document.getElementById('output').innerHTML = data;
-
Rastreie o Fluxo de Dados: Uma vez que uma fonte é identificada, siga o caminho que os dados percorrem no código. Eles são passados para alguma função de sanitização? Eles são usados em alguma operação perigosa (sink)? Use o depurador das DevTools para seguir o fluxo de execução passo a passo.
-
Identifique Sinks Potenciais: Procure por onde os dados da fonte são escritos no DOM ou executados. Preste atenção especial aos sinks listados acima.
-
Crie um Payload: Com uma fonte e um sink identificados, crie um payload que explore a vulnerabilidade. O payload deve ser projetado para ser injetado na fonte e executado pelo sink.
-
Exemplo para
innerHTML: Selocation.hashé a fonte einnerHTMLé o sink, um payload simples seria:#<img src=x onerror=alert(document.domain)> -
Exemplo para
eval(): Se uma string de query é passada paraeval(), um payload seria:?param=alert(document.domain)
-
-
Teste e Demonstre o Impacto: Injete o payload na fonte e observe o comportamento da aplicação. Demonstre o impacto (e.g., execução de
alert(), roubo de cookies, redirecionamento).
FERRAMENTAS PARA DOM XSS:
- DOM Invader (Burp Suite): Uma extensão poderosa do Burp Suite que automatiza a detecção de DOM XSS, identificando fontes e sinks e permitindo testar payloads diretamente.
- Untrusted Types (Chrome DevTools): Uma funcionalidade experimental no Chrome que ajuda a identificar sinks de
Trusted Typesque podem ser vulneráveis a XSS.
CONCEITO: Prototype Pollution é uma vulnerabilidade que permite a um atacante adicionar ou modificar propriedades de objetos JavaScript através do prototype de um objeto base (Object.prototype). Isso pode levar a uma série de ataques, incluindo execução remota de código (RCE) no servidor (Node.js) ou XSS no cliente.
COMO OCORRE: Geralmente acontece quando funções de mesclagem de objetos (e.g., jQuery.extend(), lodash.merge()) ou operações de desserialização não sanitizam corretamente as chaves de entrada, permitindo que um atacante injete __proto__ ou constructor.prototype na entrada.
METODOLOGIA DE CAÇA AO PROTOTYPE POLLUTION (PASSO A PASSO):
-
Identifique Funções de Mesclagem: Procure no código JavaScript por funções que mesclam objetos ou copiam propriedades de um objeto para outro. Exemplos comuns:
Object.assign()jQuery.extend()lodash.merge()- Funções customizadas que iteram sobre propriedades de objetos.
-
Identifique Fontes de Entrada Controláveis: Onde a aplicação aceita dados do usuário que podem ser usados para poluir o protótipo? (e.g., parâmetros de URL, corpo de requisições JSON, dados de cookies).
-
Crie um Payload de Poluição: O payload básico de poluição de protótipo geralmente se parece com:
- `{
Expandindo sobre a análise estática fundamental, esta seção detalha como realizar uma inspeção aprofundada do código-fonte JavaScript sem executá-lo. O objetivo é identificar informações sensíveis, funcionalidades ocultas, endpoints não documentados e bibliotecas vulneráveis, servindo como a base para a exploração.
Antes de qualquer análise, você precisa do código. Em aplicações web modernas, o JavaScript é frequentemente empacotado e minificado, mas ainda assim é acessível. As principais fontes para coletar esses arquivos são:
-
Ferramentas de Proxy (e.g., Burp Suite, OWASP ZAP): Configure seu navegador para usar um proxy e navegue pela aplicação. O proxy interceptará todas as requisições, incluindo os arquivos
.js. Você pode filtrar o histórico para exportar apenas esses arquivos. No Burp Suite, por exemplo, você pode ir emProxy -> HTTP history, filtrar por.jsna colunaMIME typee então selecionar os arquivos, clicar com o botão direito e escolherSave selected itemsouCopy URLspara usar com ferramentas comowget.# Exemplo de download em massa com wget após copiar as URLs do Burp wget -i urls_javascript.txt -
Ferramentas de Desenvolvedor do Navegador (DevTools): No seu navegador (Chrome, Firefox, etc.), abra as Ferramentas de Desenvolvedor (F12 ou Ctrl+Shift+I). Na aba
Sources(ouOrigens), você pode navegar pela estrutura de arquivos da aplicação e baixar arquivos JavaScript individualmente. Isso é útil para uma inspeção rápida ou para arquivos específicos. -
Crawlers e Scanners: Ferramentas automatizadas podem rastrear a aplicação e identificar todos os arquivos JavaScript referenciados. Ferramentas como
LinkFinderouArjunpodem ajudar a descobrir mais arquivos e endpoints.
Dica: Sempre tente coletar a maior quantidade possível de arquivos JavaScript. Mesmo arquivos pequenos ou aparentemente insignificantes podem conter informações valiosas.
Uma vez que você tem os arquivos JavaScript, o próximo passo é identificar endpoints e parâmetros ocultos. Desenvolvedores frequentemente codificam caminhos de API, URLs e nomes de parâmetros diretamente no JavaScript, que podem não ser visíveis através da interface do usuário. Essas informações podem revelar funcionalidades não documentadas, APIs internas ou até mesmo versões de API antigas e vulneráveis.
Ferramentas Recomendadas:
-
LinkFinder: Esta ferramenta Python é excelente para extrair URLs e endpoints de arquivos JavaScript. Ela pode ser executada em um único arquivo, em um diretório ou até mesmo em URLs ao vivo. O LinkFinder usa expressões regulares para encontrar padrões de URLs e caminhos. [1]
# Exemplo de uso do LinkFinder em um diretório de arquivos JS python linkfinder.py -i 'js/*' -o result.html # Para imprimir os resultados diretamente no terminal e filtrar python linkfinder.py -i 'js/*' -o cli | sort -u | grep 'api'
O
greppode ser usado para refinar os resultados, buscando por palavras-chave comoapi,admin,v1,internal, etc. -
Burp Suite (JS Miner): Para usuários do Burp Suite Professional, a extensão JS Miner é altamente eficaz na detecção passiva de endpoints e segredos à medida que você navega pela aplicação. Os resultados são exibidos no painel de Issues do Burp.
É surpreendentemente comum encontrar credenciais, chaves de API, tokens e outras informações sensíveis diretamente em arquivos JavaScript. Isso ocorre devido a erros de configuração, esquecimento de remover dados de desenvolvimento ou até mesmo a inclusão acidental de arquivos de configuração inteiros.
Ferramentas e Técnicas:
-
TruffleHog: Originalmente focado em repositórios Git, o TruffleHog evoluiu para escanear sistemas de arquivos e outros alvos em busca de segredos de alta entropia e padrões conhecidos. É uma ferramenta poderosa para automatizar a busca por credenciais.
# Exemplo de uso do TruffleHog em um diretório de arquivos JS ./trufflehog filesystem ~/Downloads/js --no-verification --include-detectors="all"
-
grepcom Palavras-Chave: Uma abordagem mais manual, mas ainda muito eficaz, é usar o comandogrepcom uma lista de palavras-chave comuns associadas a segredos. Crie um dicionário de termos e execute ogreprecursivamente nos arquivos JavaScript coletados.# Exemplos de palavras-chave para buscar grep -rE 'password|api_key|secret|token|admin|login|auth|credentials' /path/to/js/files/
-
Análise Manual: Nenhum scanner é perfeito. A análise manual do código-fonte, especialmente de arquivos JavaScript grandes ou complexos, pode revelar segredos que as ferramentas automatizadas perdem. Procure por:
- Variáveis com nomes sugestivos (
API_KEY,SECRET_TOKEN,DB_PASSWORD). - URLs de serviços internos ou de desenvolvimento.
- Comentários de desenvolvedores que podem conter informações sensíveis.
- Dados codificados em Base64 ou outras codificações que podem ser decodificados.
- Variáveis com nomes sugestivos (
Atenção: Sempre valide qualquer segredo encontrado. Um segredo pode ser um placeholder, um valor expirado ou pertencer a um ambiente de desenvolvimento não produtivo. Tente usá-lo em um ambiente controlado para confirmar sua validade e impacto.
Certos métodos e propriedades em JavaScript são conhecidos por serem fontes comuns de vulnerabilidades quando usados incorretamente. Identificar o uso dessas funções no código-fonte pode direcionar sua atenção para áreas onde injeções de código, manipulação do DOM ou vazamento de informações podem ocorrer.
Funções e Propriedades a Observar:
-
Element.innerHTML,Element.outerHTML,document.write,insertAdjacentHTML: Essas propriedades e métodos são frequentemente explorados em ataques de Cross-Site Scripting (XSS) baseado em DOM. Se dados controlados pelo usuário são inseridos diretamente nelas sem sanitização adequada, um atacante pode injetar código HTML ou JavaScript malicioso. -
eval(),Function(),setTimeout(),setInterval(): Funções que executam strings como código JavaScript são extremamente perigosas. Se uma string controlada pelo atacante for passada para essas funções, pode levar à execução remota de código (RCE) no navegador do cliente. -
window.postMessage(): Usado para comunicação entre diferentes origens (cross-origin communication). Vulnerabilidades podem surgir se a origem do remetente não for validada corretamente, permitindo que mensagens maliciosas de um domínio não confiável sejam processadas. -
window.localStorage,window.sessionStorage,document.cookie: Armazenamento de dados no lado do cliente. Informações sensíveis armazenadas aqui podem ser acessadas por ataques de XSS ou outras vulnerabilidades, levando a roubo de sessão ou vazamento de dados. -
location.href,location.assign(),window.open(): Métodos que podem ser manipulados para redirecionar o usuário para sites maliciosos (phishing) ou para executar código JavaScript via esquemas de URL (javascript:).
Ferramentas e Técnicas:
-
Semgrep: Uma ferramenta de análise estática de código que permite definir regras personalizadas para detectar padrões específicos, incluindo o uso de funções perigosas. Você pode criar regras para sinalizar o uso de
innerHTMLsem sanitização ou chamadas aeval().# Exemplo de regra Semgrep para detectar innerHTML sem sanitização rules: - id: dangerous-innerHTML message: "innerHTML is being used, which can lead to XSS if not properly sanitized." severity: WARNING languages: - javascript patterns: - pattern: |- $VAR.innerHTML = $VALUE - pattern-not: - pattern: |- $VAR.innerHTML = sanitize($VALUE) - pattern: |- $VAR.innerHTML = DOMPurify.sanitize($VALUE)
-
Análise Manual e
grep: Novamente, a revisão manual e o uso degrepcom as palavras-chave das funções perigosas são essenciais. Entender o contexto em que essas funções são usadas é crucial para determinar se representam uma vulnerabilidade real.grep -rE ".innerHTML|eval\(|setTimeout\(|setInterval\(|postMessage\(|localStorage|sessionStorage|document.cookie" /path/to/js/files/
Ao identificar o uso dessas funções, você terá pontos de partida claros para a análise dinâmica e para a criação de payloads de exploração. Lembre-se que o uso de uma função perigosa por si só não é uma vulnerabilidade; o contexto e a falta de sanitização ou validação de entrada é que a tornam explorável.
Enquanto a análise estática nos dá uma visão do código-fonte, a análise dinâmica nos permite observar e interagir com o JavaScript enquanto ele está em execução no navegador. Isso é fundamental para entender como a aplicação se comporta, como os dados fluem e como as vulnerabilidades se manifestam em um ambiente real. É aqui que a mágica da exploração acontece.
As DevTools são suas melhores amigas na análise dinâmica. Elas oferecem um conjunto robusto de funcionalidades para inspecionar elementos, monitorar requisições de rede, depurar código JavaScript, manipular o DOM e muito mais. Dominar as DevTools é essencial para qualquer pentester de aplicações web.
Principais Abas e Funcionalidades:
-
Elements (Elementos): Permite inspecionar e modificar o HTML e CSS da página em tempo real. Útil para identificar elementos ocultos, alterar atributos e testar injeções de HTML.
-
Console: Onde você pode executar código JavaScript diretamente no contexto da página, ver logs de erros e mensagens, e interagir com variáveis e funções globais. É seu playground para testar payloads de XSS e manipular o ambiente da aplicação.
-
Sources (Fontes): Para depurar código JavaScript. Você pode definir breakpoints, inspecionar variáveis, e seguir o fluxo de execução do código linha por linha. Isso é inestimável para entender a lógica da aplicação e como ela processa entradas do usuário.
-
Network (Rede): Monitora todas as requisições HTTP/HTTPS feitas pela página. Você pode inspecionar cabeçalhos, corpos de requisição e resposta, e identificar dados sensíveis sendo transmitidos. Essencial para entender a comunicação cliente-servidor e identificar potenciais vulnerabilidades como Insecure Direct Object References (IDOR) ou vazamento de informações.
-
Application (Aplicação): Gerencia o armazenamento local (Local Storage, Session Storage, Cookies, IndexedDB), Service Workers e Manifest. Útil para inspecionar e manipular dados armazenados no lado do cliente, que podem ser explorados em ataques de XSS persistente ou para bypass de autenticação.
Exemplo Prático: Depurando uma Aplicação JavaScript
Imagine que você identificou uma função JavaScript que parece processar entrada do usuário de forma insegura. Usando as DevTools, você pode:
- Definir um Breakpoint: Na aba
Sources, navegue até o arquivo JavaScript relevante e clique na linha de código onde a função perigosa é chamada para definir um breakpoint. - Interagir com a Aplicação: No navegador, execute a ação que aciona essa função (e.g., preencha um formulário, clique em um botão).
- Inspecionar Variáveis: Quando o breakpoint for atingido, a execução do código será pausada. Você pode inspecionar o valor das variáveis, incluindo a entrada do usuário, para ver como ela está sendo tratada antes de ser usada pela função perigosa.
- Modificar em Tempo Real: No
Console, você pode até mesmo modificar o valor de variáveis ou executar partes do código para testar diferentes cenários de ataque.
Essa capacidade de inspecionar e manipular o ambiente de execução em tempo real é o que torna a análise dinâmica tão poderosa para a descoberta e exploração de vulnerabilidades.
Com a análise estática e dinâmica em mãos, é hora de transformar o conhecimento em ação. Esta seção abordará técnicas de exploração de vulnerabilidades comuns em aplicações JavaScript, com foco em como identificar, explorar e demonstrar o impacto dessas falhas.
O XSS baseado em DOM (DOM XSS) ocorre quando uma aplicação web escreve dados controlados pelo atacante diretamente no DOM sem sanitização adequada. Diferente do XSS refletido ou armazenado, o payload nunca chega ao servidor; a vulnerabilidade reside inteiramente no lado do cliente. Isso o torna particularmente insidioso e, muitas vezes, mais difícil de detectar por scanners tradicionais.
Fontes (Sources) e Sinks:
Para entender o DOM XSS, é crucial conhecer os conceitos de fontes (sources) e sinks:
-
Fontes (Sources): São propriedades ou funções JavaScript que podem ler dados controlados pelo atacante. Exemplos comuns incluem
document.URL,location.href,location.search,location.hash,document.referrer,window.name,localStorage.getItem(),sessionStorage.getItem(), e dados de eventospostMessage. -
Sinks: São propriedades ou funções JavaScript que podem executar código ou manipular o DOM de forma perigosa, e para onde os dados da fonte são enviados. Exemplos incluem
innerHTML,outerHTML,document.write(),eval(),setTimeout(),setInterval(),script.src,location.href(quando usado para redirecionamento JavaScript), ejQuery.html().
Metodologia de Caça ao DOM XSS:
-
Identifique Fontes Potenciais: Comece procurando no código JavaScript por onde a aplicação lê dados de fontes controláveis pelo usuário. Use as técnicas de análise estática (
grep, Semgrep) e dinâmica (DevTools, abaSources,Console) para isso.// Exemplo de código vulnerável lendo de location.hash const data = location.hash.substring(1); document.getElementById(\'output\').innerHTML = data;
-
Rastreie o Fluxo de Dados: Uma vez que uma fonte é identificada, siga o caminho que os dados percorrem no código. Eles são passados para alguma função de sanitização? Eles são usados em alguma operação perigosa (sink)? Use o depurador das DevTools para seguir o fluxo de execução passo a passo.
-
Identifique Sinks Potenciais: Procure por onde os dados da fonte são escritos no DOM ou executados. Preste atenção especial aos sinks listados acima.
-
Crie um Payload: Com uma fonte e um sink identificados, crie um payload que explore a vulnerabilidade. O payload deve ser projetado para ser injetado na fonte e executado pelo sink.
-
Exemplo para
innerHTML: Selocation.hashé a fonte einnerHTMLé o sink, um payload simples seria:#<img src=x onerror=alert(document.domain)> -
Exemplo para
eval(): Se uma string de query é passada paraeval(), um payload seria:?param=alert(document.domain)
-
-
Teste e Demonstre o Impacto: Injete o payload na fonte e observe o comportamento da aplicação. Demonstre o impacto (e.g., execução de
alert(), roubo de cookies, redirecionamento).
CONCEITO: Prototype Pollution é uma vulnerabilidade que permite a um atacante adicionar ou modificar propriedades de objetos JavaScript através do prototype de um objeto base (Object.prototype). Isso pode levar a uma série de ataques, incluindo execução remota de código (RCE) no servidor (Node.js) ou XSS no cliente.
COMO OCORRE: Geralmente acontece quando funções de mesclagem de objetos (e.g., jQuery.extend(), lodash.merge()) ou operações de desserialização não sanitizam corretamente as chaves de entrada, permitindo que um atacante injete __proto__ ou constructor.prototype na entrada.
METODOLOGIA DE CAÇA AO PROTOTYPE POLLUTION (PASSO A PASSO):
-
Identifique Funções de Mesclagem: Procure no código JavaScript por funções que mesclam objetos ou copiam propriedades de um objeto para outro. Exemplos comuns:
Object.assign()jQuery.extend()lodash.merge()- Funções customizadas que iteram sobre propriedades de objetos.
-
Identifique Fontes de Entrada Controláveis: Onde a aplicação aceita dados do usuário que podem ser usados para poluir o protótipo? (e.g., parâmetros de URL, corpo de requisições JSON, dados de cookies).
-
Crie um Payload de Poluição: O payload básico de poluição de protótipo geralmente se parece com:
{"__proto__":{"key":"value"}}{"constructor":{"prototype":{"key":"value"}}}
-
Teste e Demonstre o Impacto: Injete o payload e observe o comportamento da aplicação. O impacto pode variar:
- XSS: Se a propriedade injetada for usada em um sink de DOM XSS.
- RCE (Node.js): Se a propriedade injetada puder manipular funções críticas do sistema.
- Bypass de Lógica: Se a propriedade injetada alterar o comportamento de validações ou verificações de segurança.
EXEMPLO PRÁTICO: EXPLORANDO PROTOTYPE POLLUTION PARA XSS
Considere um cenário onde a aplicação usa uma função de mesclagem vulnerável:
function merge(target, source) {
for (let key in source) {
if (key === '__proto__' || key === 'constructor') continue; // Sanitização básica (muitas vezes ausente)
if (target[key] && typeof target[key] === 'object' && typeof source[key] === 'object') {
merge(target[key], source[key]);
} else {
target[key] = source[key];
}
}
}
const userConfig = {};
const input = JSON.parse(userInput); // userInput vem de uma fonte controlável
merge(userConfig, input);
// Mais tarde, a aplicação usa userConfig.template para renderizar HTML
document.getElementById('app').innerHTML = userConfig.template;Passos para Exploração:
- Identifique a função
merge: Ela itera sobre as chaves desourcee as atribui atarget. - Identifique a fonte controlável:
userInput(e.g., um parâmetro de URL ou corpo de POST). - Crie o payload: Para injetar
templatenoObject.prototype:userInput = '{"__proto__":{"template":"<img src=x onerror=alert(document.domain)>"}}' - Execute: Quando
merge(userConfig, input)for chamado,templateserá adicionado aoObject.prototype. SeuserConfig(ou qualquer outro objeto) não tiver sua própria propriedadetemplate, ele buscará no protótipo e executará o XSS.
Ferramentas para Prototype Pollution:
- PPScan: Uma ferramenta Python para escanear aplicações web em busca de vulnerabilidades de Prototype Pollution.
- Manual Fuzzing: Modifique requisições HTTP (especialmente JSON) adicionando
__proto__ouconstructor.prototypepara ver como a aplicação reage.
Desenvolvedores frequentemente ofuscam o código JavaScript para dificultar a leitura e a engenharia reversa. No entanto, para um ethical hacker, a desofuscação é uma habilidade essencial para entender a lógica da aplicação, identificar vulnerabilidades e extrair informações sensíveis.
O que é Ofuscação?
Ofuscação é o processo de transformar o código-fonte em uma versão mais difícil de entender, mas que mantém a mesma funcionalidade. Isso pode envolver:
- Renomeação de variáveis e funções: Nomes significativos são substituídos por caracteres aleatórios (e.g.,
a,b,_1,$_). - Remoção de espaços e comentários: Reduz o tamanho do arquivo e a legibilidade.
- Codificação de strings: Strings importantes são codificadas em Base64, Hex, Unicode, etc.
- Controle de fluxo complexo: Injeção de loops, condicionais e chamadas de função desnecessárias para confundir o fluxo de execução.
- Auto-defending: Código que detecta e tenta impedir a depuração ou análise.
Metodologia de Desofuscação (Passo a Passo):
-
Identifique o Tipo de Ofuscação: Use ferramentas como
JS BeautifierouJSNicepara tentar formatar o código. Observe padrões de renomeação, codificação de strings e estruturas de controle de fluxo. Ferramentas comode4js(uma extensão do navegador) podem ajudar a identificar ofuscadores comuns. -
Desofusque Strings e Arrays: Muitos ofuscadores colocam strings em arrays e as recuperam dinamicamente. Identifique a função que faz essa recuperação e execute-a no console do navegador ou em um ambiente Node.js para decodificar as strings.
// Exemplo de array de strings ofuscadas const _0xabc1 = ["\x61\x6c\x65\x72\x74", "\x64\x6f\x63\x75\x6d\x65\x6e\x74\x2e\x64\x6f\x6d\x61\x69\x6e"]; // Função de recuperação (simplificada) function _0xdef2(index) { return _0xabc1[index]; } // No console do navegador: console.log(_0xdef2(0)); // Saída: "alert" console.log(_0xdef2(1)); // Saída: "document.domain"
-
Renomeie Variáveis e Funções: Use um editor de código com recursos de renomeação global (e.g., VS Code, Sublime Text) para dar nomes significativos a variáveis e funções ofuscadas. Isso melhora drasticamente a legibilidade.
-
Simplifique o Controle de Fluxo: Para ofuscações mais complexas, pode ser necessário reescrever partes do código para remover loops e condicionais desnecessários. Ferramentas como
JalopyouJavaScript-Deobfuscator(projetos de pesquisa) podem automatizar parte desse processo. -
Use o Depurador (DevTools): Para ofuscações que dependem de execução dinâmica ou auto-defending, o depurador é indispensável. Defina breakpoints em pontos estratégicos, inspecione o valor das variáveis e o fluxo de execução. Você pode até mesmo modificar o código em tempo real para desabilitar as proteções de ofuscação.
Ferramentas Recomendadas para Desofuscação:
- JS Beautifier: Para formatação básica e remoção de minificação.
- JSNice: Tenta inferir nomes de variáveis e funções para melhorar a legibilidade.
- de4js: Uma ferramenta online e extensão de navegador que detecta e desofusca vários tipos de ofuscação.
- AST Explorers (e.g., AST Explorer): Para ofuscações baseadas em Abstract Syntax Tree (AST), pode ser útil visualizar a estrutura da árvore para entender as transformações.
Dica Profissional: A desofuscação é um processo iterativo. Comece com as técnicas mais simples e avance para as mais complexas. Nem todo código ofuscado precisa ser 100% desofuscado; muitas vezes, basta entender a parte relevante para a vulnerabilidade que você está procurando.
Esta seção aborda conceitos mais avançados e as melhores práticas que separam os hackers éticos amadores dos profissionais. Dominar esses tópicos permitirá que você lide com cenários complexos e contribua para a segurança da aplicação de forma mais eficaz.
Como ethical hacker, sua responsabilidade não termina com a descoberta de uma vulnerabilidade. A forma como você comunica e divulga suas descobertas é crucial.
-
Divulgação Responsável (Responsible Disclosure): Sempre siga uma política de divulgação responsável. Isso geralmente envolve:
- Notificar o proprietário da aplicação de forma privada.
- Fornecer detalhes técnicos claros sobre a vulnerabilidade e seu impacto.
- Dar um prazo razoável para que a equipe de desenvolvimento corrija a falha.
- Apenas divulgar publicamente a vulnerabilidade após a correção ou o término do prazo acordado.
-
Escopo e Limites: Nunca teste além do escopo autorizado. Se você descobrir uma vulnerabilidade que pode afetar outros sistemas, comunique isso à equipe responsável e peça permissão antes de prosseguir.
-
Integridade dos Dados: Evite qualquer ação que possa comprometer a integridade ou a disponibilidade dos dados da aplicação. Use contas de teste sempre que possível e evite exfiltrar dados sensíveis, a menos que seja explicitamente permitido e necessário para demonstrar o impacto.
O cenário de segurança de aplicações web está em constante evolução. Novas vulnerabilidades, técnicas de exploração e ferramentas surgem regularmente. Para se manter relevante e eficaz, você precisa:
-
Ler Blogs e Artigos de Pesquisa: Siga blogs de segurança de renome (e.g., PortSwigger, Detectify, Intigriti) e leia artigos de pesquisa sobre novas técnicas de ataque.
-
Participar de Comunidades: Junte-se a comunidades de segurança (e.g., fóruns, grupos de Slack/Discord, conferências) para trocar conhecimentos e aprender com outros profissionais.
-
Praticar em Plataformas de Bug Bounty e CTF: Plataformas como HackerOne, Bugcrowd e Intigriti oferecem oportunidades para testar suas habilidades em aplicações reais e ser recompensado por suas descobertas. Competições de Capture The Flag (CTF) também são uma ótima maneira de aprender e praticar.
-
Contribuir para a Comunidade: Compartilhe seu conhecimento escrevendo artigos, criando ferramentas de código aberto ou apresentando em conferências. Ensinar é uma das melhores maneiras de aprender e solidificar seu próprio conhecimento.
Embora a análise manual seja insubstituível, a automação pode aumentar significativamente sua eficiência. Considere desenvolver seus próprios scripts para automatizar tarefas repetitivas, como:
- Coleta de arquivos JavaScript.
- Busca por endpoints e segredos.
- Verificação de bibliotecas vulneráveis.
- Fuzzing de parâmetros em busca de XSS e outras vulnerabilidades.
Ferramentas como Nuclei, que usa templates YAML para definir verificações de segurança, podem ser extremamente poderosas para automatizar a detecção de vulnerabilidades conhecidas em escala.