workflow.tsā¢21 kB
import { ReconTools, ScanResult, PortScanResult, TechDetectionResult } from '../tools/recon.js';
import { VulnScanTools, VulnerabilityResult } from '../tools/vulnscan.js';
import { ExploitTools, ExploitResult } from '../tools/exploit.js';
export interface PentestWorkflow {
target: string;
scope: 'network' | 'web' | 'full';
intensity: 'passive' | 'active' | 'aggressive';
phases: WorkflowPhase[];
current_phase: number;
results: WorkflowResults;
recommendations: string[];
}
export interface WorkflowPhase {
name: string;
description: string;
status: 'pending' | 'running' | 'completed' | 'failed' | 'skipped';
tools: string[];
results?: ScanResult[];
duration?: number;
start_time?: string;
end_time?: string;
}
export interface WorkflowResults {
reconnaissance: {
open_ports: PortScanResult[];
technologies: TechDetectionResult[];
subdomains: string[];
directories: string[];
};
vulnerabilities: VulnerabilityResult[];
exploits: ExploitResult[];
risk_score: number;
threat_level: 'low' | 'medium' | 'high' | 'critical';
}
export interface NextStepsRecommendation {
priority: 'high' | 'medium' | 'low';
action: string;
tool: string;
reason: string;
estimated_time: string;
risk_level: 'low' | 'medium' | 'high' | 'critical';
}
export class WorkflowEngine {
private reconTools: ReconTools;
private vulnScanTools: VulnScanTools;
private exploitTools: ExploitTools;
constructor() {
this.reconTools = new ReconTools();
this.vulnScanTools = new VulnScanTools();
this.exploitTools = new ExploitTools();
}
async autoPentest(target: string, scope: 'network' | 'web' | 'full' = 'full', intensity: 'passive' | 'active' | 'aggressive' = 'active'): Promise<ScanResult> {
try {
const workflow: PentestWorkflow = this.initializeWorkflow(target, scope, intensity);
console.error(`Starting automated pentest for ${target} (scope: ${scope}, intensity: ${intensity})`);
// Execute phases sequentially
for (let i = 0; i < workflow.phases.length; i++) {
workflow.current_phase = i;
const phase = workflow.phases[i];
console.error(`Executing phase: ${phase.name}`);
phase.status = 'running';
phase.start_time = new Date().toISOString();
try {
await this.executePhase(workflow, phase);
phase.status = 'completed';
phase.end_time = new Date().toISOString();
// Analyze results and decide next steps
await this.analyzePhaseResults(workflow, phase);
} catch (error) {
phase.status = 'failed';
console.error(`Phase ${phase.name} failed:`, error);
// Decide whether to continue or abort based on failure
if (this.shouldAbortOnFailure(phase, error)) {
break;
}
}
}
// Calculate final risk score and recommendations
this.calculateFinalRiskScore(workflow);
this.generateFinalRecommendations(workflow);
return {
target,
timestamp: new Date().toISOString(),
tool: 'auto_pentest',
results: {
workflow,
completed_phases: workflow.phases.filter(p => p.status === 'completed').length,
total_phases: workflow.phases.length,
final_risk_score: workflow.results.risk_score,
threat_level: workflow.results.threat_level
},
status: 'success'
};
} catch (error) {
return {
target,
timestamp: new Date().toISOString(),
tool: 'auto_pentest',
results: {},
status: 'error',
error: error instanceof Error ? error.message : String(error)
};
}
}
async suggestNextSteps(scanResults: string): Promise<ScanResult> {
try {
const results = JSON.parse(scanResults);
const recommendations: NextStepsRecommendation[] = [];
// Analyze reconnaissance results
if (results.reconnaissance) {
recommendations.push(...this.analyzeReconResults(results.reconnaissance));
}
// Analyze vulnerability results
if (results.vulnerabilities) {
recommendations.push(...this.analyzeVulnResults(results.vulnerabilities));
}
// Analyze exploitation results
if (results.exploits) {
recommendations.push(...this.analyzeExploitResults(results.exploits));
}
// Sort recommendations by priority and risk
recommendations.sort((a, b) => {
const priorityOrder = { high: 3, medium: 2, low: 1 };
const riskOrder = { critical: 4, high: 3, medium: 2, low: 1 };
const aScore = priorityOrder[a.priority] + riskOrder[a.risk_level];
const bScore = priorityOrder[b.priority] + riskOrder[b.risk_level];
return bScore - aScore;
});
return {
target: 'analysis',
timestamp: new Date().toISOString(),
tool: 'suggest_next_steps',
results: {
recommendations: recommendations.slice(0, 10), // Top 10 recommendations
total_recommendations: recommendations.length,
analysis_summary: this.generateAnalysisSummary(results)
},
status: 'success'
};
} catch (error) {
return {
target: 'analysis',
timestamp: new Date().toISOString(),
tool: 'suggest_next_steps',
results: {},
status: 'error',
error: error instanceof Error ? error.message : String(error)
};
}
}
// Helper methods
private initializeWorkflow(target: string, scope: string, intensity: string): PentestWorkflow {
const phases: WorkflowPhase[] = [];
// Always start with reconnaissance
phases.push({
name: 'reconnaissance',
description: 'Information gathering and target enumeration',
status: 'pending',
tools: ['nmap_scan', 'subdomain_enum', 'tech_detection']
});
if (scope === 'web' || scope === 'full') {
phases.push({
name: 'web_discovery',
description: 'Web application discovery and enumeration',
status: 'pending',
tools: ['directory_bruteforce', 'tech_detection']
});
phases.push({
name: 'web_vulnerability_scan',
description: 'Web application vulnerability assessment',
status: 'pending',
tools: ['nuclei_scan', 'nikto_scan', 'custom_web_vuln_scan']
});
}
if (scope === 'network' || scope === 'full') {
phases.push({
name: 'network_vulnerability_scan',
description: 'Network service vulnerability assessment',
status: 'pending',
tools: ['nuclei_scan', 'service_specific_scans']
});
}
if (intensity === 'active' || intensity === 'aggressive') {
phases.push({
name: 'exploitation',
description: 'Controlled exploitation attempts',
status: 'pending',
tools: ['exploit_attempt', 'metasploit_search']
});
}
phases.push({
name: 'post_exploitation',
description: 'Post-exploitation analysis and privilege escalation',
status: 'pending',
tools: ['privilege_escalation', 'lateral_movement']
});
return {
target,
scope: scope as any,
intensity: intensity as any,
phases,
current_phase: 0,
results: {
reconnaissance: {
open_ports: [],
technologies: [],
subdomains: [],
directories: []
},
vulnerabilities: [],
exploits: [],
risk_score: 0,
threat_level: 'low'
},
recommendations: []
};
}
private async executePhase(workflow: PentestWorkflow, phase: WorkflowPhase): Promise<void> {
phase.results = [];
switch (phase.name) {
case 'reconnaissance':
await this.executeReconPhase(workflow, phase);
break;
case 'web_discovery':
await this.executeWebDiscoveryPhase(workflow, phase);
break;
case 'web_vulnerability_scan':
await this.executeWebVulnPhase(workflow, phase);
break;
case 'network_vulnerability_scan':
await this.executeNetworkVulnPhase(workflow, phase);
break;
case 'exploitation':
await this.executeExploitationPhase(workflow, phase);
break;
case 'post_exploitation':
await this.executePostExploitationPhase(workflow, phase);
break;
}
}
private async executeReconPhase(workflow: PentestWorkflow, phase: WorkflowPhase): Promise<void> {
const target = workflow.target;
// Port scan
const nmapResult = await this.reconTools.nmapScan(target, workflow.intensity === 'aggressive' ? 'full' : 'quick');
phase.results!.push(nmapResult);
if (nmapResult.status === 'success' && nmapResult.results.open_ports) {
workflow.results.reconnaissance.open_ports = nmapResult.results.open_ports;
}
// Subdomain enumeration (only for domain targets)
if (this.isDomain(target)) {
const subdomainResult = await this.reconTools.subdomainEnum(target);
phase.results!.push(subdomainResult);
if (subdomainResult.status === 'success' && subdomainResult.results.subdomains) {
workflow.results.reconnaissance.subdomains = subdomainResult.results.subdomains;
}
}
// Technology detection (for web targets)
if (this.hasWebPort(workflow.results.reconnaissance.open_ports) || this.isURL(target)) {
const webTarget = this.isURL(target) ? target : `http://${target}`;
const techResult = await this.reconTools.techDetection(webTarget);
phase.results!.push(techResult);
if (techResult.status === 'success' && techResult.results.technologies) {
workflow.results.reconnaissance.technologies = techResult.results.technologies;
}
}
}
private async executeWebDiscoveryPhase(workflow: PentestWorkflow, phase: WorkflowPhase): Promise<void> {
const target = workflow.target;
const webTarget = this.isURL(target) ? target : `http://${target}`;
// Directory brute force
const dirResult = await this.reconTools.directoryBruteforce(webTarget);
phase.results!.push(dirResult);
if (dirResult.status === 'success' && dirResult.results.found_paths) {
workflow.results.reconnaissance.directories = dirResult.results.found_paths;
}
}
private async executeWebVulnPhase(workflow: PentestWorkflow, phase: WorkflowPhase): Promise<void> {
const target = workflow.target;
const webTarget = this.isURL(target) ? target : `http://${target}`;
// Nuclei scan for web vulnerabilities
const nucleiResult = await this.vulnScanTools.nucleiScan(webTarget, ['http'], 'medium');
phase.results!.push(nucleiResult);
// Nikto scan
const niktoResult = await this.vulnScanTools.niktoScan(webTarget);
phase.results!.push(niktoResult);
// Custom web vulnerability scan
const customVulnResult = await this.vulnScanTools.customWebVulnScan(webTarget);
phase.results!.push(customVulnResult);
// Aggregate vulnerabilities
const allVulns: VulnerabilityResult[] = [];
[nucleiResult, niktoResult, customVulnResult].forEach(result => {
if (result.status === 'success' && result.results.vulnerabilities) {
allVulns.push(...result.results.vulnerabilities);
}
});
workflow.results.vulnerabilities.push(...allVulns);
}
private async executeNetworkVulnPhase(workflow: PentestWorkflow, phase: WorkflowPhase): Promise<void> {
const target = workflow.target;
// Network-focused Nuclei scan
const nucleiResult = await this.vulnScanTools.nucleiScan(target, ['network'], 'medium');
phase.results!.push(nucleiResult);
if (nucleiResult.status === 'success' && nucleiResult.results.vulnerabilities) {
workflow.results.vulnerabilities.push(...nucleiResult.results.vulnerabilities);
}
}
private async executeExploitationPhase(workflow: PentestWorkflow, phase: WorkflowPhase): Promise<void> {
const target = workflow.target;
// Only attempt exploitation if vulnerabilities were found
if (workflow.results.vulnerabilities.length === 0) {
phase.status = 'skipped';
return;
}
// Sort vulnerabilities by severity and attempt exploitation
const highSeverityVulns = workflow.results.vulnerabilities
.filter(v => v.severity === 'high' || v.severity === 'critical')
.slice(0, 3); // Limit to top 3 for safety
for (const vuln of highSeverityVulns) {
const exploitResult = await this.exploitTools.exploitAttempt(target, vuln.name);
phase.results!.push(exploitResult);
if (exploitResult.status === 'success' && exploitResult.results.successful_exploits) {
workflow.results.exploits.push(...exploitResult.results.successful_exploits);
}
}
}
private async executePostExploitationPhase(workflow: PentestWorkflow, phase: WorkflowPhase): Promise<void> {
// Only execute if we have successful exploits
if (workflow.results.exploits.length === 0) {
phase.status = 'skipped';
return;
}
// Post-exploitation activities would go here
// For now, just document the successful exploits
console.error(`Post-exploitation phase: ${workflow.results.exploits.length} successful exploits to analyze`);
}
private async analyzePhaseResults(workflow: PentestWorkflow, phase: WorkflowPhase): Promise<void> {
// Analyze results and potentially modify subsequent phases
if (phase.name === 'reconnaissance') {
// If no web ports found, skip web phases
if (!this.hasWebPort(workflow.results.reconnaissance.open_ports) && !this.isURL(workflow.target)) {
workflow.phases.forEach(p => {
if (p.name.includes('web')) {
p.status = 'skipped';
}
});
}
}
if (phase.name === 'web_vulnerability_scan' || phase.name === 'network_vulnerability_scan') {
// If no high-severity vulnerabilities found, consider skipping exploitation
const highSeverityVulns = workflow.results.vulnerabilities.filter(v =>
v.severity === 'high' || v.severity === 'critical'
);
if (highSeverityVulns.length === 0 && workflow.intensity !== 'aggressive') {
const exploitPhase = workflow.phases.find(p => p.name === 'exploitation');
if (exploitPhase) {
exploitPhase.status = 'skipped';
}
}
}
}
private shouldAbortOnFailure(phase: WorkflowPhase, error: any): boolean {
// Critical failures that should abort the workflow
if (phase.name === 'reconnaissance') {
// If recon fails completely, we can't continue
return true;
}
// For other phases, continue with remaining phases
return false;
}
private calculateFinalRiskScore(workflow: PentestWorkflow): void {
let score = 0;
// Score based on open ports (max 20 points)
score += Math.min(workflow.results.reconnaissance.open_ports.length * 2, 20);
// Score based on vulnerabilities (max 50 points)
workflow.results.vulnerabilities.forEach(vuln => {
switch (vuln.severity) {
case 'critical': score += 10; break;
case 'high': score += 7; break;
case 'medium': score += 4; break;
case 'low': score += 2; break;
case 'info': score += 1; break;
}
});
score = Math.min(score, 70); // Cap vulnerability score
// Score based on successful exploits (max 30 points)
score += Math.min(workflow.results.exploits.length * 10, 30);
workflow.results.risk_score = Math.min(score, 100);
// Determine threat level
if (score >= 80) {
workflow.results.threat_level = 'critical';
} else if (score >= 60) {
workflow.results.threat_level = 'high';
} else if (score >= 30) {
workflow.results.threat_level = 'medium';
} else {
workflow.results.threat_level = 'low';
}
}
private generateFinalRecommendations(workflow: PentestWorkflow): void {
const recommendations: string[] = [];
// Port-based recommendations
if (workflow.results.reconnaissance.open_ports.length > 10) {
recommendations.push('Reduce attack surface by closing unnecessary ports');
}
// Vulnerability-based recommendations
const criticalVulns = workflow.results.vulnerabilities.filter(v => v.severity === 'critical');
if (criticalVulns.length > 0) {
recommendations.push(`Address ${criticalVulns.length} critical vulnerabilities immediately`);
}
// Exploit-based recommendations
if (workflow.results.exploits.length > 0) {
recommendations.push('Implement additional security controls - active exploitation successful');
}
// Technology-based recommendations
const outdatedTech = workflow.results.reconnaissance.technologies.filter(t =>
t.technology.toLowerCase().includes('apache') && t.version
);
if (outdatedTech.length > 0) {
recommendations.push('Update server software and frameworks to latest versions');
}
workflow.recommendations = recommendations;
}
private analyzeReconResults(recon: any): NextStepsRecommendation[] {
const recommendations: NextStepsRecommendation[] = [];
if (recon.open_ports && recon.open_ports.length > 0) {
const webPorts = recon.open_ports.filter((p: any) => p.port === 80 || p.port === 443 || p.port === 8080);
if (webPorts.length > 0) {
recommendations.push({
priority: 'high',
action: 'Perform web application vulnerability scan',
tool: 'nuclei_scan',
reason: 'Web services detected on target',
estimated_time: '10-30 minutes',
risk_level: 'medium'
});
}
const sshPorts = recon.open_ports.filter((p: any) => p.port === 22);
if (sshPorts.length > 0) {
recommendations.push({
priority: 'medium',
action: 'Test SSH for weak credentials',
tool: 'ssh_bruteforce',
reason: 'SSH service exposed',
estimated_time: '30-60 minutes',
risk_level: 'high'
});
}
}
return recommendations;
}
private analyzeVulnResults(vulnerabilities: VulnerabilityResult[]): NextStepsRecommendation[] {
const recommendations: NextStepsRecommendation[] = [];
const criticalVulns = vulnerabilities.filter(v => v.severity === 'critical');
const highVulns = vulnerabilities.filter(v => v.severity === 'high');
if (criticalVulns.length > 0) {
recommendations.push({
priority: 'high',
action: 'Attempt exploitation of critical vulnerabilities',
tool: 'exploit_attempt',
reason: `${criticalVulns.length} critical vulnerabilities found`,
estimated_time: '15-45 minutes',
risk_level: 'critical'
});
}
if (highVulns.length > 0) {
recommendations.push({
priority: 'medium',
action: 'Investigate high severity vulnerabilities',
tool: 'manual_verification',
reason: `${highVulns.length} high severity vulnerabilities found`,
estimated_time: '20-60 minutes',
risk_level: 'high'
});
}
return recommendations;
}
private analyzeExploitResults(exploits: ExploitResult[]): NextStepsRecommendation[] {
const recommendations: NextStepsRecommendation[] = [];
const successfulExploits = exploits.filter(e => e.success);
if (successfulExploits.length > 0) {
recommendations.push({
priority: 'high',
action: 'Perform post-exploitation activities',
tool: 'post_exploitation',
reason: `${successfulExploits.length} successful exploits achieved`,
estimated_time: '30-120 minutes',
risk_level: 'critical'
});
}
return recommendations;
}
private generateAnalysisSummary(results: any): any {
return {
total_open_ports: results.reconnaissance?.open_ports?.length || 0,
total_vulnerabilities: results.vulnerabilities?.length || 0,
successful_exploits: results.exploits?.filter((e: any) => e.success)?.length || 0,
risk_assessment: results.risk_score >= 70 ? 'High Risk' :
results.risk_score >= 40 ? 'Medium Risk' : 'Low Risk'
};
}
// Utility methods
private isDomain(target: string): boolean {
return /^[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9](?:\.[a-zA-Z]{2,})+$/.test(target);
}
private isURL(target: string): boolean {
return target.startsWith('http://') || target.startsWith('https://');
}
private hasWebPort(ports: PortScanResult[]): boolean {
return ports.some(p => p.port === 80 || p.port === 443 || p.port === 8080 || p.port === 8443);
}
}