mirror of
https://github.com/mblanke/StrikePackageGPT.git
synced 2026-03-01 14:20:21 -05:00
feat: Add HackGpt Enterprise features
- 6-Phase pentest methodology UI (Recon, Scanning, Vuln, Exploit, Report, Retest) - Phase-aware AI prompts with context from current phase - Attack chain analysis and visualization - CVSS-style severity badges (CRITICAL/HIGH/MEDIUM/LOW) - Findings sidebar with severity counts - Phase-specific tools and quick actions
This commit is contained in:
4
services/shared/__init__.py
Normal file
4
services/shared/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
"""
|
||||
StrikePackageGPT Shared Library
|
||||
Common models, utilities, and constants used across services.
|
||||
"""
|
||||
158
services/shared/models.py
Normal file
158
services/shared/models.py
Normal file
@@ -0,0 +1,158 @@
|
||||
"""
|
||||
Shared Pydantic models for StrikePackageGPT services.
|
||||
"""
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import Optional, Literal, List, Dict, Any
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class TaskState(str, Enum):
|
||||
PENDING = "pending"
|
||||
RUNNING = "running"
|
||||
COMPLETED = "completed"
|
||||
FAILED = "failed"
|
||||
CANCELLED = "cancelled"
|
||||
|
||||
|
||||
class ToolCategory(str, Enum):
|
||||
RECON = "reconnaissance"
|
||||
VULN_SCAN = "vulnerability_scanning"
|
||||
EXPLOITATION = "exploitation"
|
||||
WEB_TESTING = "web_testing"
|
||||
PASSWORD = "password_attacks"
|
||||
WIRELESS = "wireless"
|
||||
FORENSICS = "forensics"
|
||||
|
||||
|
||||
# ============== Chat Models ==============
|
||||
|
||||
class ChatMessage(BaseModel):
|
||||
role: Literal["system", "user", "assistant"]
|
||||
content: str
|
||||
timestamp: Optional[datetime] = None
|
||||
|
||||
|
||||
class ChatRequest(BaseModel):
|
||||
message: str
|
||||
session_id: Optional[str] = None
|
||||
context: Optional[str] = None
|
||||
provider: str = "ollama"
|
||||
model: str = "llama3.2"
|
||||
temperature: float = 0.7
|
||||
max_tokens: int = 2048
|
||||
|
||||
|
||||
class ChatResponse(BaseModel):
|
||||
provider: str
|
||||
model: str
|
||||
content: str
|
||||
usage: Optional[Dict[str, int]] = None
|
||||
session_id: Optional[str] = None
|
||||
|
||||
|
||||
# ============== Command Execution Models ==============
|
||||
|
||||
class CommandRequest(BaseModel):
|
||||
command: str
|
||||
timeout: int = Field(default=300, ge=1, le=3600)
|
||||
working_dir: Optional[str] = "/workspace"
|
||||
env: Optional[Dict[str, str]] = None
|
||||
|
||||
|
||||
class CommandResult(BaseModel):
|
||||
command: str
|
||||
exit_code: int
|
||||
stdout: str
|
||||
stderr: str
|
||||
duration_seconds: float
|
||||
timed_out: bool = False
|
||||
|
||||
|
||||
# ============== Task Models ==============
|
||||
|
||||
class Task(BaseModel):
|
||||
task_id: str
|
||||
task_type: str
|
||||
status: TaskState = TaskState.PENDING
|
||||
created_at: datetime = Field(default_factory=datetime.utcnow)
|
||||
started_at: Optional[datetime] = None
|
||||
completed_at: Optional[datetime] = None
|
||||
result: Optional[Any] = None
|
||||
error: Optional[str] = None
|
||||
progress: int = Field(default=0, ge=0, le=100)
|
||||
metadata: Dict[str, Any] = Field(default_factory=dict)
|
||||
|
||||
|
||||
# ============== Security Tool Models ==============
|
||||
|
||||
class SecurityTool(BaseModel):
|
||||
name: str
|
||||
description: str
|
||||
category: ToolCategory
|
||||
command_template: str
|
||||
required_args: List[str] = []
|
||||
optional_args: List[str] = []
|
||||
output_parser: Optional[str] = None
|
||||
|
||||
|
||||
class ScanTarget(BaseModel):
|
||||
target: str # IP, hostname, URL, or CIDR
|
||||
target_type: Literal["ip", "hostname", "url", "cidr", "auto"] = "auto"
|
||||
ports: Optional[str] = None # e.g., "22,80,443" or "1-1000"
|
||||
options: Dict[str, Any] = Field(default_factory=dict)
|
||||
|
||||
|
||||
class ScanRequest(BaseModel):
|
||||
target: ScanTarget
|
||||
tool: str
|
||||
scan_type: Optional[str] = None
|
||||
options: Dict[str, Any] = Field(default_factory=dict)
|
||||
|
||||
|
||||
class ScanResult(BaseModel):
|
||||
scan_id: str
|
||||
tool: str
|
||||
target: str
|
||||
status: TaskState
|
||||
started_at: datetime
|
||||
completed_at: Optional[datetime] = None
|
||||
raw_output: Optional[str] = None
|
||||
parsed_results: Optional[Dict[str, Any]] = None
|
||||
findings: List[Dict[str, Any]] = []
|
||||
|
||||
|
||||
# ============== Session Models ==============
|
||||
|
||||
class Session(BaseModel):
|
||||
session_id: str
|
||||
created_at: datetime = Field(default_factory=datetime.utcnow)
|
||||
last_activity: datetime = Field(default_factory=datetime.utcnow)
|
||||
messages: List[ChatMessage] = []
|
||||
context: Dict[str, Any] = Field(default_factory=dict)
|
||||
active_scans: List[str] = []
|
||||
|
||||
|
||||
# ============== Finding Models ==============
|
||||
|
||||
class Severity(str, Enum):
|
||||
CRITICAL = "critical"
|
||||
HIGH = "high"
|
||||
MEDIUM = "medium"
|
||||
LOW = "low"
|
||||
INFO = "info"
|
||||
|
||||
|
||||
class Finding(BaseModel):
|
||||
finding_id: str
|
||||
title: str
|
||||
description: str
|
||||
severity: Severity
|
||||
category: str
|
||||
target: str
|
||||
evidence: Optional[str] = None
|
||||
remediation: Optional[str] = None
|
||||
references: List[str] = []
|
||||
cve_ids: List[str] = []
|
||||
detected_at: datetime = Field(default_factory=datetime.utcnow)
|
||||
tool: Optional[str] = None
|
||||
315
services/shared/parsers.py
Normal file
315
services/shared/parsers.py
Normal file
@@ -0,0 +1,315 @@
|
||||
"""
|
||||
Output parsers for security tool results.
|
||||
Converts raw tool output into structured data.
|
||||
"""
|
||||
import re
|
||||
import json
|
||||
import xml.etree.ElementTree as ET
|
||||
from typing import Dict, Any, List, Optional
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class BaseParser:
|
||||
"""Base class for tool output parsers."""
|
||||
|
||||
def parse(self, output: str) -> Dict[str, Any]:
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class NmapParser(BaseParser):
|
||||
"""Parser for nmap output."""
|
||||
|
||||
def parse(self, output: str) -> Dict[str, Any]:
|
||||
"""Parse nmap text output."""
|
||||
results = {
|
||||
"hosts": [],
|
||||
"scan_info": {},
|
||||
"raw": output
|
||||
}
|
||||
|
||||
current_host = None
|
||||
|
||||
for line in output.split('\n'):
|
||||
line = line.strip()
|
||||
|
||||
# Parse scan info
|
||||
if line.startswith('Nmap scan report for'):
|
||||
if current_host:
|
||||
results["hosts"].append(current_host)
|
||||
|
||||
# Extract hostname and IP
|
||||
match = re.search(r'for (\S+)(?: \((\d+\.\d+\.\d+\.\d+)\))?', line)
|
||||
if match:
|
||||
current_host = {
|
||||
"hostname": match.group(1),
|
||||
"ip": match.group(2) or match.group(1),
|
||||
"ports": [],
|
||||
"os": None,
|
||||
"status": "up"
|
||||
}
|
||||
|
||||
# Parse port info
|
||||
elif current_host and re.match(r'^\d+/(tcp|udp)', line):
|
||||
parts = line.split()
|
||||
if len(parts) >= 3:
|
||||
port_proto = parts[0].split('/')
|
||||
current_host["ports"].append({
|
||||
"port": int(port_proto[0]),
|
||||
"protocol": port_proto[1],
|
||||
"state": parts[1],
|
||||
"service": parts[2] if len(parts) > 2 else "unknown",
|
||||
"version": ' '.join(parts[3:]) if len(parts) > 3 else None
|
||||
})
|
||||
|
||||
# Parse OS detection
|
||||
elif current_host and 'OS details:' in line:
|
||||
current_host["os"] = line.replace('OS details:', '').strip()
|
||||
|
||||
# Parse timing info
|
||||
elif 'scanned in' in line.lower():
|
||||
match = re.search(r'scanned in ([\d.]+) seconds', line)
|
||||
if match:
|
||||
results["scan_info"]["duration_seconds"] = float(match.group(1))
|
||||
|
||||
if current_host:
|
||||
results["hosts"].append(current_host)
|
||||
|
||||
return results
|
||||
|
||||
def parse_xml(self, xml_output: str) -> Dict[str, Any]:
|
||||
"""Parse nmap XML output for more detailed results."""
|
||||
try:
|
||||
root = ET.fromstring(xml_output)
|
||||
results = {
|
||||
"hosts": [],
|
||||
"scan_info": {
|
||||
"scanner": root.get("scanner"),
|
||||
"args": root.get("args"),
|
||||
"start_time": root.get("start"),
|
||||
}
|
||||
}
|
||||
|
||||
for host in root.findall('.//host'):
|
||||
host_info = {
|
||||
"ip": None,
|
||||
"hostname": None,
|
||||
"status": host.find('status').get('state') if host.find('status') is not None else "unknown",
|
||||
"ports": [],
|
||||
"os": []
|
||||
}
|
||||
|
||||
# Get addresses
|
||||
for addr in host.findall('.//address'):
|
||||
if addr.get('addrtype') == 'ipv4':
|
||||
host_info["ip"] = addr.get('addr')
|
||||
|
||||
# Get hostnames
|
||||
hostname_elem = host.find('.//hostname')
|
||||
if hostname_elem is not None:
|
||||
host_info["hostname"] = hostname_elem.get('name')
|
||||
|
||||
# Get ports
|
||||
for port in host.findall('.//port'):
|
||||
port_info = {
|
||||
"port": int(port.get('portid')),
|
||||
"protocol": port.get('protocol'),
|
||||
"state": port.find('state').get('state') if port.find('state') is not None else "unknown",
|
||||
}
|
||||
|
||||
service = port.find('service')
|
||||
if service is not None:
|
||||
port_info["service"] = service.get('name')
|
||||
port_info["product"] = service.get('product')
|
||||
port_info["version"] = service.get('version')
|
||||
|
||||
host_info["ports"].append(port_info)
|
||||
|
||||
results["hosts"].append(host_info)
|
||||
|
||||
return results
|
||||
except ET.ParseError:
|
||||
return {"error": "Failed to parse XML", "raw": xml_output}
|
||||
|
||||
|
||||
class NiktoParser(BaseParser):
|
||||
"""Parser for nikto output."""
|
||||
|
||||
def parse(self, output: str) -> Dict[str, Any]:
|
||||
results = {
|
||||
"target": None,
|
||||
"findings": [],
|
||||
"server_info": {},
|
||||
"raw": output
|
||||
}
|
||||
|
||||
for line in output.split('\n'):
|
||||
line = line.strip()
|
||||
|
||||
# Target info
|
||||
if '+ Target IP:' in line:
|
||||
results["target"] = line.split(':')[-1].strip()
|
||||
elif '+ Target Hostname:' in line:
|
||||
results["server_info"]["hostname"] = line.split(':')[-1].strip()
|
||||
elif '+ Target Port:' in line:
|
||||
results["server_info"]["port"] = line.split(':')[-1].strip()
|
||||
elif '+ Server:' in line:
|
||||
results["server_info"]["server"] = line.split(':', 1)[-1].strip()
|
||||
|
||||
# Findings (lines starting with +)
|
||||
elif line.startswith('+') and ':' in line:
|
||||
# Skip info lines
|
||||
if any(skip in line for skip in ['Target IP', 'Target Hostname', 'Target Port', 'Server:', 'Start Time', 'End Time']):
|
||||
continue
|
||||
|
||||
finding = {
|
||||
"raw": line[1:].strip(),
|
||||
"severity": "info"
|
||||
}
|
||||
|
||||
# Determine severity based on content
|
||||
if any(word in line.lower() for word in ['vulnerable', 'vulnerability', 'exploit']):
|
||||
finding["severity"] = "high"
|
||||
elif any(word in line.lower() for word in ['outdated', 'deprecated', 'insecure']):
|
||||
finding["severity"] = "medium"
|
||||
elif any(word in line.lower() for word in ['disclosed', 'information', 'header']):
|
||||
finding["severity"] = "low"
|
||||
|
||||
# Extract OSVDB if present
|
||||
osvdb_match = re.search(r'OSVDB-(\d+)', line)
|
||||
if osvdb_match:
|
||||
finding["osvdb"] = osvdb_match.group(1)
|
||||
|
||||
results["findings"].append(finding)
|
||||
|
||||
return results
|
||||
|
||||
|
||||
class SQLMapParser(BaseParser):
|
||||
"""Parser for sqlmap output."""
|
||||
|
||||
def parse(self, output: str) -> Dict[str, Any]:
|
||||
results = {
|
||||
"target": None,
|
||||
"parameters": [],
|
||||
"injections": [],
|
||||
"databases": [],
|
||||
"raw": output
|
||||
}
|
||||
|
||||
in_parameter_section = False
|
||||
|
||||
for line in output.split('\n'):
|
||||
line = line.strip()
|
||||
|
||||
# Target URL
|
||||
if 'target URL' in line.lower():
|
||||
match = re.search(r"'([^']+)'", line)
|
||||
if match:
|
||||
results["target"] = match.group(1)
|
||||
|
||||
# Injectable parameters
|
||||
if 'Parameter:' in line:
|
||||
param_match = re.search(r"Parameter: (\S+)", line)
|
||||
if param_match:
|
||||
results["parameters"].append({
|
||||
"name": param_match.group(1),
|
||||
"injectable": True
|
||||
})
|
||||
|
||||
# Injection type
|
||||
if 'Type:' in line and 'injection' in line.lower():
|
||||
results["injections"].append(line.replace('Type:', '').strip())
|
||||
|
||||
# Databases found
|
||||
if line.startswith('[*]') and 'available databases' not in line.lower():
|
||||
db_name = line[3:].strip()
|
||||
if db_name:
|
||||
results["databases"].append(db_name)
|
||||
|
||||
return results
|
||||
|
||||
|
||||
class GobusterParser(BaseParser):
|
||||
"""Parser for gobuster output."""
|
||||
|
||||
def parse(self, output: str) -> Dict[str, Any]:
|
||||
results = {
|
||||
"findings": [],
|
||||
"directories": [],
|
||||
"files": [],
|
||||
"raw": output
|
||||
}
|
||||
|
||||
for line in output.split('\n'):
|
||||
line = line.strip()
|
||||
|
||||
# Parse found paths
|
||||
# Format: /path (Status: 200) [Size: 1234]
|
||||
match = re.search(r'^(/\S*)\s+\(Status:\s*(\d+)\)(?:\s+\[Size:\s*(\d+)\])?', line)
|
||||
if match:
|
||||
finding = {
|
||||
"path": match.group(1),
|
||||
"status": int(match.group(2)),
|
||||
"size": int(match.group(3)) if match.group(3) else None
|
||||
}
|
||||
|
||||
results["findings"].append(finding)
|
||||
|
||||
if finding["path"].endswith('/'):
|
||||
results["directories"].append(finding["path"])
|
||||
else:
|
||||
results["files"].append(finding["path"])
|
||||
|
||||
return results
|
||||
|
||||
|
||||
class HydraParser(BaseParser):
|
||||
"""Parser for hydra output."""
|
||||
|
||||
def parse(self, output: str) -> Dict[str, Any]:
|
||||
results = {
|
||||
"credentials": [],
|
||||
"target": None,
|
||||
"service": None,
|
||||
"raw": output
|
||||
}
|
||||
|
||||
for line in output.split('\n'):
|
||||
line = line.strip()
|
||||
|
||||
# Parse found credentials
|
||||
# Format: [port][service] host: x login: y password: z
|
||||
cred_match = re.search(r'\[(\d+)\]\[(\w+)\]\s+host:\s+(\S+)\s+login:\s+(\S+)\s+password:\s+(\S+)', line)
|
||||
if cred_match:
|
||||
results["credentials"].append({
|
||||
"port": int(cred_match.group(1)),
|
||||
"service": cred_match.group(2),
|
||||
"host": cred_match.group(3),
|
||||
"username": cred_match.group(4),
|
||||
"password": cred_match.group(5)
|
||||
})
|
||||
results["target"] = cred_match.group(3)
|
||||
results["service"] = cred_match.group(2)
|
||||
|
||||
return results
|
||||
|
||||
|
||||
# Registry of parsers
|
||||
PARSERS = {
|
||||
"nmap": NmapParser(),
|
||||
"nikto": NiktoParser(),
|
||||
"sqlmap": SQLMapParser(),
|
||||
"gobuster": GobusterParser(),
|
||||
"hydra": HydraParser(),
|
||||
}
|
||||
|
||||
|
||||
def parse_tool_output(tool: str, output: str) -> Dict[str, Any]:
|
||||
"""Parse output from a security tool."""
|
||||
parser = PARSERS.get(tool.lower())
|
||||
if parser:
|
||||
try:
|
||||
return parser.parse(output)
|
||||
except Exception as e:
|
||||
return {"error": str(e), "raw": output}
|
||||
return {"raw": output}
|
||||
263
services/shared/tools.py
Normal file
263
services/shared/tools.py
Normal file
@@ -0,0 +1,263 @@
|
||||
"""
|
||||
Security tool definitions and command builders.
|
||||
"""
|
||||
from typing import Dict, List, Optional, Any
|
||||
|
||||
|
||||
SECURITY_TOOLS = {
|
||||
# ============== Reconnaissance ==============
|
||||
"nmap": {
|
||||
"name": "nmap",
|
||||
"description": "Network scanner and security auditing tool",
|
||||
"category": "reconnaissance",
|
||||
"templates": {
|
||||
"quick": "nmap -T4 -F {target}",
|
||||
"full": "nmap -sV -sC -O -p- {target}",
|
||||
"stealth": "nmap -sS -T2 -f {target}",
|
||||
"udp": "nmap -sU --top-ports 100 {target}",
|
||||
"vuln": "nmap --script vuln {target}",
|
||||
"version": "nmap -sV -p {ports} {target}",
|
||||
"os": "nmap -O --osscan-guess {target}",
|
||||
},
|
||||
"default_template": "quick",
|
||||
"output_parser": "nmap"
|
||||
},
|
||||
|
||||
"masscan": {
|
||||
"name": "masscan",
|
||||
"description": "Fast TCP port scanner",
|
||||
"category": "reconnaissance",
|
||||
"templates": {
|
||||
"quick": "masscan {target} --ports 0-1000 --rate 1000",
|
||||
"full": "masscan {target} --ports 0-65535 --rate 10000",
|
||||
"top100": "masscan {target} --top-ports 100 --rate 1000",
|
||||
},
|
||||
"default_template": "quick",
|
||||
},
|
||||
|
||||
"amass": {
|
||||
"name": "amass",
|
||||
"description": "Subdomain enumeration tool",
|
||||
"category": "reconnaissance",
|
||||
"templates": {
|
||||
"passive": "amass enum -passive -d {target}",
|
||||
"active": "amass enum -active -d {target}",
|
||||
"intel": "amass intel -d {target}",
|
||||
},
|
||||
"default_template": "passive",
|
||||
},
|
||||
|
||||
"theharvester": {
|
||||
"name": "theHarvester",
|
||||
"description": "OSINT tool for gathering emails, names, subdomains",
|
||||
"category": "reconnaissance",
|
||||
"templates": {
|
||||
"all": "theHarvester -d {target} -b all",
|
||||
"google": "theHarvester -d {target} -b google",
|
||||
"linkedin": "theHarvester -d {target} -b linkedin",
|
||||
},
|
||||
"default_template": "all",
|
||||
},
|
||||
|
||||
"whatweb": {
|
||||
"name": "whatweb",
|
||||
"description": "Web technology fingerprinting",
|
||||
"category": "reconnaissance",
|
||||
"templates": {
|
||||
"default": "whatweb {target}",
|
||||
"aggressive": "whatweb -a 3 {target}",
|
||||
"verbose": "whatweb -v {target}",
|
||||
},
|
||||
"default_template": "default",
|
||||
},
|
||||
|
||||
"dnsrecon": {
|
||||
"name": "dnsrecon",
|
||||
"description": "DNS enumeration tool",
|
||||
"category": "reconnaissance",
|
||||
"templates": {
|
||||
"standard": "dnsrecon -d {target}",
|
||||
"zone": "dnsrecon -d {target} -t axfr",
|
||||
"brute": "dnsrecon -d {target} -t brt",
|
||||
},
|
||||
"default_template": "standard",
|
||||
},
|
||||
|
||||
# ============== Vulnerability Scanning ==============
|
||||
"nikto": {
|
||||
"name": "nikto",
|
||||
"description": "Web server vulnerability scanner",
|
||||
"category": "vulnerability_scanning",
|
||||
"templates": {
|
||||
"default": "nikto -h {target}",
|
||||
"ssl": "nikto -h {target} -ssl",
|
||||
"tuning": "nikto -h {target} -Tuning x",
|
||||
"full": "nikto -h {target} -C all",
|
||||
},
|
||||
"default_template": "default",
|
||||
"output_parser": "nikto"
|
||||
},
|
||||
|
||||
"sqlmap": {
|
||||
"name": "sqlmap",
|
||||
"description": "SQL injection detection and exploitation",
|
||||
"category": "vulnerability_scanning",
|
||||
"templates": {
|
||||
"test": "sqlmap -u '{target}' --batch",
|
||||
"dbs": "sqlmap -u '{target}' --batch --dbs",
|
||||
"tables": "sqlmap -u '{target}' --batch -D {database} --tables",
|
||||
"dump": "sqlmap -u '{target}' --batch -D {database} -T {table} --dump",
|
||||
"forms": "sqlmap -u '{target}' --batch --forms",
|
||||
},
|
||||
"default_template": "test",
|
||||
"output_parser": "sqlmap"
|
||||
},
|
||||
|
||||
"wpscan": {
|
||||
"name": "wpscan",
|
||||
"description": "WordPress vulnerability scanner",
|
||||
"category": "vulnerability_scanning",
|
||||
"templates": {
|
||||
"default": "wpscan --url {target}",
|
||||
"enumerate": "wpscan --url {target} -e vp,vt,u",
|
||||
"aggressive": "wpscan --url {target} -e ap,at,u --plugins-detection aggressive",
|
||||
},
|
||||
"default_template": "default",
|
||||
},
|
||||
|
||||
# ============== Web Testing ==============
|
||||
"gobuster": {
|
||||
"name": "gobuster",
|
||||
"description": "Directory/file brute-forcing",
|
||||
"category": "web_testing",
|
||||
"templates": {
|
||||
"dir": "gobuster dir -u {target} -w /usr/share/wordlists/dirb/common.txt",
|
||||
"big": "gobuster dir -u {target} -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt",
|
||||
"dns": "gobuster dns -d {target} -w /usr/share/wordlists/dns/subdomains-top1million-5000.txt",
|
||||
"vhost": "gobuster vhost -u {target} -w /usr/share/wordlists/dns/subdomains-top1million-5000.txt",
|
||||
},
|
||||
"default_template": "dir",
|
||||
"output_parser": "gobuster"
|
||||
},
|
||||
|
||||
"ffuf": {
|
||||
"name": "ffuf",
|
||||
"description": "Fast web fuzzer",
|
||||
"category": "web_testing",
|
||||
"templates": {
|
||||
"dir": "ffuf -u {target}/FUZZ -w /usr/share/wordlists/dirb/common.txt",
|
||||
"vhost": "ffuf -u {target} -H 'Host: FUZZ.{domain}' -w /usr/share/wordlists/dns/subdomains-top1million-5000.txt",
|
||||
"param": "ffuf -u '{target}?FUZZ=test' -w /usr/share/wordlists/dirb/common.txt",
|
||||
},
|
||||
"default_template": "dir",
|
||||
},
|
||||
|
||||
"dirb": {
|
||||
"name": "dirb",
|
||||
"description": "Web content scanner",
|
||||
"category": "web_testing",
|
||||
"templates": {
|
||||
"default": "dirb {target}",
|
||||
"small": "dirb {target} /usr/share/wordlists/dirb/small.txt",
|
||||
"big": "dirb {target} /usr/share/wordlists/dirb/big.txt",
|
||||
},
|
||||
"default_template": "default",
|
||||
},
|
||||
|
||||
# ============== Exploitation ==============
|
||||
"searchsploit": {
|
||||
"name": "searchsploit",
|
||||
"description": "Exploit database search tool",
|
||||
"category": "exploitation",
|
||||
"templates": {
|
||||
"search": "searchsploit {query}",
|
||||
"exact": "searchsploit -e {query}",
|
||||
"json": "searchsploit -j {query}",
|
||||
"path": "searchsploit -p {exploit_id}",
|
||||
},
|
||||
"default_template": "search",
|
||||
},
|
||||
|
||||
"hydra": {
|
||||
"name": "hydra",
|
||||
"description": "Network login cracker",
|
||||
"category": "password_attacks",
|
||||
"templates": {
|
||||
"ssh": "hydra -l {user} -P /usr/share/wordlists/rockyou.txt {target} ssh",
|
||||
"ftp": "hydra -l {user} -P /usr/share/wordlists/rockyou.txt {target} ftp",
|
||||
"http_post": "hydra -l {user} -P /usr/share/wordlists/rockyou.txt {target} http-post-form '{form}'",
|
||||
"smb": "hydra -l {user} -P /usr/share/wordlists/rockyou.txt {target} smb",
|
||||
},
|
||||
"default_template": "ssh",
|
||||
"output_parser": "hydra"
|
||||
},
|
||||
|
||||
# ============== Network Tools ==============
|
||||
"netcat": {
|
||||
"name": "nc",
|
||||
"description": "Network utility for TCP/UDP connections",
|
||||
"category": "network",
|
||||
"templates": {
|
||||
"listen": "nc -lvnp {port}",
|
||||
"connect": "nc -v {target} {port}",
|
||||
"scan": "nc -zv {target} {port_range}",
|
||||
},
|
||||
"default_template": "scan",
|
||||
},
|
||||
|
||||
"curl": {
|
||||
"name": "curl",
|
||||
"description": "HTTP client",
|
||||
"category": "web_testing",
|
||||
"templates": {
|
||||
"get": "curl -v {target}",
|
||||
"headers": "curl -I {target}",
|
||||
"post": "curl -X POST -d '{data}' {target}",
|
||||
"follow": "curl -L -v {target}",
|
||||
},
|
||||
"default_template": "get",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def get_tool(name: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get tool definition by name."""
|
||||
return SECURITY_TOOLS.get(name.lower())
|
||||
|
||||
|
||||
def get_tools_by_category(category: str) -> List[Dict[str, Any]]:
|
||||
"""Get all tools in a category."""
|
||||
return [tool for tool in SECURITY_TOOLS.values() if tool.get("category") == category]
|
||||
|
||||
|
||||
def build_command(tool_name: str, template_name: str = None, **kwargs) -> Optional[str]:
|
||||
"""Build a command from a tool template."""
|
||||
tool = get_tool(tool_name)
|
||||
if not tool:
|
||||
return None
|
||||
|
||||
template_name = template_name or tool.get("default_template")
|
||||
template = tool.get("templates", {}).get(template_name)
|
||||
|
||||
if not template:
|
||||
return None
|
||||
|
||||
try:
|
||||
return template.format(**kwargs)
|
||||
except KeyError as e:
|
||||
return None
|
||||
|
||||
|
||||
def list_all_tools() -> Dict[str, List[Dict[str, str]]]:
|
||||
"""List all available tools grouped by category."""
|
||||
result = {}
|
||||
for tool in SECURITY_TOOLS.values():
|
||||
category = tool.get("category", "other")
|
||||
if category not in result:
|
||||
result[category] = []
|
||||
result[category].append({
|
||||
"name": tool["name"],
|
||||
"description": tool["description"],
|
||||
"templates": list(tool.get("templates", {}).keys())
|
||||
})
|
||||
return result
|
||||
Reference in New Issue
Block a user