Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,9 +1,14 @@
|
|
| 1 |
|
|
|
|
|
|
|
|
|
|
| 2 |
═══════════════════════════════════════════════════════════════════════════════
|
| 3 |
-
PRIVATE RED TEAM WEB RECONNAISSANCE FRAMEWORK v3.0
|
| 4 |
─────────────────────────────────────────────────────────────────────────
|
| 5 |
-
|
| 6 |
-
|
|
|
|
|
|
|
| 7 |
|
| 8 |
import gradio as gr
|
| 9 |
import asyncio
|
|
@@ -36,11 +41,20 @@ from urllib.parse import urljoin, urlparse
|
|
| 36 |
# ════════════════════════════════════════════════════════════════════════════
|
| 37 |
|
| 38 |
class ThreatLevel(Enum):
|
|
|
|
| 39 |
LOW = 0
|
| 40 |
MEDIUM = 1
|
| 41 |
HIGH = 2
|
| 42 |
CRITICAL = 3
|
| 43 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
STRIDE_THREATS = {
|
| 45 |
"Spoofing": {
|
| 46 |
"description": "Identity spoofing",
|
|
@@ -74,6 +88,7 @@ STRIDE_THREATS = {
|
|
| 74 |
}
|
| 75 |
}
|
| 76 |
|
|
|
|
| 77 |
MITRE_TECHNIQUES = {
|
| 78 |
"Reconnaissance": {
|
| 79 |
"T1592": "Gather Victim Host Information",
|
|
@@ -135,6 +150,47 @@ MITRE_TECHNIQUES = {
|
|
| 135 |
}
|
| 136 |
}
|
| 137 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 138 |
SECURITY_HEADERS = {
|
| 139 |
"Strict-Transport-Security": "HSTS",
|
| 140 |
"Content-Security-Policy": "CSP",
|
|
@@ -145,6 +201,7 @@ SECURITY_HEADERS = {
|
|
| 145 |
"Permissions-Policy": "Feature Policy"
|
| 146 |
}
|
| 147 |
|
|
|
|
| 148 |
COMMON_ENDPOINTS = [
|
| 149 |
"", "admin", "api", "login", "test", "debug", "config",
|
| 150 |
"api/users", "api/admin", "api/auth", "api/data", "api/v1",
|
|
@@ -162,6 +219,7 @@ COMMON_ENDPOINTS = [
|
|
| 162 |
|
| 163 |
@dataclass
|
| 164 |
class IntelligenceIndicator:
|
|
|
|
| 165 |
type: str
|
| 166 |
value: str
|
| 167 |
confidence: float
|
|
@@ -171,6 +229,7 @@ class IntelligenceIndicator:
|
|
| 171 |
|
| 172 |
@dataclass
|
| 173 |
class ThreatVector:
|
|
|
|
| 174 |
category: str
|
| 175 |
location: str
|
| 176 |
risk_score: float
|
|
@@ -182,6 +241,7 @@ class ThreatVector:
|
|
| 182 |
|
| 183 |
@dataclass
|
| 184 |
class AttackPath:
|
|
|
|
| 185 |
entry_point: str
|
| 186 |
intermediate_steps: List[str]
|
| 187 |
objective: str
|
|
@@ -195,6 +255,7 @@ class AttackPath:
|
|
| 195 |
|
| 196 |
@dataclass
|
| 197 |
class Vulnerability:
|
|
|
|
| 198 |
name: str
|
| 199 |
description: str
|
| 200 |
severity: str
|
|
@@ -216,6 +277,8 @@ class Vulnerability:
|
|
| 216 |
# ════════════════════════════════════════════════════════════════════════════
|
| 217 |
|
| 218 |
class StealthConfig:
|
|
|
|
|
|
|
| 219 |
def __init__(self, threat_level: ThreatLevel = ThreatLevel.MEDIUM):
|
| 220 |
self.threat_level = threat_level
|
| 221 |
|
|
@@ -246,10 +309,12 @@ class StealthConfig:
|
|
| 246 |
self.current_proxy = 0
|
| 247 |
|
| 248 |
def get_delay(self) -> float:
|
|
|
|
| 249 |
min_d, max_d = self.delay_ranges[self.threat_level]
|
| 250 |
return random.uniform(min_d, max_d) / 1000
|
| 251 |
|
| 252 |
def get_headers(self) -> Dict[str, str]:
|
|
|
|
| 253 |
headers = {
|
| 254 |
"User-Agent": random.choice(self.user_agents),
|
| 255 |
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
|
|
@@ -265,12 +330,22 @@ class StealthConfig:
|
|
| 265 |
"Sec-Fetch-User": "?1"
|
| 266 |
}
|
| 267 |
return headers
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 268 |
|
| 269 |
# ════════════════════════════════════════════════════════════════════════════
|
| 270 |
# SECTION 4: PASSIVE OSINT ENGINE
|
| 271 |
# ════════════════════════════════════════════════════════════════════════════
|
| 272 |
|
| 273 |
class PassiveOSINTEngine:
|
|
|
|
|
|
|
| 274 |
def __init__(self, config: StealthConfig):
|
| 275 |
self.config = config
|
| 276 |
self.indicators: Dict[str, List[IntelligenceIndicator]] = defaultdict(list)
|
|
@@ -281,6 +356,7 @@ class PassiveOSINTEngine:
|
|
| 281 |
return logging.getLogger("PassiveOSINT")
|
| 282 |
|
| 283 |
async def gather_dns_intel(self, domain: str) -> Dict:
|
|
|
|
| 284 |
intel = {
|
| 285 |
"subdomains": [],
|
| 286 |
"mx_records": [],
|
|
@@ -294,6 +370,7 @@ class PassiveOSINTEngine:
|
|
| 294 |
try:
|
| 295 |
import dns.resolver
|
| 296 |
|
|
|
|
| 297 |
common_subs = [
|
| 298 |
"www", "mail", "ftp", "admin", "api", "dev", "staging",
|
| 299 |
"cdn", "test", "blog", "shop", "support", "docs", "app",
|
|
@@ -314,6 +391,7 @@ class PassiveOSINTEngine:
|
|
| 314 |
except:
|
| 315 |
pass
|
| 316 |
|
|
|
|
| 317 |
try:
|
| 318 |
full_domain = f"{sub}.{domain}"
|
| 319 |
result = dns.resolver.resolve(full_domain, 'AAAA')
|
|
@@ -325,18 +403,21 @@ class PassiveOSINTEngine:
|
|
| 325 |
except:
|
| 326 |
pass
|
| 327 |
|
|
|
|
| 328 |
try:
|
| 329 |
mx = dns.resolver.resolve(domain, 'MX')
|
| 330 |
intel["mx_records"] = [{"preference": r.preference, "exchange": str(r.exchange)} for r in mx]
|
| 331 |
except:
|
| 332 |
pass
|
| 333 |
|
|
|
|
| 334 |
try:
|
| 335 |
ns = dns.resolver.resolve(domain, 'NS')
|
| 336 |
intel["ns_records"] = [str(r) for r in ns]
|
| 337 |
except:
|
| 338 |
pass
|
| 339 |
|
|
|
|
| 340 |
try:
|
| 341 |
txt = dns.resolver.resolve(domain, 'TXT')
|
| 342 |
intel["txt_records"] = [str(r) for r in txt]
|
|
@@ -349,6 +430,7 @@ class PassiveOSINTEngine:
|
|
| 349 |
return intel
|
| 350 |
|
| 351 |
async def gather_ssl_cert_intel(self, domain: str) -> Dict:
|
|
|
|
| 352 |
cert_intel = {
|
| 353 |
"subject": None,
|
| 354 |
"issuer": None,
|
|
@@ -379,11 +461,13 @@ class PassiveOSINTEngine:
|
|
| 379 |
cert_intel["version"] = version
|
| 380 |
cert_intel["cipher"] = cipher
|
| 381 |
|
|
|
|
| 382 |
from datetime import datetime
|
| 383 |
expiry = datetime.strptime(cert['notAfter'], '%b %d %H:%M:%S %Y %Z')
|
| 384 |
cert_intel["expired"] = expiry < datetime.now()
|
| 385 |
cert_intel["valid"] = True
|
| 386 |
|
|
|
|
| 387 |
for alt_name in cert.get('subjectAltName', []):
|
| 388 |
if alt_name[0] == 'DNS':
|
| 389 |
cert_intel["subjectAltNames"].append(alt_name[1])
|
|
@@ -393,6 +477,7 @@ class PassiveOSINTEngine:
|
|
| 393 |
return cert_intel
|
| 394 |
|
| 395 |
async def crt_sh_lookup(self, domain: str) -> List[str]:
|
|
|
|
| 396 |
subdomains = set()
|
| 397 |
try:
|
| 398 |
url = f"https://crt.sh/?q=%.{domain}&output=json"
|
|
@@ -412,6 +497,7 @@ class PassiveOSINTEngine:
|
|
| 412 |
return list(subdomains)
|
| 413 |
|
| 414 |
async def github_reconnaissance(self, org_name: str) -> Dict:
|
|
|
|
| 415 |
github_intel = {
|
| 416 |
"repositories": [],
|
| 417 |
"leaked_patterns": [],
|
|
@@ -421,6 +507,7 @@ class PassiveOSINTEngine:
|
|
| 421 |
}
|
| 422 |
|
| 423 |
try:
|
|
|
|
| 424 |
endpoint = f"https://api.github.com/users/{org_name}/repos"
|
| 425 |
headers = self.config.get_headers()
|
| 426 |
|
|
@@ -428,7 +515,7 @@ class PassiveOSINTEngine:
|
|
| 428 |
async with session.get(endpoint, headers=headers, timeout=10) as resp:
|
| 429 |
if resp.status == 200:
|
| 430 |
repos = await resp.json()
|
| 431 |
-
for repo in repos[:20]:
|
| 432 |
github_intel["repositories"].append({
|
| 433 |
"name": repo.get("name"),
|
| 434 |
"url": repo.get("html_url"),
|
|
@@ -442,6 +529,7 @@ class PassiveOSINTEngine:
|
|
| 442 |
if repo.get("language"):
|
| 443 |
github_intel["technology_hints"].append(repo.get("language"))
|
| 444 |
|
|
|
|
| 445 |
desc = (repo.get("description") or "").lower()
|
| 446 |
if any(x in desc for x in ['password', 'secret', 'key', 'token', 'credential']):
|
| 447 |
github_intel["leaked_patterns"].append({
|
|
@@ -449,6 +537,7 @@ class PassiveOSINTEngine:
|
|
| 449 |
"pattern": "Potential secret in description"
|
| 450 |
})
|
| 451 |
|
|
|
|
| 452 |
gist_endpoint = f"https://api.github.com/users/{org_name}/gists"
|
| 453 |
async with aiohttp.ClientSession() as session:
|
| 454 |
async with session.get(gist_endpoint, headers=headers, timeout=10) as resp:
|
|
@@ -466,6 +555,7 @@ class PassiveOSINTEngine:
|
|
| 466 |
return github_intel
|
| 467 |
|
| 468 |
async def wayback_machine_lookup(self, domain: str) -> List[str]:
|
|
|
|
| 469 |
urls = []
|
| 470 |
try:
|
| 471 |
endpoint = f"http://web.archive.org/cdx/search/cdx?url=*.{domain}/*&output=json&fl=original&collapse=urlkey"
|
|
@@ -475,24 +565,74 @@ class PassiveOSINTEngine:
|
|
| 475 |
async with session.get(endpoint, headers=headers, timeout=15) as resp:
|
| 476 |
if resp.status == 200:
|
| 477 |
data = await resp.json()
|
| 478 |
-
if len(data) > 1:
|
| 479 |
urls = [row[0] for row in data[1:]]
|
| 480 |
except Exception as e:
|
| 481 |
self.logger.error(f"Wayback lookup failed: {e}")
|
| 482 |
|
| 483 |
-
return urls[:100]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 484 |
|
| 485 |
# ════════════════════════════════════════════════════════════════════════════
|
| 486 |
# SECTION 5: ACTIVE RECONNAISSANCE ENGINE
|
| 487 |
# ════════════════════════════════════════════════════════════════════════════
|
| 488 |
|
| 489 |
class ActiveReconEngine:
|
|
|
|
|
|
|
| 490 |
def __init__(self, config: StealthConfig):
|
| 491 |
self.config = config
|
| 492 |
self.findings = []
|
| 493 |
self.logger = logging.getLogger("ActiveRecon")
|
| 494 |
|
| 495 |
async def fingerprint_technologies(self, url: str) -> Dict:
|
|
|
|
| 496 |
technologies = {
|
| 497 |
"web_server": None,
|
| 498 |
"cms": [],
|
|
@@ -509,18 +649,26 @@ class ActiveReconEngine:
|
|
| 509 |
headers = self.config.get_headers()
|
| 510 |
resp = requests.get(f"https://{url}", headers=headers, timeout=10, verify=False, allow_redirects=True)
|
| 511 |
|
|
|
|
| 512 |
if "Server" in resp.headers:
|
| 513 |
-
|
|
|
|
| 514 |
|
|
|
|
| 515 |
if "X-Powered-By" in resp.headers:
|
| 516 |
technologies["frameworks"].append(resp.headers["X-Powered-By"])
|
| 517 |
|
|
|
|
| 518 |
if "X-Generator" in resp.headers:
|
| 519 |
technologies["cms"].append(resp.headers["X-Generator"])
|
| 520 |
|
|
|
|
| 521 |
if "CF-RAY" in resp.headers or "Cloudflare" in resp.headers.get("Server", ""):
|
| 522 |
technologies["cdn"].append("Cloudflare")
|
|
|
|
|
|
|
| 523 |
|
|
|
|
| 524 |
for header, description in SECURITY_HEADERS.items():
|
| 525 |
if header in resp.headers:
|
| 526 |
technologies["security_headers"][header] = resp.headers[header]
|
|
@@ -529,6 +677,7 @@ class ActiveReconEngine:
|
|
| 529 |
|
| 530 |
content = resp.text
|
| 531 |
|
|
|
|
| 532 |
patterns = {
|
| 533 |
"WordPress": r"wp-content|wp-includes|/wp-admin|wordpress",
|
| 534 |
"Drupal": r"sites/default/files|drupal\\.css|drupal.js",
|
|
@@ -562,6 +711,7 @@ class ActiveReconEngine:
|
|
| 562 |
if tech not in technologies["analytics"]:
|
| 563 |
technologies["analytics"].append(tech)
|
| 564 |
|
|
|
|
| 565 |
if "Set-Cookie" in resp.headers:
|
| 566 |
cookies = resp.headers["Set-Cookie"]
|
| 567 |
if "PHPSESSID" in cookies:
|
|
@@ -575,10 +725,11 @@ class ActiveReconEngine:
|
|
| 575 |
return technologies
|
| 576 |
|
| 577 |
async def discover_endpoints(self, url: str, wordlist: List[str] = None) -> List[Dict]:
|
|
|
|
| 578 |
discovered = []
|
| 579 |
wordlist = wordlist or COMMON_ENDPOINTS
|
| 580 |
|
| 581 |
-
for path in wordlist[:50]:
|
| 582 |
try:
|
| 583 |
full_url = f"https://{url.rstrip('/')}/{path.lstrip('/')}"
|
| 584 |
headers = self.config.get_headers()
|
|
@@ -602,6 +753,7 @@ class ActiveReconEngine:
|
|
| 602 |
return discovered
|
| 603 |
|
| 604 |
def _extract_title(self, html: str) -> str:
|
|
|
|
| 605 |
try:
|
| 606 |
soup = BeautifulSoup(html, 'html.parser')
|
| 607 |
title = soup.find('title')
|
|
@@ -610,6 +762,7 @@ class ActiveReconEngine:
|
|
| 610 |
return "Error"
|
| 611 |
|
| 612 |
async def analyze_forms(self, url: str) -> List[Dict]:
|
|
|
|
| 613 |
forms = []
|
| 614 |
|
| 615 |
try:
|
|
@@ -638,11 +791,13 @@ class ActiveReconEngine:
|
|
| 638 |
}
|
| 639 |
form_data["fields"].append(field_info)
|
| 640 |
|
|
|
|
| 641 |
if field.get('type') == 'password':
|
| 642 |
-
form_data["vulnerabilities"].append("Password field detected")
|
| 643 |
if field.get('type') == 'file':
|
| 644 |
-
form_data["vulnerabilities"].append("File upload
|
| 645 |
|
|
|
|
| 646 |
has_csrf = any('csrf' in str(f.get('name', '')).lower() or
|
| 647 |
'token' in str(f.get('name', '')).lower()
|
| 648 |
for f in form_data["fields"])
|
|
@@ -657,12 +812,14 @@ class ActiveReconEngine:
|
|
| 657 |
return forms
|
| 658 |
|
| 659 |
async def extract_javascript_endpoints(self, url: str) -> List[Dict]:
|
|
|
|
| 660 |
endpoints = []
|
| 661 |
|
| 662 |
try:
|
| 663 |
headers = self.config.get_headers()
|
| 664 |
resp = requests.get(f"https://{url}", headers=headers, timeout=10, verify=False)
|
| 665 |
|
|
|
|
| 666 |
soup = BeautifulSoup(resp.text, 'html.parser')
|
| 667 |
scripts = []
|
| 668 |
|
|
@@ -670,6 +827,7 @@ class ActiveReconEngine:
|
|
| 670 |
if script.string:
|
| 671 |
scripts.append(script.string)
|
| 672 |
elif script.get('src'):
|
|
|
|
| 673 |
try:
|
| 674 |
src = script['src']
|
| 675 |
if src.startswith('http'):
|
|
@@ -682,6 +840,7 @@ class ActiveReconEngine:
|
|
| 682 |
except:
|
| 683 |
pass
|
| 684 |
|
|
|
|
| 685 |
api_patterns = [
|
| 686 |
r'["\']/(api|v[0-9]|rest|graphql)/[^"\'\\s]+["\']',
|
| 687 |
r'(https?://[^"\'\\s]+/api/[^"\'\\s]+)',
|
|
@@ -696,14 +855,15 @@ class ActiveReconEngine:
|
|
| 696 |
matches = re.findall(pattern, script_content)
|
| 697 |
for match in matches:
|
| 698 |
if isinstance(match, tuple):
|
| 699 |
-
match = match[-1]
|
| 700 |
if match and match not in [e["endpoint"] for e in endpoints]:
|
| 701 |
endpoints.append({
|
| 702 |
"endpoint": match,
|
| 703 |
-
"source": "
|
| 704 |
"type": "api"
|
| 705 |
})
|
| 706 |
|
|
|
|
| 707 |
secret_patterns = [
|
| 708 |
(r'api[_-]?key["\']?\\s*[:=]\\s*["\']([a-zA-Z0-9_\\-]{16,})["\']', "API Key"),
|
| 709 |
(r'secret[_-]?key["\']?\\s*[:=]\\s*["\']([a-zA-Z0-9_\\-]{16,})["\']', "Secret Key"),
|
|
@@ -718,7 +878,7 @@ class ActiveReconEngine:
|
|
| 718 |
matches = re.findall(pattern, script_content, re.IGNORECASE)
|
| 719 |
for match in matches:
|
| 720 |
endpoints.append({
|
| 721 |
-
"endpoint": f"[{secret_type} DETECTED]",
|
| 722 |
"source": "js_analysis",
|
| 723 |
"type": "secret",
|
| 724 |
"secret_type": secret_type
|
|
@@ -730,6 +890,7 @@ class ActiveReconEngine:
|
|
| 730 |
return endpoints
|
| 731 |
|
| 732 |
async def analyze_security_headers(self, url: str) -> Dict:
|
|
|
|
| 733 |
headers_analysis = {
|
| 734 |
"present": {},
|
| 735 |
"missing": [],
|
|
@@ -743,8 +904,8 @@ class ActiveReconEngine:
|
|
| 743 |
security_headers = {
|
| 744 |
"Strict-Transport-Security": {"weight": 3, "recommendation": "Implement HSTS"},
|
| 745 |
"Content-Security-Policy": {"weight": 3, "recommendation": "Implement CSP"},
|
| 746 |
-
"X-Frame-Options": {"weight": 2, "recommendation": "Set X-Frame-Options"},
|
| 747 |
-
"X-Content-Type-Options": {"weight": 2, "recommendation": "Set X-Content-Type-Options"},
|
| 748 |
"X-XSS-Protection": {"weight": 1, "recommendation": "Set X-XSS-Protection"},
|
| 749 |
"Referrer-Policy": {"weight": 1, "recommendation": "Implement Referrer-Policy"},
|
| 750 |
"Permissions-Policy": {"weight": 1, "recommendation": "Implement Permissions-Policy"}
|
|
@@ -769,113 +930,117 @@ class ActiveReconEngine:
|
|
| 769 |
return headers_analysis
|
| 770 |
|
| 771 |
async def check_common_vulnerabilities(self, url: str) -> List[Vulnerability]:
|
|
|
|
| 772 |
vulnerabilities = []
|
| 773 |
|
| 774 |
try:
|
| 775 |
headers = self.config.get_headers()
|
| 776 |
|
| 777 |
-
# Check .env
|
| 778 |
try:
|
| 779 |
env_resp = requests.get(f"https://{url}/.env", headers=headers, timeout=5, verify=False)
|
| 780 |
if env_resp.status_code == 200 and "=" in env_resp.text:
|
| 781 |
vuln = Vulnerability(
|
| 782 |
name="Exposed Environment File",
|
| 783 |
-
description="The .env file is publicly accessible",
|
| 784 |
severity="CRITICAL",
|
| 785 |
cvss_score=7.5,
|
| 786 |
cvss_vector="CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
|
| 787 |
location=f"https://{url}/.env",
|
| 788 |
-
evidence=".env file accessible",
|
| 789 |
-
remediation="Restrict access to .env files",
|
| 790 |
cwe_id="CWE-200",
|
| 791 |
-
owasp_category="A01:2021",
|
| 792 |
mitre_techniques=["T1083"]
|
| 793 |
)
|
| 794 |
vulnerabilities.append(vuln)
|
| 795 |
except:
|
| 796 |
pass
|
| 797 |
|
| 798 |
-
# Check .git
|
| 799 |
try:
|
| 800 |
git_resp = requests.get(f"https://{url}/.git/HEAD", headers=headers, timeout=5, verify=False)
|
| 801 |
if git_resp.status_code == 200 and "ref:" in git_resp.text:
|
| 802 |
vuln = Vulnerability(
|
| 803 |
name="Exposed Git Repository",
|
| 804 |
-
description="Git repository is publicly accessible",
|
| 805 |
severity="HIGH",
|
| 806 |
cvss_score=7.5,
|
| 807 |
cvss_vector="CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
|
| 808 |
location=f"https://{url}/.git/",
|
| 809 |
evidence="Git HEAD file accessible",
|
| 810 |
-
remediation="Restrict access to .git directory",
|
| 811 |
cwe_id="CWE-200",
|
| 812 |
-
owasp_category="A01:2021",
|
| 813 |
mitre_techniques=["T1083"]
|
| 814 |
)
|
| 815 |
vulnerabilities.append(vuln)
|
| 816 |
except:
|
| 817 |
pass
|
| 818 |
|
| 819 |
-
# Check directory listing
|
| 820 |
try:
|
| 821 |
dir_resp = requests.get(f"https://{url}/images/", headers=headers, timeout=5, verify=False)
|
| 822 |
if dir_resp.status_code == 200 and "Index of" in dir_resp.text:
|
| 823 |
vuln = Vulnerability(
|
| 824 |
name="Directory Listing Enabled",
|
| 825 |
-
description="Directory listing is enabled",
|
| 826 |
severity="MEDIUM",
|
| 827 |
cvss_score=5.3,
|
| 828 |
cvss_vector="CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N",
|
| 829 |
location=f"https://{url}/images/",
|
| 830 |
-
evidence="Directory index displayed",
|
| 831 |
-
remediation="Disable directory listing",
|
| 832 |
cwe_id="CWE-548",
|
| 833 |
-
owasp_category="A01:2021",
|
| 834 |
mitre_techniques=["T1083"]
|
| 835 |
)
|
| 836 |
vulnerabilities.append(vuln)
|
| 837 |
except:
|
| 838 |
pass
|
| 839 |
|
| 840 |
-
# Check SQL injection
|
| 841 |
test_url = f"https://{url}/?id=1'"
|
| 842 |
try:
|
| 843 |
sql_resp = requests.get(test_url, headers=headers, timeout=5, verify=False)
|
| 844 |
-
sql_errors = [
|
|
|
|
|
|
|
|
|
|
| 845 |
if any(error.lower() in sql_resp.text.lower() for error in sql_errors):
|
| 846 |
vuln = Vulnerability(
|
| 847 |
name="SQL Injection",
|
| 848 |
-
description="Potential SQL injection vulnerability",
|
| 849 |
severity="CRITICAL",
|
| 850 |
cvss_score=9.8,
|
| 851 |
cvss_vector="CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
|
| 852 |
location=test_url,
|
| 853 |
-
evidence="SQL error message",
|
| 854 |
-
remediation="Use parameterized queries",
|
| 855 |
cwe_id="CWE-89",
|
| 856 |
-
owasp_category="A03:2021",
|
| 857 |
mitre_techniques=["T1190"]
|
| 858 |
)
|
| 859 |
vulnerabilities.append(vuln)
|
| 860 |
except:
|
| 861 |
pass
|
| 862 |
|
| 863 |
-
# Check XSS
|
| 864 |
test_xss_url = f"https://{url}/?q=<script>alert(1)</script>"
|
| 865 |
try:
|
| 866 |
xss_resp = requests.get(test_xss_url, headers=headers, timeout=5, verify=False)
|
| 867 |
if "<script>alert(1)</script>" in xss_resp.text:
|
| 868 |
vuln = Vulnerability(
|
| 869 |
name="Cross-Site Scripting (XSS)",
|
| 870 |
-
description="Reflected XSS vulnerability",
|
| 871 |
severity="HIGH",
|
| 872 |
cvss_score=6.1,
|
| 873 |
cvss_vector="CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N",
|
| 874 |
location=test_xss_url,
|
| 875 |
-
evidence="Script tag reflected",
|
| 876 |
-
remediation="Implement output encoding",
|
| 877 |
cwe_id="CWE-79",
|
| 878 |
-
owasp_category="A03:2021",
|
| 879 |
mitre_techniques=["T1189"]
|
| 880 |
)
|
| 881 |
vulnerabilities.append(vuln)
|
|
@@ -887,27 +1052,22 @@ class ActiveReconEngine:
|
|
| 887 |
|
| 888 |
return vulnerabilities
|
| 889 |
|
| 890 |
-
'''
|
| 891 |
-
|
| 892 |
-
print("KODUN İLK YARISI HAZIR")
|
| 893 |
-
print("=" * 60)
|
| 894 |
-
print(f"Karakter sayısı: {len(fixed_code)}")
|
| 895 |
-
|
| 896 |
-
# Kodun ikinci yarısı
|
| 897 |
-
|
| 898 |
-
second_half = '''
|
| 899 |
# ════════════════════════════════════════════════════════════════════════════
|
| 900 |
-
# SECTION 6: THREAT MODELING ENGINE
|
| 901 |
# ════════════════════════════════════════════════════════════════════════════
|
| 902 |
|
| 903 |
class ThreatModelingEngine:
|
|
|
|
|
|
|
| 904 |
def __init__(self):
|
| 905 |
self.threats: List[Dict] = []
|
| 906 |
self.attack_paths: List[AttackPath] = []
|
| 907 |
|
| 908 |
def analyze_web_app(self, recon_data: Dict) -> List[ThreatVector]:
|
|
|
|
| 909 |
threat_vectors = []
|
| 910 |
|
|
|
|
| 911 |
for form in recon_data.get("forms", []):
|
| 912 |
risk = 7.5
|
| 913 |
techniques = ["T1565.001", "T1598.003"]
|
|
@@ -927,6 +1087,7 @@ class ThreatModelingEngine:
|
|
| 927 |
evidence=f"Form method: {form.get('method')}, Fields: {len(form.get('fields', []))}"
|
| 928 |
))
|
| 929 |
|
|
|
|
| 930 |
for js_file in recon_data.get("js_files", []):
|
| 931 |
threat_vectors.append(ThreatVector(
|
| 932 |
category="js_gadget",
|
|
@@ -939,6 +1100,7 @@ class ThreatModelingEngine:
|
|
| 939 |
evidence="Client-side code analysis"
|
| 940 |
))
|
| 941 |
|
|
|
|
| 942 |
for endpoint in recon_data.get("endpoints", []):
|
| 943 |
if isinstance(endpoint, dict):
|
| 944 |
path = endpoint.get("path", "")
|
|
@@ -958,12 +1120,13 @@ class ThreatModelingEngine:
|
|
| 958 |
location=path,
|
| 959 |
risk_score=risk,
|
| 960 |
techniques=["T1526"],
|
| 961 |
-
description=f"API endpoint: {path} (Status: {status})",
|
| 962 |
cvss_score=risk,
|
| 963 |
cwe_id="CWE-200",
|
| 964 |
evidence=f"HTTP {status}"
|
| 965 |
))
|
| 966 |
|
|
|
|
| 967 |
security_score = recon_data.get("security_headers", {}).get("score", 100)
|
| 968 |
if security_score < 50:
|
| 969 |
threat_vectors.append(ThreatVector(
|
|
@@ -980,30 +1143,34 @@ class ThreatModelingEngine:
|
|
| 980 |
return threat_vectors
|
| 981 |
|
| 982 |
def build_attack_paths(self, threat_vectors: List[ThreatVector], technologies: Dict) -> List[AttackPath]:
|
|
|
|
| 983 |
paths = []
|
| 984 |
|
|
|
|
| 985 |
paths.append(AttackPath(
|
| 986 |
entry_point="Public web form or API endpoint",
|
| 987 |
intermediate_steps=[
|
| 988 |
-
"Reconnaissance",
|
| 989 |
-
"Vulnerability identification",
|
| 990 |
"Exploitation",
|
| 991 |
-
"Data exfiltration"
|
| 992 |
],
|
| 993 |
-
objective="Unauthorized access",
|
| 994 |
risk_level="CRITICAL",
|
| 995 |
complexity=0.6,
|
| 996 |
mitre_techniques=["T1595", "T1190", "T1567"]
|
| 997 |
))
|
| 998 |
|
|
|
|
| 999 |
cms_list = technologies.get("cms", [])
|
| 1000 |
if "WordPress" in cms_list:
|
| 1001 |
paths.append(AttackPath(
|
| 1002 |
-
entry_point="WordPress admin",
|
| 1003 |
intermediate_steps=[
|
| 1004 |
-
"Plugin enumeration",
|
| 1005 |
-
"CVE exploitation",
|
| 1006 |
-
"RCE
|
|
|
|
| 1007 |
],
|
| 1008 |
objective="Remote Code Execution",
|
| 1009 |
risk_level="CRITICAL",
|
|
@@ -1011,24 +1178,44 @@ class ThreatModelingEngine:
|
|
| 1011 |
mitre_techniques=["T1595", "T1190", "T1059", "T1078"]
|
| 1012 |
))
|
| 1013 |
|
|
|
|
| 1014 |
api_endpoints = [v for v in threat_vectors if v.category == "api_endpoint"]
|
| 1015 |
if api_endpoints:
|
| 1016 |
paths.append(AttackPath(
|
| 1017 |
entry_point="Exposed API endpoint",
|
| 1018 |
intermediate_steps=[
|
| 1019 |
-
"API enumeration",
|
| 1020 |
-
"
|
| 1021 |
-
"IDOR
|
|
|
|
| 1022 |
],
|
| 1023 |
-
objective="
|
| 1024 |
risk_level="HIGH",
|
| 1025 |
complexity=0.5,
|
| 1026 |
mitre_techniques=["T1526", "T1078", "T1567"]
|
| 1027 |
))
|
| 1028 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1029 |
return paths
|
| 1030 |
|
| 1031 |
def generate_stride_report(self, recon_data: Dict) -> Dict:
|
|
|
|
| 1032 |
stride_report = {}
|
| 1033 |
|
| 1034 |
for threat_category, threat_info in STRIDE_THREATS.items():
|
|
@@ -1040,40 +1227,93 @@ class ThreatModelingEngine:
|
|
| 1040 |
"risk_level": "LOW"
|
| 1041 |
}
|
| 1042 |
|
|
|
|
| 1043 |
if "forms" in recon_data and len(recon_data["forms"]) > 0:
|
| 1044 |
if threat_category == "Tampering":
|
| 1045 |
-
stride_report[threat_category]["potential_impacts"].append(
|
|
|
|
|
|
|
| 1046 |
stride_report[threat_category]["affected_components"].append("Database")
|
| 1047 |
stride_report[threat_category]["risk_level"] = "CRITICAL"
|
| 1048 |
|
| 1049 |
if threat_category == "InformationDisclosure":
|
| 1050 |
-
stride_report[threat_category]["potential_impacts"].append(
|
|
|
|
|
|
|
| 1051 |
stride_report[threat_category]["risk_level"] = "HIGH"
|
| 1052 |
|
| 1053 |
if "endpoints" in recon_data and len(recon_data["endpoints"]) > 0:
|
| 1054 |
if threat_category == "InformationDisclosure":
|
| 1055 |
-
stride_report[threat_category]["potential_impacts"].append(
|
|
|
|
|
|
|
| 1056 |
stride_report[threat_category]["affected_components"].append("API")
|
| 1057 |
stride_report[threat_category]["risk_level"] = "HIGH"
|
| 1058 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1059 |
if "security_headers" in recon_data:
|
| 1060 |
score = recon_data["security_headers"].get("score", 100)
|
| 1061 |
if score < 50:
|
| 1062 |
if threat_category == "Spoofing":
|
| 1063 |
-
stride_report[threat_category]["potential_impacts"].append(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1064 |
stride_report[threat_category]["risk_level"] = "MEDIUM"
|
| 1065 |
|
| 1066 |
return stride_report
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1067 |
|
| 1068 |
# ════════════════════════════════════════════════════════════════════════════
|
| 1069 |
-
# SECTION 7: ATTACK GRAPH VISUALIZATION
|
| 1070 |
# ════════════════════════════════════════════════════════════════════════════
|
| 1071 |
|
| 1072 |
class AttackGraphEngine:
|
|
|
|
|
|
|
| 1073 |
@staticmethod
|
| 1074 |
def create_enhanced_attack_graph(threat_vectors: List[ThreatVector],
|
| 1075 |
attack_paths: List[AttackPath],
|
| 1076 |
vulnerabilities: List[Vulnerability] = None) -> Dict:
|
|
|
|
| 1077 |
|
| 1078 |
nodes = ["Attacker", "Internet", "Target Domain"]
|
| 1079 |
edges = [("Attacker", "Internet"), ("Internet", "Target Domain")]
|
|
@@ -1083,7 +1323,8 @@ class AttackGraphEngine:
|
|
| 1083 |
"Target Domain": {"type": "asset", "risk": 7, "layer": 2}
|
| 1084 |
}
|
| 1085 |
|
| 1086 |
-
|
|
|
|
| 1087 |
node_name = f"{vector.category.replace('_', ' ').title()}_{i+1}"
|
| 1088 |
nodes.append(node_name)
|
| 1089 |
edges.append(("Target Domain", node_name))
|
|
@@ -1096,9 +1337,10 @@ class AttackGraphEngine:
|
|
| 1096 |
"cwe": vector.cwe_id
|
| 1097 |
}
|
| 1098 |
|
|
|
|
| 1099 |
if vulnerabilities:
|
| 1100 |
for i, vuln in enumerate(vulnerabilities[:10]):
|
| 1101 |
-
node_name = f"Vuln: {vuln.name[:20]}"
|
| 1102 |
nodes.append(node_name)
|
| 1103 |
edges.append(("Target Domain", node_name))
|
| 1104 |
node_info[node_name] = {
|
|
@@ -1121,9 +1363,12 @@ class AttackGraphEngine:
|
|
| 1121 |
|
| 1122 |
@staticmethod
|
| 1123 |
def visualize_attack_graph_plotly(graph_data: Dict) -> go.Figure:
|
|
|
|
|
|
|
| 1124 |
G = nx.DiGraph()
|
| 1125 |
G.add_edges_from(graph_data["edges"])
|
| 1126 |
|
|
|
|
| 1127 |
pos = {}
|
| 1128 |
layers = defaultdict(list)
|
| 1129 |
|
|
@@ -1136,6 +1381,7 @@ class AttackGraphEngine:
|
|
| 1136 |
for i, node in enumerate(nodes):
|
| 1137 |
pos[node] = (layer * 3, (i - y_offset/2) * 2)
|
| 1138 |
|
|
|
|
| 1139 |
edge_x, edge_y = [], []
|
| 1140 |
for edge in G.edges():
|
| 1141 |
x0, y0 = pos[edge[0]]
|
|
@@ -1151,6 +1397,7 @@ class AttackGraphEngine:
|
|
| 1151 |
name='Attack Path'
|
| 1152 |
)
|
| 1153 |
|
|
|
|
| 1154 |
node_x, node_y, node_text, node_color, node_size, hover_text = [], [], [], [], [], []
|
| 1155 |
|
| 1156 |
for node in G.nodes():
|
|
@@ -1163,6 +1410,7 @@ class AttackGraphEngine:
|
|
| 1163 |
risk = node_info.get("risk", 5)
|
| 1164 |
node_type = node_info.get("type", "unknown")
|
| 1165 |
|
|
|
|
| 1166 |
if node_type == "attacker":
|
| 1167 |
node_color.append('#ff0000')
|
| 1168 |
elif node_type == "network":
|
|
@@ -1172,18 +1420,20 @@ class AttackGraphEngine:
|
|
| 1172 |
elif node_type == "exploit":
|
| 1173 |
node_color.append('#ff00ff')
|
| 1174 |
else:
|
|
|
|
| 1175 |
if risk >= 9:
|
| 1176 |
-
node_color.append('#ff0000')
|
| 1177 |
elif risk >= 7:
|
| 1178 |
-
node_color.append('#ff7700')
|
| 1179 |
elif risk >= 4:
|
| 1180 |
-
node_color.append('#ffcc00')
|
| 1181 |
else:
|
| 1182 |
-
node_color.append('#00ff00')
|
| 1183 |
|
| 1184 |
size = 40 if node_type in ["attacker", "asset"] else 30 + (risk * 1.5)
|
| 1185 |
node_size.append(size)
|
| 1186 |
|
|
|
|
| 1187 |
hover_info = f"<b>{node}</b><br>Type: {node_type}<br>Risk: {risk}"
|
| 1188 |
if node_info.get("cvss"):
|
| 1189 |
hover_info += f"<br>CVSS: {node_info['cvss']}"
|
|
@@ -1211,7 +1461,7 @@ class AttackGraphEngine:
|
|
| 1211 |
fig = go.Figure(data=[edge_trace, node_trace])
|
| 1212 |
fig.update_layout(
|
| 1213 |
title={
|
| 1214 |
-
'text': 'Advanced Attack Surface Graph',
|
| 1215 |
'font': {'size': 24, 'color': '#ff0000'},
|
| 1216 |
'x': 0.5
|
| 1217 |
},
|
|
@@ -1227,7 +1477,7 @@ class AttackGraphEngine:
|
|
| 1227 |
dict(
|
| 1228 |
x=0.02, y=0.98,
|
| 1229 |
xref='paper', yref='paper',
|
| 1230 |
-
text='Critical Risk<br
|
| 1231 |
showarrow=False,
|
| 1232 |
font=dict(size=12, color='white'),
|
| 1233 |
bgcolor='rgba(0,0,0,0.5)',
|
|
@@ -1238,90 +1488,382 @@ class AttackGraphEngine:
|
|
| 1238 |
)
|
| 1239 |
|
| 1240 |
return fig
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1241 |
|
| 1242 |
# ════════════════════════════════════════════════════════════════════════════
|
| 1243 |
-
# SECTION 8: REPORTING ENGINE
|
| 1244 |
# ════════════════════════════════════════════════════════════════════════════
|
| 1245 |
|
| 1246 |
class ReportingEngine:
|
|
|
|
|
|
|
| 1247 |
@staticmethod
|
| 1248 |
def generate_assessment_report(target: str, recon_data: Dict, threat_vectors: List[ThreatVector],
|
| 1249 |
attack_paths: List[AttackPath], stride_report: Dict,
|
| 1250 |
vulnerabilities: List[Vulnerability] = None) -> str:
|
|
|
|
| 1251 |
|
| 1252 |
vulns = vulnerabilities or []
|
| 1253 |
|
| 1254 |
-
|
| 1255 |
-
|
| 1256 |
-
|
| 1257 |
-
|
| 1258 |
-
|
| 1259 |
-
|
| 1260 |
-
|
| 1261 |
-
|
| 1262 |
-
|
| 1263 |
-
|
| 1264 |
-
|
| 1265 |
-
|
| 1266 |
-
|
| 1267 |
-
|
| 1268 |
-
|
| 1269 |
-
|
| 1270 |
-
|
| 1271 |
-
|
| 1272 |
-
|
| 1273 |
-
|
| 1274 |
-
|
| 1275 |
-
|
| 1276 |
-
|
| 1277 |
-
|
| 1278 |
-
|
| 1279 |
-
|
| 1280 |
-
|
| 1281 |
-
|
| 1282 |
-
|
| 1283 |
-
|
| 1284 |
-
|
| 1285 |
-
|
| 1286 |
-
|
| 1287 |
-
|
| 1288 |
-
|
| 1289 |
-
|
| 1290 |
-
|
| 1291 |
-
|
| 1292 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1293 |
for i, vuln in enumerate(vulns, 1):
|
| 1294 |
-
|
| 1295 |
-
|
| 1296 |
-
|
| 1297 |
-
|
| 1298 |
-
|
| 1299 |
-
|
| 1300 |
-
|
| 1301 |
-
|
| 1302 |
-
|
| 1303 |
-
|
| 1304 |
-
|
| 1305 |
-
|
| 1306 |
-
|
| 1307 |
-
|
| 1308 |
-
|
| 1309 |
-
|
| 1310 |
-
|
| 1311 |
-
|
| 1312 |
-
|
| 1313 |
-
|
| 1314 |
-
|
| 1315 |
-
|
| 1316 |
-
|
| 1317 |
-
|
| 1318 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1319 |
|
| 1320 |
# ════════════════════════════════════════════════════════════════════════════
|
| 1321 |
# SECTION 9: MAIN ORCHESTRATOR
|
| 1322 |
# ════════════════════════════════════════════════════════════════════════════
|
| 1323 |
|
| 1324 |
class RedTeamReconFramework:
|
|
|
|
|
|
|
| 1325 |
def __init__(self):
|
| 1326 |
self.stealth_config = StealthConfig(ThreatLevel.MEDIUM)
|
| 1327 |
self.passive_engine = PassiveOSINTEngine(self.stealth_config)
|
|
@@ -1331,6 +1873,8 @@ class RedTeamReconFramework:
|
|
| 1331 |
self.reporting = ReportingEngine()
|
| 1332 |
|
| 1333 |
async def execute_assessment(self, target_url: str) -> Dict:
|
|
|
|
|
|
|
| 1334 |
results = {
|
| 1335 |
"target": target_url,
|
| 1336 |
"timestamp": datetime.now().isoformat(),
|
|
@@ -1349,7 +1893,8 @@ class RedTeamReconFramework:
|
|
| 1349 |
}
|
| 1350 |
|
| 1351 |
try:
|
| 1352 |
-
|
|
|
|
| 1353 |
passive_data = await self.passive_engine.gather_dns_intel(target_url)
|
| 1354 |
results["subdomains"] = passive_data.get("subdomains", [])
|
| 1355 |
|
|
@@ -1360,18 +1905,22 @@ class RedTeamReconFramework:
|
|
| 1360 |
for san in ssl_data["subjectAltNames"]
|
| 1361 |
])
|
| 1362 |
|
|
|
|
| 1363 |
ct_subdomains = await self.passive_engine.crt_sh_lookup(target_url)
|
| 1364 |
for sub in ct_subdomains:
|
| 1365 |
if sub not in [s.get("subdomain") for s in results["subdomains"]]:
|
| 1366 |
results["subdomains"].append({"subdomain": sub, "ip": "from_ct"})
|
| 1367 |
|
|
|
|
| 1368 |
github_data = await self.passive_engine.github_reconnaissance(target_url.replace(".com", ""))
|
| 1369 |
results["github_intel"] = github_data
|
| 1370 |
|
|
|
|
| 1371 |
wayback_urls = await self.passive_engine.wayback_machine_lookup(target_url)
|
| 1372 |
results["historical_urls"] = wayback_urls
|
| 1373 |
|
| 1374 |
-
|
|
|
|
| 1375 |
technologies = await self.active_engine.fingerprint_technologies(target_url)
|
| 1376 |
results["technologies"] = technologies
|
| 1377 |
|
|
@@ -1387,11 +1936,13 @@ class RedTeamReconFramework:
|
|
| 1387 |
security_headers = await self.active_engine.analyze_security_headers(target_url)
|
| 1388 |
results["security_headers"] = security_headers
|
| 1389 |
|
| 1390 |
-
|
|
|
|
| 1391 |
vulnerabilities = await self.active_engine.check_common_vulnerabilities(target_url)
|
| 1392 |
results["vulnerabilities"] = [asdict(v) for v in vulnerabilities]
|
| 1393 |
|
| 1394 |
-
|
|
|
|
| 1395 |
threat_vectors = self.threat_model.analyze_web_app(results)
|
| 1396 |
results["threat_vectors"] = [asdict(tv) for tv in threat_vectors]
|
| 1397 |
|
|
@@ -1401,19 +1952,21 @@ class RedTeamReconFramework:
|
|
| 1401 |
stride_analysis = self.threat_model.generate_stride_report(results)
|
| 1402 |
results["stride_analysis"] = stride_analysis
|
| 1403 |
|
| 1404 |
-
|
|
|
|
| 1405 |
graph_data = self.graph_engine.create_enhanced_attack_graph(
|
| 1406 |
threat_vectors, attack_paths, vulnerabilities
|
| 1407 |
)
|
| 1408 |
results["graph_data"] = graph_data
|
| 1409 |
|
| 1410 |
-
|
|
|
|
| 1411 |
report = self.reporting.generate_assessment_report(
|
| 1412 |
target_url, results, threat_vectors, attack_paths, stride_analysis, vulnerabilities
|
| 1413 |
)
|
| 1414 |
results["report"] = report
|
| 1415 |
|
| 1416 |
-
print("Assessment complete!")
|
| 1417 |
|
| 1418 |
except Exception as e:
|
| 1419 |
results["error"] = str(e)
|
|
@@ -1423,21 +1976,26 @@ class RedTeamReconFramework:
|
|
| 1423 |
|
| 1424 |
return results
|
| 1425 |
|
| 1426 |
-
|
| 1427 |
# SECTION 10: GRADIO INTERFACE
|
| 1428 |
# ════════════════════════════════════════════════════════════════════════════
|
| 1429 |
|
|
|
|
| 1430 |
framework = RedTeamReconFramework()
|
| 1431 |
|
| 1432 |
def run_assessment(target_url: str, threat_level: str, progress=gr.Progress(track_tqdm=True)):
|
|
|
|
|
|
|
| 1433 |
try:
|
| 1434 |
if not target_url:
|
| 1435 |
-
return "Error: Please enter a target domain", "{}", go.Figure(), "No report"
|
| 1436 |
|
|
|
|
| 1437 |
target_url = target_url.replace("https://", "").replace("http://", "").strip("/")
|
| 1438 |
|
| 1439 |
-
progress(0.1, desc="Validating target...")
|
| 1440 |
|
|
|
|
| 1441 |
threat_map = {
|
| 1442 |
"Low (Stealthy)": ThreatLevel.LOW,
|
| 1443 |
"Medium (Balanced)": ThreatLevel.MEDIUM,
|
|
@@ -1445,56 +2003,67 @@ def run_assessment(target_url: str, threat_level: str, progress=gr.Progress(trac
|
|
| 1445 |
}
|
| 1446 |
framework.stealth_config = StealthConfig(threat_map.get(threat_level, ThreatLevel.MEDIUM))
|
| 1447 |
|
| 1448 |
-
progress(0.2, desc="Starting passive OSINT...")
|
| 1449 |
-
progress(0.4, desc="Running active reconnaissance...")
|
| 1450 |
-
progress(0.6, desc="Analyzing threats...")
|
| 1451 |
-
progress(0.8, desc="Generating attack graph...")
|
| 1452 |
|
|
|
|
| 1453 |
loop = asyncio.new_event_loop()
|
| 1454 |
asyncio.set_event_loop(loop)
|
| 1455 |
results = loop.run_until_complete(framework.execute_assessment(target_url))
|
| 1456 |
loop.close()
|
| 1457 |
|
| 1458 |
-
progress(0.95, desc="Finalizing report...")
|
| 1459 |
|
|
|
|
| 1460 |
if results.get("graph_data"):
|
| 1461 |
fig = framework.graph_engine.visualize_attack_graph_plotly(results["graph_data"])
|
| 1462 |
else:
|
| 1463 |
fig = go.Figure()
|
| 1464 |
|
|
|
|
| 1465 |
vulns = results.get("vulnerabilities", [])
|
| 1466 |
critical = len([v for v in vulns if v.get("cvss_score", 0) >= 9.0])
|
| 1467 |
high = len([v for v in vulns if 7.0 <= v.get("cvss_score", 0) < 9.0])
|
| 1468 |
medium = len([v for v in vulns if 4.0 <= v.get("cvss_score", 0) < 7.0])
|
| 1469 |
|
| 1470 |
-
|
| 1471 |
-
|
|
|
|
| 1472 |
|
| 1473 |
**Target:** {target_url}
|
| 1474 |
**Date:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
|
| 1475 |
**Threat Level:** {threat_level}
|
| 1476 |
|
| 1477 |
-
###
|
| 1478 |
-
- Subdomains: {len(results.get('subdomains', []))}
|
| 1479 |
-
- Technologies: {len(results.get('technologies', {}).get('cms', [])) + len(results.get('technologies', {}).get('frameworks', []))}
|
| 1480 |
-
- Endpoints: {len(results.get('endpoints', []))}
|
| 1481 |
-
- Forms: {len(results.get('forms', []))}
|
| 1482 |
-
-
|
| 1483 |
-
-
|
| 1484 |
-
|
| 1485 |
-
|
| 1486 |
-
|
| 1487 |
-
-
|
| 1488 |
-
-
|
| 1489 |
-
|
| 1490 |
-
|
| 1491 |
-
|
| 1492 |
-
-
|
| 1493 |
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1494 |
"""
|
| 1495 |
|
| 1496 |
return (
|
| 1497 |
-
|
| 1498 |
json.dumps(results, indent=2, default=str),
|
| 1499 |
fig,
|
| 1500 |
results.get("report", "No report generated")
|
|
@@ -1504,33 +2073,41 @@ def run_assessment(target_url: str, threat_level: str, progress=gr.Progress(trac
|
|
| 1504 |
error_msg = f"Error: {str(e)}"
|
| 1505 |
import traceback
|
| 1506 |
error_detail = traceback.format_exc()
|
| 1507 |
-
return error_msg,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1508 |
|
| 1509 |
def create_interface():
|
|
|
|
|
|
|
| 1510 |
with gr.Blocks(
|
| 1511 |
theme=gr.themes.Soft(primary_hue="red"),
|
| 1512 |
title="Red Team Recon Framework v3.0",
|
| 1513 |
css="""
|
|
|
|
| 1514 |
.disclaimer { background-color: #ffeeee; padding: 10px; border-left: 5px solid #ff0000; }
|
| 1515 |
"""
|
| 1516 |
) as demo:
|
| 1517 |
|
| 1518 |
gr.Markdown("""
|
| 1519 |
-
#
|
| 1520 |
### Professional Security Assessment Tool - Private Space Edition
|
| 1521 |
|
| 1522 |
<div class="disclaimer">
|
| 1523 |
-
<strong>DISCLAIMER:</strong>
|
| 1524 |
-
Unauthorized access is illegal.
|
|
|
|
| 1525 |
</div>
|
| 1526 |
|
| 1527 |
**Features:**
|
| 1528 |
-
- Passive OSINT (DNS, SSL, GitHub, crt.sh, Wayback)
|
| 1529 |
-
- Active Reconnaissance (Fingerprinting, endpoint discovery)
|
| 1530 |
-
- Vulnerability Analysis (Pattern-based detection)
|
| 1531 |
-
- Threat Modeling (STRIDE + MITRE ATT&CK)
|
| 1532 |
-
- Attack Surface Visualization
|
| 1533 |
-
- Professional Reporting
|
| 1534 |
""")
|
| 1535 |
|
| 1536 |
with gr.Row():
|
|
@@ -1544,49 +2121,120 @@ def create_interface():
|
|
| 1544 |
threat_level = gr.Radio(
|
| 1545 |
choices=["Low (Stealthy)", "Medium (Balanced)", "High (Aggressive)"],
|
| 1546 |
value="Medium (Balanced)",
|
| 1547 |
-
label="Threat Level"
|
| 1548 |
)
|
| 1549 |
|
| 1550 |
-
scan_button = gr.Button("START ASSESSMENT", variant="primary", size="lg")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1551 |
|
| 1552 |
with gr.Column(scale=1):
|
| 1553 |
gr.Markdown("""
|
| 1554 |
-
### Methodology
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1555 |
|
| 1556 |
-
|
| 1557 |
-
|
| 1558 |
-
|
| 1559 |
-
|
| 1560 |
-
|
| 1561 |
""")
|
| 1562 |
|
| 1563 |
with gr.Tabs():
|
| 1564 |
-
with gr.Tab("Summary"):
|
| 1565 |
summary_output = gr.Markdown(label="Assessment Summary")
|
| 1566 |
|
| 1567 |
-
with gr.Tab("Attack Graph"):
|
| 1568 |
graph_output = gr.Plot(label="Attack Surface Visualization")
|
| 1569 |
|
| 1570 |
-
with gr.Tab("Raw Data"):
|
| 1571 |
-
json_output = gr.Code(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1572 |
|
| 1573 |
-
with gr.Tab("
|
| 1574 |
-
|
| 1575 |
|
|
|
|
| 1576 |
scan_button.click(
|
| 1577 |
fn=run_assessment,
|
| 1578 |
inputs=[target_input, threat_level],
|
| 1579 |
outputs=[summary_output, json_output, graph_output, report_output]
|
| 1580 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1581 |
|
| 1582 |
return demo
|
| 1583 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1584 |
if __name__ == "__main__":
|
| 1585 |
demo = create_interface()
|
| 1586 |
demo.launch(
|
| 1587 |
-
share=False,
|
| 1588 |
server_name="0.0.0.0",
|
| 1589 |
server_port=7860,
|
| 1590 |
show_error=True
|
| 1591 |
)
|
| 1592 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
|
| 2 |
+
# BÖLÜM 1: KODUN 1-7. BÖLÜMLERİ
|
| 3 |
+
# Bu dosyayı app_part1.py olarak kaydedin
|
| 4 |
+
|
| 5 |
═══════════════════════════════════════════════════════════════════════════════
|
| 6 |
+
PRIVATE RED TEAM WEB RECONNAISSANCE FRAMEWORK v3.0 - PART 1
|
| 7 |
─────────────────────────────────────────────────────────────────────────
|
| 8 |
+
Bölümler: 1-7 (Configuration, Data Models, Stealth, OSINT, Active Recon,
|
| 9 |
+
Threat Modeling, Attack Graph)
|
| 10 |
+
═══════════════════════════════════════════════════════════════════════════════
|
| 11 |
+
"""
|
| 12 |
|
| 13 |
import gradio as gr
|
| 14 |
import asyncio
|
|
|
|
| 41 |
# ════════════════════════════════════════════════════════════════════════════
|
| 42 |
|
| 43 |
class ThreatLevel(Enum):
|
| 44 |
+
"""Threat/Risk Assessment Levels"""
|
| 45 |
LOW = 0
|
| 46 |
MEDIUM = 1
|
| 47 |
HIGH = 2
|
| 48 |
CRITICAL = 3
|
| 49 |
|
| 50 |
+
class CVESSeverity(Enum):
|
| 51 |
+
"""CVSS Severity Ratings"""
|
| 52 |
+
CRITICAL = (9.0, 10.0)
|
| 53 |
+
HIGH = (7.0, 8.9)
|
| 54 |
+
MEDIUM = (4.0, 6.9)
|
| 55 |
+
LOW = (0.1, 3.9)
|
| 56 |
+
|
| 57 |
+
# STRIDE Threat Model
|
| 58 |
STRIDE_THREATS = {
|
| 59 |
"Spoofing": {
|
| 60 |
"description": "Identity spoofing",
|
|
|
|
| 88 |
}
|
| 89 |
}
|
| 90 |
|
| 91 |
+
# Extended MITRE ATT&CK Matrix
|
| 92 |
MITRE_TECHNIQUES = {
|
| 93 |
"Reconnaissance": {
|
| 94 |
"T1592": "Gather Victim Host Information",
|
|
|
|
| 150 |
}
|
| 151 |
}
|
| 152 |
|
| 153 |
+
# Technology fingerprints - Extended
|
| 154 |
+
TECH_FINGERPRINTS = {
|
| 155 |
+
"Web Servers": {
|
| 156 |
+
"Apache": [r"Server: Apache", r"X-Powered-By: Apache"],
|
| 157 |
+
"Nginx": [r"Server: nginx", r"X-Nginx"],
|
| 158 |
+
"IIS": [r"Server: Microsoft-IIS"],
|
| 159 |
+
"Cloudflare": [r"CF-RAY", r"Cloudflare"],
|
| 160 |
+
"AWS": [r"X-Amz", r"AmazonS3"],
|
| 161 |
+
"Azure": [r"Azure", r"Microsoft-IIS"]
|
| 162 |
+
},
|
| 163 |
+
"CMS": {
|
| 164 |
+
"WordPress": [r"/wp-admin", r"wp-content", r"wp_.*"],
|
| 165 |
+
"Drupal": [r"/sites/default", r"drupal\\.css"],
|
| 166 |
+
"Joomla": [r"/administrator", r"com_content"],
|
| 167 |
+
"Magento": [r"/skin/frontend", r"Mage.Cookies"],
|
| 168 |
+
"Shopify": [r"cdn.shopify.com", r"Shopify.theme"]
|
| 169 |
+
},
|
| 170 |
+
"Frameworks": {
|
| 171 |
+
"Django": [r"CSRF", r"django_session"],
|
| 172 |
+
"Flask": [r"werkzeug", r"Flask"],
|
| 173 |
+
"Laravel": [r"XSRF-TOKEN", r"laravel_session"],
|
| 174 |
+
"Spring": [r"JSESSIONID", r"spring"],
|
| 175 |
+
"Ruby on Rails": [r"_rails", r"authenticity_token"],
|
| 176 |
+
"ASP.NET": [r"ASP.NET_SessionId", r"__VIEWSTATE"]
|
| 177 |
+
},
|
| 178 |
+
"JavaScript": {
|
| 179 |
+
"React": [r"__REACT", r"react\\.js"],
|
| 180 |
+
"Vue": [r"__VUE", r"vue\\.js"],
|
| 181 |
+
"Angular": [r"ng-app", r"angular\\.js"],
|
| 182 |
+
"jQuery": [r"jquery", r"jQuery"],
|
| 183 |
+
"Bootstrap": [r"bootstrap", r"data-toggle"]
|
| 184 |
+
},
|
| 185 |
+
"Databases": {
|
| 186 |
+
"MySQL": [r"MySQL", r"sqlstate"],
|
| 187 |
+
"PostgreSQL": [r"PostgreSQL", r"pg_query"],
|
| 188 |
+
"MongoDB": [r"MongoDB", r"mongod"],
|
| 189 |
+
"Redis": [r"Redis", r"redis-cli"]
|
| 190 |
+
}
|
| 191 |
+
}
|
| 192 |
+
|
| 193 |
+
# Security Headers to check
|
| 194 |
SECURITY_HEADERS = {
|
| 195 |
"Strict-Transport-Security": "HSTS",
|
| 196 |
"Content-Security-Policy": "CSP",
|
|
|
|
| 201 |
"Permissions-Policy": "Feature Policy"
|
| 202 |
}
|
| 203 |
|
| 204 |
+
# Common endpoints for discovery
|
| 205 |
COMMON_ENDPOINTS = [
|
| 206 |
"", "admin", "api", "login", "test", "debug", "config",
|
| 207 |
"api/users", "api/admin", "api/auth", "api/data", "api/v1",
|
|
|
|
| 219 |
|
| 220 |
@dataclass
|
| 221 |
class IntelligenceIndicator:
|
| 222 |
+
"""IOC - Indicator of Compromise"""
|
| 223 |
type: str
|
| 224 |
value: str
|
| 225 |
confidence: float
|
|
|
|
| 229 |
|
| 230 |
@dataclass
|
| 231 |
class ThreatVector:
|
| 232 |
+
"""Attack surface element"""
|
| 233 |
category: str
|
| 234 |
location: str
|
| 235 |
risk_score: float
|
|
|
|
| 241 |
|
| 242 |
@dataclass
|
| 243 |
class AttackPath:
|
| 244 |
+
"""End-to-end attack chain"""
|
| 245 |
entry_point: str
|
| 246 |
intermediate_steps: List[str]
|
| 247 |
objective: str
|
|
|
|
| 255 |
|
| 256 |
@dataclass
|
| 257 |
class Vulnerability:
|
| 258 |
+
"""Vulnerability finding"""
|
| 259 |
name: str
|
| 260 |
description: str
|
| 261 |
severity: str
|
|
|
|
| 277 |
# ════════════════════════════════════════════════════════════════════════════
|
| 278 |
|
| 279 |
class StealthConfig:
|
| 280 |
+
"""Anti-detection & evasion configuration"""
|
| 281 |
+
|
| 282 |
def __init__(self, threat_level: ThreatLevel = ThreatLevel.MEDIUM):
|
| 283 |
self.threat_level = threat_level
|
| 284 |
|
|
|
|
| 309 |
self.current_proxy = 0
|
| 310 |
|
| 311 |
def get_delay(self) -> float:
|
| 312 |
+
"""Random delay to avoid pattern detection"""
|
| 313 |
min_d, max_d = self.delay_ranges[self.threat_level]
|
| 314 |
return random.uniform(min_d, max_d) / 1000
|
| 315 |
|
| 316 |
def get_headers(self) -> Dict[str, str]:
|
| 317 |
+
"""Anti-fingerprinting headers"""
|
| 318 |
headers = {
|
| 319 |
"User-Agent": random.choice(self.user_agents),
|
| 320 |
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
|
|
|
|
| 330 |
"Sec-Fetch-User": "?1"
|
| 331 |
}
|
| 332 |
return headers
|
| 333 |
+
|
| 334 |
+
def get_proxy(self) -> Optional[Dict]:
|
| 335 |
+
"""Rotate proxies if available"""
|
| 336 |
+
if not self.proxies:
|
| 337 |
+
return None
|
| 338 |
+
proxy = self.proxies[self.current_proxy % len(self.proxies)]
|
| 339 |
+
self.current_proxy += 1
|
| 340 |
+
return proxy
|
| 341 |
|
| 342 |
# ════════════════════════════════════════════════════════════════════════════
|
| 343 |
# SECTION 4: PASSIVE OSINT ENGINE
|
| 344 |
# ════════════════════════════════════════════════════════════════════════════
|
| 345 |
|
| 346 |
class PassiveOSINTEngine:
|
| 347 |
+
"""Passive reconnaissance without alerting target"""
|
| 348 |
+
|
| 349 |
def __init__(self, config: StealthConfig):
|
| 350 |
self.config = config
|
| 351 |
self.indicators: Dict[str, List[IntelligenceIndicator]] = defaultdict(list)
|
|
|
|
| 356 |
return logging.getLogger("PassiveOSINT")
|
| 357 |
|
| 358 |
async def gather_dns_intel(self, domain: str) -> Dict:
|
| 359 |
+
"""DNS records, subdomains from public sources"""
|
| 360 |
intel = {
|
| 361 |
"subdomains": [],
|
| 362 |
"mx_records": [],
|
|
|
|
| 370 |
try:
|
| 371 |
import dns.resolver
|
| 372 |
|
| 373 |
+
# Try common subdomains
|
| 374 |
common_subs = [
|
| 375 |
"www", "mail", "ftp", "admin", "api", "dev", "staging",
|
| 376 |
"cdn", "test", "blog", "shop", "support", "docs", "app",
|
|
|
|
| 391 |
except:
|
| 392 |
pass
|
| 393 |
|
| 394 |
+
# Try AAAA records
|
| 395 |
try:
|
| 396 |
full_domain = f"{sub}.{domain}"
|
| 397 |
result = dns.resolver.resolve(full_domain, 'AAAA')
|
|
|
|
| 403 |
except:
|
| 404 |
pass
|
| 405 |
|
| 406 |
+
# MX records
|
| 407 |
try:
|
| 408 |
mx = dns.resolver.resolve(domain, 'MX')
|
| 409 |
intel["mx_records"] = [{"preference": r.preference, "exchange": str(r.exchange)} for r in mx]
|
| 410 |
except:
|
| 411 |
pass
|
| 412 |
|
| 413 |
+
# NS records
|
| 414 |
try:
|
| 415 |
ns = dns.resolver.resolve(domain, 'NS')
|
| 416 |
intel["ns_records"] = [str(r) for r in ns]
|
| 417 |
except:
|
| 418 |
pass
|
| 419 |
|
| 420 |
+
# TXT records (SPF, DKIM, DMARC)
|
| 421 |
try:
|
| 422 |
txt = dns.resolver.resolve(domain, 'TXT')
|
| 423 |
intel["txt_records"] = [str(r) for r in txt]
|
|
|
|
| 430 |
return intel
|
| 431 |
|
| 432 |
async def gather_ssl_cert_intel(self, domain: str) -> Dict:
|
| 433 |
+
"""SSL certificate analysis for subdomains"""
|
| 434 |
cert_intel = {
|
| 435 |
"subject": None,
|
| 436 |
"issuer": None,
|
|
|
|
| 461 |
cert_intel["version"] = version
|
| 462 |
cert_intel["cipher"] = cipher
|
| 463 |
|
| 464 |
+
# Check expiration
|
| 465 |
from datetime import datetime
|
| 466 |
expiry = datetime.strptime(cert['notAfter'], '%b %d %H:%M:%S %Y %Z')
|
| 467 |
cert_intel["expired"] = expiry < datetime.now()
|
| 468 |
cert_intel["valid"] = True
|
| 469 |
|
| 470 |
+
# Extract SANs
|
| 471 |
for alt_name in cert.get('subjectAltName', []):
|
| 472 |
if alt_name[0] == 'DNS':
|
| 473 |
cert_intel["subjectAltNames"].append(alt_name[1])
|
|
|
|
| 477 |
return cert_intel
|
| 478 |
|
| 479 |
async def crt_sh_lookup(self, domain: str) -> List[str]:
|
| 480 |
+
"""Query Certificate Transparency logs via crt.sh"""
|
| 481 |
subdomains = set()
|
| 482 |
try:
|
| 483 |
url = f"https://crt.sh/?q=%.{domain}&output=json"
|
|
|
|
| 497 |
return list(subdomains)
|
| 498 |
|
| 499 |
async def github_reconnaissance(self, org_name: str) -> Dict:
|
| 500 |
+
"""Search GitHub for organization info"""
|
| 501 |
github_intel = {
|
| 502 |
"repositories": [],
|
| 503 |
"leaked_patterns": [],
|
|
|
|
| 507 |
}
|
| 508 |
|
| 509 |
try:
|
| 510 |
+
# Search repos
|
| 511 |
endpoint = f"https://api.github.com/users/{org_name}/repos"
|
| 512 |
headers = self.config.get_headers()
|
| 513 |
|
|
|
|
| 515 |
async with session.get(endpoint, headers=headers, timeout=10) as resp:
|
| 516 |
if resp.status == 200:
|
| 517 |
repos = await resp.json()
|
| 518 |
+
for repo in repos[:20]: # Limit to 20
|
| 519 |
github_intel["repositories"].append({
|
| 520 |
"name": repo.get("name"),
|
| 521 |
"url": repo.get("html_url"),
|
|
|
|
| 529 |
if repo.get("language"):
|
| 530 |
github_intel["technology_hints"].append(repo.get("language"))
|
| 531 |
|
| 532 |
+
# Check for common leaked patterns in repo names/descriptions
|
| 533 |
desc = (repo.get("description") or "").lower()
|
| 534 |
if any(x in desc for x in ['password', 'secret', 'key', 'token', 'credential']):
|
| 535 |
github_intel["leaked_patterns"].append({
|
|
|
|
| 537 |
"pattern": "Potential secret in description"
|
| 538 |
})
|
| 539 |
|
| 540 |
+
# Search for gists
|
| 541 |
gist_endpoint = f"https://api.github.com/users/{org_name}/gists"
|
| 542 |
async with aiohttp.ClientSession() as session:
|
| 543 |
async with session.get(gist_endpoint, headers=headers, timeout=10) as resp:
|
|
|
|
| 555 |
return github_intel
|
| 556 |
|
| 557 |
async def wayback_machine_lookup(self, domain: str) -> List[str]:
|
| 558 |
+
"""Query Wayback Machine for historical URLs"""
|
| 559 |
urls = []
|
| 560 |
try:
|
| 561 |
endpoint = f"http://web.archive.org/cdx/search/cdx?url=*.{domain}/*&output=json&fl=original&collapse=urlkey"
|
|
|
|
| 565 |
async with session.get(endpoint, headers=headers, timeout=15) as resp:
|
| 566 |
if resp.status == 200:
|
| 567 |
data = await resp.json()
|
| 568 |
+
if len(data) > 1: # First row is headers
|
| 569 |
urls = [row[0] for row in data[1:]]
|
| 570 |
except Exception as e:
|
| 571 |
self.logger.error(f"Wayback lookup failed: {e}")
|
| 572 |
|
| 573 |
+
return urls[:100] # Limit to 100
|
| 574 |
+
|
| 575 |
+
async def exposed_data_check(self, domain: str) -> List[Dict]:
|
| 576 |
+
"""Check if domain in breach databases"""
|
| 577 |
+
breaches = []
|
| 578 |
+
|
| 579 |
+
try:
|
| 580 |
+
# HIBP API (requires key in production, placeholder here)
|
| 581 |
+
# endpoint = f"https://haveibeenpwned.com/api/v3/breaches?domain={domain}"
|
| 582 |
+
# headers = {"User-Agent": "RedTeamFramework/3.0", "hibp-api-key": "YOUR_API_KEY"}
|
| 583 |
+
# resp = requests.get(endpoint, headers=headers, timeout=5)
|
| 584 |
+
# if resp.status_code == 200:
|
| 585 |
+
# breaches = resp.json()
|
| 586 |
+
pass
|
| 587 |
+
except:
|
| 588 |
+
pass
|
| 589 |
+
|
| 590 |
+
return breaches
|
| 591 |
+
|
| 592 |
+
async def shodan_lookup(self, domain: str) -> Dict:
|
| 593 |
+
"""Shodan host lookup (requires API key)"""
|
| 594 |
+
shodan_data = {
|
| 595 |
+
"ip": None,
|
| 596 |
+
"ports": [],
|
| 597 |
+
"services": [],
|
| 598 |
+
"vulnerabilities": [],
|
| 599 |
+
"hostnames": [],
|
| 600 |
+
"location": {}
|
| 601 |
+
}
|
| 602 |
+
|
| 603 |
+
try:
|
| 604 |
+
# Placeholder - requires Shodan API key
|
| 605 |
+
# import shodan
|
| 606 |
+
# api = shodan.Shodan("YOUR_API_KEY")
|
| 607 |
+
# host = api.host(domain)
|
| 608 |
+
# shodan_data = {
|
| 609 |
+
# "ip": host['ip_str'],
|
| 610 |
+
# "ports": host['ports'],
|
| 611 |
+
# "services": [match['product'] for match in host['data']],
|
| 612 |
+
# "vulnerabilities": host.get('vulns', []),
|
| 613 |
+
# "hostnames": host.get('hostnames', []),
|
| 614 |
+
# "location": host.get('location', {})
|
| 615 |
+
# }
|
| 616 |
+
pass
|
| 617 |
+
except:
|
| 618 |
+
pass
|
| 619 |
+
|
| 620 |
+
return shodan_data
|
| 621 |
|
| 622 |
# ════════════════════════════════════════════════════════════════════════════
|
| 623 |
# SECTION 5: ACTIVE RECONNAISSANCE ENGINE
|
| 624 |
# ════════════════════════════════════════════════════════════════════════════
|
| 625 |
|
| 626 |
class ActiveReconEngine:
|
| 627 |
+
"""Active scanning with OPSEC measures"""
|
| 628 |
+
|
| 629 |
def __init__(self, config: StealthConfig):
|
| 630 |
self.config = config
|
| 631 |
self.findings = []
|
| 632 |
self.logger = logging.getLogger("ActiveRecon")
|
| 633 |
|
| 634 |
async def fingerprint_technologies(self, url: str) -> Dict:
|
| 635 |
+
"""Identify technologies from headers, HTML, JS"""
|
| 636 |
technologies = {
|
| 637 |
"web_server": None,
|
| 638 |
"cms": [],
|
|
|
|
| 649 |
headers = self.config.get_headers()
|
| 650 |
resp = requests.get(f"https://{url}", headers=headers, timeout=10, verify=False, allow_redirects=True)
|
| 651 |
|
| 652 |
+
# Server header analysis
|
| 653 |
if "Server" in resp.headers:
|
| 654 |
+
server = resp.headers["Server"]
|
| 655 |
+
technologies["web_server"] = server
|
| 656 |
|
| 657 |
+
# X-Powered-By
|
| 658 |
if "X-Powered-By" in resp.headers:
|
| 659 |
technologies["frameworks"].append(resp.headers["X-Powered-By"])
|
| 660 |
|
| 661 |
+
# X-Generator (CMS)
|
| 662 |
if "X-Generator" in resp.headers:
|
| 663 |
technologies["cms"].append(resp.headers["X-Generator"])
|
| 664 |
|
| 665 |
+
# CDN detection
|
| 666 |
if "CF-RAY" in resp.headers or "Cloudflare" in resp.headers.get("Server", ""):
|
| 667 |
technologies["cdn"].append("Cloudflare")
|
| 668 |
+
if "X-Cache" in resp.headers or "Fastly" in str(resp.headers):
|
| 669 |
+
technologies["cdn"].append("Fastly")
|
| 670 |
|
| 671 |
+
# Security headers analysis
|
| 672 |
for header, description in SECURITY_HEADERS.items():
|
| 673 |
if header in resp.headers:
|
| 674 |
technologies["security_headers"][header] = resp.headers[header]
|
|
|
|
| 677 |
|
| 678 |
content = resp.text
|
| 679 |
|
| 680 |
+
# CMS/Framework detection
|
| 681 |
patterns = {
|
| 682 |
"WordPress": r"wp-content|wp-includes|/wp-admin|wordpress",
|
| 683 |
"Drupal": r"sites/default/files|drupal\\.css|drupal.js",
|
|
|
|
| 711 |
if tech not in technologies["analytics"]:
|
| 712 |
technologies["analytics"].append(tech)
|
| 713 |
|
| 714 |
+
# Check for cookies
|
| 715 |
if "Set-Cookie" in resp.headers:
|
| 716 |
cookies = resp.headers["Set-Cookie"]
|
| 717 |
if "PHPSESSID" in cookies:
|
|
|
|
| 725 |
return technologies
|
| 726 |
|
| 727 |
async def discover_endpoints(self, url: str, wordlist: List[str] = None) -> List[Dict]:
|
| 728 |
+
"""Endpoint discovery with smart filtering"""
|
| 729 |
discovered = []
|
| 730 |
wordlist = wordlist or COMMON_ENDPOINTS
|
| 731 |
|
| 732 |
+
for path in wordlist[:50]: # Limit wordlist
|
| 733 |
try:
|
| 734 |
full_url = f"https://{url.rstrip('/')}/{path.lstrip('/')}"
|
| 735 |
headers = self.config.get_headers()
|
|
|
|
| 753 |
return discovered
|
| 754 |
|
| 755 |
def _extract_title(self, html: str) -> str:
|
| 756 |
+
"""Extract page title from HTML"""
|
| 757 |
try:
|
| 758 |
soup = BeautifulSoup(html, 'html.parser')
|
| 759 |
title = soup.find('title')
|
|
|
|
| 762 |
return "Error"
|
| 763 |
|
| 764 |
async def analyze_forms(self, url: str) -> List[Dict]:
|
| 765 |
+
"""Form detection and analysis"""
|
| 766 |
forms = []
|
| 767 |
|
| 768 |
try:
|
|
|
|
| 791 |
}
|
| 792 |
form_data["fields"].append(field_info)
|
| 793 |
|
| 794 |
+
# Check for potential vulnerabilities
|
| 795 |
if field.get('type') == 'password':
|
| 796 |
+
form_data["vulnerabilities"].append("Password field detected - check for brute force protection")
|
| 797 |
if field.get('type') == 'file':
|
| 798 |
+
form_data["vulnerabilities"].append("File upload - check for upload restrictions")
|
| 799 |
|
| 800 |
+
# Check for CSRF protection
|
| 801 |
has_csrf = any('csrf' in str(f.get('name', '')).lower() or
|
| 802 |
'token' in str(f.get('name', '')).lower()
|
| 803 |
for f in form_data["fields"])
|
|
|
|
| 812 |
return forms
|
| 813 |
|
| 814 |
async def extract_javascript_endpoints(self, url: str) -> List[Dict]:
|
| 815 |
+
"""Extract API endpoints from JavaScript"""
|
| 816 |
endpoints = []
|
| 817 |
|
| 818 |
try:
|
| 819 |
headers = self.config.get_headers()
|
| 820 |
resp = requests.get(f"https://{url}", headers=headers, timeout=10, verify=False)
|
| 821 |
|
| 822 |
+
# Find all script tags
|
| 823 |
soup = BeautifulSoup(resp.text, 'html.parser')
|
| 824 |
scripts = []
|
| 825 |
|
|
|
|
| 827 |
if script.string:
|
| 828 |
scripts.append(script.string)
|
| 829 |
elif script.get('src'):
|
| 830 |
+
# Fetch external scripts
|
| 831 |
try:
|
| 832 |
src = script['src']
|
| 833 |
if src.startswith('http'):
|
|
|
|
| 840 |
except:
|
| 841 |
pass
|
| 842 |
|
| 843 |
+
# Extract API patterns
|
| 844 |
api_patterns = [
|
| 845 |
r'["\']/(api|v[0-9]|rest|graphql)/[^"\'\\s]+["\']',
|
| 846 |
r'(https?://[^"\'\\s]+/api/[^"\'\\s]+)',
|
|
|
|
| 855 |
matches = re.findall(pattern, script_content)
|
| 856 |
for match in matches:
|
| 857 |
if isinstance(match, tuple):
|
| 858 |
+
match = match[-1] # Get the last group
|
| 859 |
if match and match not in [e["endpoint"] for e in endpoints]:
|
| 860 |
endpoints.append({
|
| 861 |
"endpoint": match,
|
| 862 |
+
"source": "inline_js" if script_content in [s.string for s in soup.find_all('script') if s.string] else "external_js",
|
| 863 |
"type": "api"
|
| 864 |
})
|
| 865 |
|
| 866 |
+
# Look for hardcoded secrets
|
| 867 |
secret_patterns = [
|
| 868 |
(r'api[_-]?key["\']?\\s*[:=]\\s*["\']([a-zA-Z0-9_\\-]{16,})["\']', "API Key"),
|
| 869 |
(r'secret[_-]?key["\']?\\s*[:=]\\s*["\']([a-zA-Z0-9_\\-]{16,})["\']', "Secret Key"),
|
|
|
|
| 878 |
matches = re.findall(pattern, script_content, re.IGNORECASE)
|
| 879 |
for match in matches:
|
| 880 |
endpoints.append({
|
| 881 |
+
"endpoint": f"[{secret_type} DETECTED - REDACTED]",
|
| 882 |
"source": "js_analysis",
|
| 883 |
"type": "secret",
|
| 884 |
"secret_type": secret_type
|
|
|
|
| 890 |
return endpoints
|
| 891 |
|
| 892 |
async def analyze_security_headers(self, url: str) -> Dict:
|
| 893 |
+
"""Analyze security headers"""
|
| 894 |
headers_analysis = {
|
| 895 |
"present": {},
|
| 896 |
"missing": [],
|
|
|
|
| 904 |
security_headers = {
|
| 905 |
"Strict-Transport-Security": {"weight": 3, "recommendation": "Implement HSTS"},
|
| 906 |
"Content-Security-Policy": {"weight": 3, "recommendation": "Implement CSP"},
|
| 907 |
+
"X-Frame-Options": {"weight": 2, "recommendation": "Set X-Frame-Options to DENY or SAMEORIGIN"},
|
| 908 |
+
"X-Content-Type-Options": {"weight": 2, "recommendation": "Set X-Content-Type-Options to nosniff"},
|
| 909 |
"X-XSS-Protection": {"weight": 1, "recommendation": "Set X-XSS-Protection"},
|
| 910 |
"Referrer-Policy": {"weight": 1, "recommendation": "Implement Referrer-Policy"},
|
| 911 |
"Permissions-Policy": {"weight": 1, "recommendation": "Implement Permissions-Policy"}
|
|
|
|
| 930 |
return headers_analysis
|
| 931 |
|
| 932 |
async def check_common_vulnerabilities(self, url: str) -> List[Vulnerability]:
|
| 933 |
+
"""Check for common vulnerability patterns"""
|
| 934 |
vulnerabilities = []
|
| 935 |
|
| 936 |
try:
|
| 937 |
headers = self.config.get_headers()
|
| 938 |
|
| 939 |
+
# Check for exposed .env
|
| 940 |
try:
|
| 941 |
env_resp = requests.get(f"https://{url}/.env", headers=headers, timeout=5, verify=False)
|
| 942 |
if env_resp.status_code == 200 and "=" in env_resp.text:
|
| 943 |
vuln = Vulnerability(
|
| 944 |
name="Exposed Environment File",
|
| 945 |
+
description="The .env file is publicly accessible, potentially exposing sensitive configuration",
|
| 946 |
severity="CRITICAL",
|
| 947 |
cvss_score=7.5,
|
| 948 |
cvss_vector="CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
|
| 949 |
location=f"https://{url}/.env",
|
| 950 |
+
evidence=".env file accessible without authentication",
|
| 951 |
+
remediation="Restrict access to .env files via web server configuration",
|
| 952 |
cwe_id="CWE-200",
|
| 953 |
+
owasp_category="A01:2021 - Broken Access Control",
|
| 954 |
mitre_techniques=["T1083"]
|
| 955 |
)
|
| 956 |
vulnerabilities.append(vuln)
|
| 957 |
except:
|
| 958 |
pass
|
| 959 |
|
| 960 |
+
# Check for exposed .git
|
| 961 |
try:
|
| 962 |
git_resp = requests.get(f"https://{url}/.git/HEAD", headers=headers, timeout=5, verify=False)
|
| 963 |
if git_resp.status_code == 200 and "ref:" in git_resp.text:
|
| 964 |
vuln = Vulnerability(
|
| 965 |
name="Exposed Git Repository",
|
| 966 |
+
description="Git repository is publicly accessible, potentially exposing source code",
|
| 967 |
severity="HIGH",
|
| 968 |
cvss_score=7.5,
|
| 969 |
cvss_vector="CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
|
| 970 |
location=f"https://{url}/.git/",
|
| 971 |
evidence="Git HEAD file accessible",
|
| 972 |
+
remediation="Restrict access to .git directory via web server configuration",
|
| 973 |
cwe_id="CWE-200",
|
| 974 |
+
owasp_category="A01:2021 - Broken Access Control",
|
| 975 |
mitre_techniques=["T1083"]
|
| 976 |
)
|
| 977 |
vulnerabilities.append(vuln)
|
| 978 |
except:
|
| 979 |
pass
|
| 980 |
|
| 981 |
+
# Check for directory listing
|
| 982 |
try:
|
| 983 |
dir_resp = requests.get(f"https://{url}/images/", headers=headers, timeout=5, verify=False)
|
| 984 |
if dir_resp.status_code == 200 and "Index of" in dir_resp.text:
|
| 985 |
vuln = Vulnerability(
|
| 986 |
name="Directory Listing Enabled",
|
| 987 |
+
description="Directory listing is enabled, exposing file structure",
|
| 988 |
severity="MEDIUM",
|
| 989 |
cvss_score=5.3,
|
| 990 |
cvss_vector="CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N",
|
| 991 |
location=f"https://{url}/images/",
|
| 992 |
+
evidence="Directory index page displayed",
|
| 993 |
+
remediation="Disable directory listing in web server configuration",
|
| 994 |
cwe_id="CWE-548",
|
| 995 |
+
owasp_category="A01:2021 - Broken Access Control",
|
| 996 |
mitre_techniques=["T1083"]
|
| 997 |
)
|
| 998 |
vulnerabilities.append(vuln)
|
| 999 |
except:
|
| 1000 |
pass
|
| 1001 |
|
| 1002 |
+
# Check for SQL injection in URL parameters
|
| 1003 |
test_url = f"https://{url}/?id=1'"
|
| 1004 |
try:
|
| 1005 |
sql_resp = requests.get(test_url, headers=headers, timeout=5, verify=False)
|
| 1006 |
+
sql_errors = [
|
| 1007 |
+
"sql syntax", "mysql_fetch", "pg_query", "ORA-",
|
| 1008 |
+
"Microsoft OLE DB", "ODBC SQL Server", "SQLite3::"
|
| 1009 |
+
]
|
| 1010 |
if any(error.lower() in sql_resp.text.lower() for error in sql_errors):
|
| 1011 |
vuln = Vulnerability(
|
| 1012 |
name="SQL Injection",
|
| 1013 |
+
description="Potential SQL injection vulnerability detected in URL parameters",
|
| 1014 |
severity="CRITICAL",
|
| 1015 |
cvss_score=9.8,
|
| 1016 |
cvss_vector="CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
|
| 1017 |
location=test_url,
|
| 1018 |
+
evidence="SQL error message in response",
|
| 1019 |
+
remediation="Use parameterized queries and input validation",
|
| 1020 |
cwe_id="CWE-89",
|
| 1021 |
+
owasp_category="A03:2021 - Injection",
|
| 1022 |
mitre_techniques=["T1190"]
|
| 1023 |
)
|
| 1024 |
vulnerabilities.append(vuln)
|
| 1025 |
except:
|
| 1026 |
pass
|
| 1027 |
|
| 1028 |
+
# Check for XSS
|
| 1029 |
test_xss_url = f"https://{url}/?q=<script>alert(1)</script>"
|
| 1030 |
try:
|
| 1031 |
xss_resp = requests.get(test_xss_url, headers=headers, timeout=5, verify=False)
|
| 1032 |
if "<script>alert(1)</script>" in xss_resp.text:
|
| 1033 |
vuln = Vulnerability(
|
| 1034 |
name="Cross-Site Scripting (XSS)",
|
| 1035 |
+
description="Reflected XSS vulnerability detected",
|
| 1036 |
severity="HIGH",
|
| 1037 |
cvss_score=6.1,
|
| 1038 |
cvss_vector="CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N",
|
| 1039 |
location=test_xss_url,
|
| 1040 |
+
evidence="Script tag reflected in response without encoding",
|
| 1041 |
+
remediation="Implement output encoding and CSP headers",
|
| 1042 |
cwe_id="CWE-79",
|
| 1043 |
+
owasp_category="A03:2021 - Injection",
|
| 1044 |
mitre_techniques=["T1189"]
|
| 1045 |
)
|
| 1046 |
vulnerabilities.append(vuln)
|
|
|
|
| 1052 |
|
| 1053 |
return vulnerabilities
|
| 1054 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1055 |
# ════════════════════════════════════════════════════════════════════════════
|
| 1056 |
+
# SECTION 6: THREAT MODELING ENGINE (STRIDE + MITRE ATT&CK)
|
| 1057 |
# ════════════════════════════════════════════════════════════════════════════
|
| 1058 |
|
| 1059 |
class ThreatModelingEngine:
|
| 1060 |
+
"""Advanced threat modeling"""
|
| 1061 |
+
|
| 1062 |
def __init__(self):
|
| 1063 |
self.threats: List[Dict] = []
|
| 1064 |
self.attack_paths: List[AttackPath] = []
|
| 1065 |
|
| 1066 |
def analyze_web_app(self, recon_data: Dict) -> List[ThreatVector]:
|
| 1067 |
+
"""Map reconnaissance to threats"""
|
| 1068 |
threat_vectors = []
|
| 1069 |
|
| 1070 |
+
# Forms = injection vectors
|
| 1071 |
for form in recon_data.get("forms", []):
|
| 1072 |
risk = 7.5
|
| 1073 |
techniques = ["T1565.001", "T1598.003"]
|
|
|
|
| 1087 |
evidence=f"Form method: {form.get('method')}, Fields: {len(form.get('fields', []))}"
|
| 1088 |
))
|
| 1089 |
|
| 1090 |
+
# JavaScript = gadget chains
|
| 1091 |
for js_file in recon_data.get("js_files", []):
|
| 1092 |
threat_vectors.append(ThreatVector(
|
| 1093 |
category="js_gadget",
|
|
|
|
| 1100 |
evidence="Client-side code analysis"
|
| 1101 |
))
|
| 1102 |
|
| 1103 |
+
# API endpoints = information disclosure
|
| 1104 |
for endpoint in recon_data.get("endpoints", []):
|
| 1105 |
if isinstance(endpoint, dict):
|
| 1106 |
path = endpoint.get("path", "")
|
|
|
|
| 1120 |
location=path,
|
| 1121 |
risk_score=risk,
|
| 1122 |
techniques=["T1526"],
|
| 1123 |
+
description=f"API endpoint discovered: {path} (Status: {status})",
|
| 1124 |
cvss_score=risk,
|
| 1125 |
cwe_id="CWE-200",
|
| 1126 |
evidence=f"HTTP {status}"
|
| 1127 |
))
|
| 1128 |
|
| 1129 |
+
# Security headers missing
|
| 1130 |
security_score = recon_data.get("security_headers", {}).get("score", 100)
|
| 1131 |
if security_score < 50:
|
| 1132 |
threat_vectors.append(ThreatVector(
|
|
|
|
| 1143 |
return threat_vectors
|
| 1144 |
|
| 1145 |
def build_attack_paths(self, threat_vectors: List[ThreatVector], technologies: Dict) -> List[AttackPath]:
|
| 1146 |
+
"""Generate attack chains"""
|
| 1147 |
paths = []
|
| 1148 |
|
| 1149 |
+
# Generic attack path
|
| 1150 |
paths.append(AttackPath(
|
| 1151 |
entry_point="Public web form or API endpoint",
|
| 1152 |
intermediate_steps=[
|
| 1153 |
+
"Reconnaissance (technology fingerprinting)",
|
| 1154 |
+
"Vulnerability identification (SQLi, XSS, CSRF)",
|
| 1155 |
"Exploitation",
|
| 1156 |
+
"Data exfiltration or lateral movement"
|
| 1157 |
],
|
| 1158 |
+
objective="Unauthorized access / Data breach",
|
| 1159 |
risk_level="CRITICAL",
|
| 1160 |
complexity=0.6,
|
| 1161 |
mitre_techniques=["T1595", "T1190", "T1567"]
|
| 1162 |
))
|
| 1163 |
|
| 1164 |
+
# WordPress-specific
|
| 1165 |
cms_list = technologies.get("cms", [])
|
| 1166 |
if "WordPress" in cms_list:
|
| 1167 |
paths.append(AttackPath(
|
| 1168 |
+
entry_point="WordPress admin panel or vulnerable plugin",
|
| 1169 |
intermediate_steps=[
|
| 1170 |
+
"Plugin enumeration via wp-content/plugins/",
|
| 1171 |
+
"Known CVE exploitation (plugin vulnerabilities)",
|
| 1172 |
+
"Plugin upload for RCE (if authenticated)",
|
| 1173 |
+
"Server compromise via wp-config.php access"
|
| 1174 |
],
|
| 1175 |
objective="Remote Code Execution",
|
| 1176 |
risk_level="CRITICAL",
|
|
|
|
| 1178 |
mitre_techniques=["T1595", "T1190", "T1059", "T1078"]
|
| 1179 |
))
|
| 1180 |
|
| 1181 |
+
# API-specific
|
| 1182 |
api_endpoints = [v for v in threat_vectors if v.category == "api_endpoint"]
|
| 1183 |
if api_endpoints:
|
| 1184 |
paths.append(AttackPath(
|
| 1185 |
entry_point="Exposed API endpoint",
|
| 1186 |
intermediate_steps=[
|
| 1187 |
+
"API endpoint enumeration",
|
| 1188 |
+
"Authentication bypass or weak authentication",
|
| 1189 |
+
"IDOR (Insecure Direct Object Reference)",
|
| 1190 |
+
"Data exfiltration via API"
|
| 1191 |
],
|
| 1192 |
+
objective="Unauthorized data access",
|
| 1193 |
risk_level="HIGH",
|
| 1194 |
complexity=0.5,
|
| 1195 |
mitre_techniques=["T1526", "T1078", "T1567"]
|
| 1196 |
))
|
| 1197 |
|
| 1198 |
+
# JavaScript/Secret exposure
|
| 1199 |
+
js_threats = [v for v in threat_vectors if v.category == "js_gadget"]
|
| 1200 |
+
if js_threats:
|
| 1201 |
+
paths.append(AttackPath(
|
| 1202 |
+
entry_point="Hardcoded secrets in JavaScript",
|
| 1203 |
+
intermediate_steps=[
|
| 1204 |
+
"JavaScript analysis for API keys/secrets",
|
| 1205 |
+
"Credential harvesting",
|
| 1206 |
+
"API access with stolen credentials",
|
| 1207 |
+
"Data breach or system compromise"
|
| 1208 |
+
],
|
| 1209 |
+
objective="Credential theft",
|
| 1210 |
+
risk_level="HIGH",
|
| 1211 |
+
complexity=0.3,
|
| 1212 |
+
mitre_techniques=["T1552", "T1078", "T1567"]
|
| 1213 |
+
))
|
| 1214 |
+
|
| 1215 |
return paths
|
| 1216 |
|
| 1217 |
def generate_stride_report(self, recon_data: Dict) -> Dict:
|
| 1218 |
+
"""Generate STRIDE threat model"""
|
| 1219 |
stride_report = {}
|
| 1220 |
|
| 1221 |
for threat_category, threat_info in STRIDE_THREATS.items():
|
|
|
|
| 1227 |
"risk_level": "LOW"
|
| 1228 |
}
|
| 1229 |
|
| 1230 |
+
# Match with found vulnerabilities
|
| 1231 |
if "forms" in recon_data and len(recon_data["forms"]) > 0:
|
| 1232 |
if threat_category == "Tampering":
|
| 1233 |
+
stride_report[threat_category]["potential_impacts"].append(
|
| 1234 |
+
"SQL Injection in form fields"
|
| 1235 |
+
)
|
| 1236 |
stride_report[threat_category]["affected_components"].append("Database")
|
| 1237 |
stride_report[threat_category]["risk_level"] = "CRITICAL"
|
| 1238 |
|
| 1239 |
if threat_category == "InformationDisclosure":
|
| 1240 |
+
stride_report[threat_category]["potential_impacts"].append(
|
| 1241 |
+
"Sensitive data exposure through form manipulation"
|
| 1242 |
+
)
|
| 1243 |
stride_report[threat_category]["risk_level"] = "HIGH"
|
| 1244 |
|
| 1245 |
if "endpoints" in recon_data and len(recon_data["endpoints"]) > 0:
|
| 1246 |
if threat_category == "InformationDisclosure":
|
| 1247 |
+
stride_report[threat_category]["potential_impacts"].append(
|
| 1248 |
+
"Sensitive data exposed via API endpoints"
|
| 1249 |
+
)
|
| 1250 |
stride_report[threat_category]["affected_components"].append("API")
|
| 1251 |
stride_report[threat_category]["risk_level"] = "HIGH"
|
| 1252 |
|
| 1253 |
+
if "js_files" in recon_data and len(recon_data["js_files"]) > 0:
|
| 1254 |
+
if threat_category == "InformationDisclosure":
|
| 1255 |
+
stride_report[threat_category]["potential_impacts"].append(
|
| 1256 |
+
"Hardcoded secrets in client-side JavaScript"
|
| 1257 |
+
)
|
| 1258 |
+
stride_report[threat_category]["risk_level"] = "HIGH"
|
| 1259 |
+
|
| 1260 |
if "security_headers" in recon_data:
|
| 1261 |
score = recon_data["security_headers"].get("score", 100)
|
| 1262 |
if score < 50:
|
| 1263 |
if threat_category == "Spoofing":
|
| 1264 |
+
stride_report[threat_category]["potential_impacts"].append(
|
| 1265 |
+
"Session hijacking due to missing security headers"
|
| 1266 |
+
)
|
| 1267 |
+
stride_report[threat_category]["risk_level"] = "MEDIUM"
|
| 1268 |
+
|
| 1269 |
+
if threat_category == "Tampering":
|
| 1270 |
+
stride_report[threat_category]["potential_impacts"].append(
|
| 1271 |
+
"Clickjacking attacks (missing X-Frame-Options)"
|
| 1272 |
+
)
|
| 1273 |
stride_report[threat_category]["risk_level"] = "MEDIUM"
|
| 1274 |
|
| 1275 |
return stride_report
|
| 1276 |
+
|
| 1277 |
+
def calculate_cvss_score(self, vulnerability: Vulnerability) -> Dict:
|
| 1278 |
+
"""Calculate CVSS v3.1 score"""
|
| 1279 |
+
return {
|
| 1280 |
+
"base_score": vulnerability.cvss_score,
|
| 1281 |
+
"vector": vulnerability.cvss_vector,
|
| 1282 |
+
"severity": self._get_severity(vulnerability.cvss_score),
|
| 1283 |
+
"impact_score": self._calculate_impact(vulnerability.cvss_vector),
|
| 1284 |
+
"exploitability_score": self._calculate_exploitability(vulnerability.cvss_vector)
|
| 1285 |
+
}
|
| 1286 |
+
|
| 1287 |
+
def _get_severity(self, score: float) -> str:
|
| 1288 |
+
if score >= 9.0:
|
| 1289 |
+
return "CRITICAL"
|
| 1290 |
+
elif score >= 7.0:
|
| 1291 |
+
return "HIGH"
|
| 1292 |
+
elif score >= 4.0:
|
| 1293 |
+
return "MEDIUM"
|
| 1294 |
+
else:
|
| 1295 |
+
return "LOW"
|
| 1296 |
+
|
| 1297 |
+
def _calculate_impact(self, vector: str) -> float:
|
| 1298 |
+
# Simplified calculation
|
| 1299 |
+
return 0.0
|
| 1300 |
+
|
| 1301 |
+
def _calculate_exploitability(self, vector: str) -> float:
|
| 1302 |
+
# Simplified calculation
|
| 1303 |
+
return 0.0
|
| 1304 |
|
| 1305 |
# ════════════════════════════════════════════════════════════════════════════
|
| 1306 |
+
# SECTION 7: ATTACK GRAPH VISUALIZATION (ENHANCED)
|
| 1307 |
# ════════════════════════════════════════════════════════════════════════════
|
| 1308 |
|
| 1309 |
class AttackGraphEngine:
|
| 1310 |
+
"""Advanced attack surface visualization"""
|
| 1311 |
+
|
| 1312 |
@staticmethod
|
| 1313 |
def create_enhanced_attack_graph(threat_vectors: List[ThreatVector],
|
| 1314 |
attack_paths: List[AttackPath],
|
| 1315 |
vulnerabilities: List[Vulnerability] = None) -> Dict:
|
| 1316 |
+
"""Build graph with threat vectors and attack paths"""
|
| 1317 |
|
| 1318 |
nodes = ["Attacker", "Internet", "Target Domain"]
|
| 1319 |
edges = [("Attacker", "Internet"), ("Internet", "Target Domain")]
|
|
|
|
| 1323 |
"Target Domain": {"type": "asset", "risk": 7, "layer": 2}
|
| 1324 |
}
|
| 1325 |
|
| 1326 |
+
# Add threat vectors as nodes
|
| 1327 |
+
for i, vector in enumerate(threat_vectors[:15]): # Increased limit
|
| 1328 |
node_name = f"{vector.category.replace('_', ' ').title()}_{i+1}"
|
| 1329 |
nodes.append(node_name)
|
| 1330 |
edges.append(("Target Domain", node_name))
|
|
|
|
| 1337 |
"cwe": vector.cwe_id
|
| 1338 |
}
|
| 1339 |
|
| 1340 |
+
# Add vulnerabilities as nodes
|
| 1341 |
if vulnerabilities:
|
| 1342 |
for i, vuln in enumerate(vulnerabilities[:10]):
|
| 1343 |
+
node_name = f"Vuln: {vuln.name[:20]}..."
|
| 1344 |
nodes.append(node_name)
|
| 1345 |
edges.append(("Target Domain", node_name))
|
| 1346 |
node_info[node_name] = {
|
|
|
|
| 1363 |
|
| 1364 |
@staticmethod
|
| 1365 |
def visualize_attack_graph_plotly(graph_data: Dict) -> go.Figure:
|
| 1366 |
+
"""Create interactive Plotly visualization"""
|
| 1367 |
+
|
| 1368 |
G = nx.DiGraph()
|
| 1369 |
G.add_edges_from(graph_data["edges"])
|
| 1370 |
|
| 1371 |
+
# Use hierarchical layout
|
| 1372 |
pos = {}
|
| 1373 |
layers = defaultdict(list)
|
| 1374 |
|
|
|
|
| 1381 |
for i, node in enumerate(nodes):
|
| 1382 |
pos[node] = (layer * 3, (i - y_offset/2) * 2)
|
| 1383 |
|
| 1384 |
+
# Edge traces
|
| 1385 |
edge_x, edge_y = [], []
|
| 1386 |
for edge in G.edges():
|
| 1387 |
x0, y0 = pos[edge[0]]
|
|
|
|
| 1397 |
name='Attack Path'
|
| 1398 |
)
|
| 1399 |
|
| 1400 |
+
# Node traces with risk coloring
|
| 1401 |
node_x, node_y, node_text, node_color, node_size, hover_text = [], [], [], [], [], []
|
| 1402 |
|
| 1403 |
for node in G.nodes():
|
|
|
|
| 1410 |
risk = node_info.get("risk", 5)
|
| 1411 |
node_type = node_info.get("type", "unknown")
|
| 1412 |
|
| 1413 |
+
# Color by type and risk
|
| 1414 |
if node_type == "attacker":
|
| 1415 |
node_color.append('#ff0000')
|
| 1416 |
elif node_type == "network":
|
|
|
|
| 1420 |
elif node_type == "exploit":
|
| 1421 |
node_color.append('#ff00ff')
|
| 1422 |
else:
|
| 1423 |
+
# Color by risk
|
| 1424 |
if risk >= 9:
|
| 1425 |
+
node_color.append('#ff0000') # Red - Critical
|
| 1426 |
elif risk >= 7:
|
| 1427 |
+
node_color.append('#ff7700') # Orange - High
|
| 1428 |
elif risk >= 4:
|
| 1429 |
+
node_color.append('#ffcc00') # Yellow - Medium
|
| 1430 |
else:
|
| 1431 |
+
node_color.append('#00ff00') # Green - Low
|
| 1432 |
|
| 1433 |
size = 40 if node_type in ["attacker", "asset"] else 30 + (risk * 1.5)
|
| 1434 |
node_size.append(size)
|
| 1435 |
|
| 1436 |
+
# Hover text
|
| 1437 |
hover_info = f"<b>{node}</b><br>Type: {node_type}<br>Risk: {risk}"
|
| 1438 |
if node_info.get("cvss"):
|
| 1439 |
hover_info += f"<br>CVSS: {node_info['cvss']}"
|
|
|
|
| 1461 |
fig = go.Figure(data=[edge_trace, node_trace])
|
| 1462 |
fig.update_layout(
|
| 1463 |
title={
|
| 1464 |
+
'text': '🎯 Advanced Attack Surface Graph',
|
| 1465 |
'font': {'size': 24, 'color': '#ff0000'},
|
| 1466 |
'x': 0.5
|
| 1467 |
},
|
|
|
|
| 1477 |
dict(
|
| 1478 |
x=0.02, y=0.98,
|
| 1479 |
xref='paper', yref='paper',
|
| 1480 |
+
text='🔴 Critical Risk<br>🟠 High Risk<br>🟡 Medium Risk<br>🟢 Low Risk',
|
| 1481 |
showarrow=False,
|
| 1482 |
font=dict(size=12, color='white'),
|
| 1483 |
bgcolor='rgba(0,0,0,0.5)',
|
|
|
|
| 1488 |
)
|
| 1489 |
|
| 1490 |
return fig
|
| 1491 |
+
|
| 1492 |
+
@staticmethod
|
| 1493 |
+
def create_risk_heatmap(threat_vectors: List[ThreatVector]) -> go.Figure:
|
| 1494 |
+
"""Create risk heatmap"""
|
| 1495 |
+
categories = defaultdict(list)
|
| 1496 |
+
for tv in threat_vectors:
|
| 1497 |
+
categories[tv.category].append(tv.risk_score)
|
| 1498 |
+
|
| 1499 |
+
if not categories:
|
| 1500 |
+
return go.Figure()
|
| 1501 |
+
|
| 1502 |
+
cat_names = list(categories.keys())
|
| 1503 |
+
avg_risks = [sum(scores)/len(scores) for scores in categories.values()]
|
| 1504 |
+
counts = [len(scores) for scores in categories.values()]
|
| 1505 |
+
|
| 1506 |
+
fig = go.Figure(data=[
|
| 1507 |
+
go.Bar(
|
| 1508 |
+
x=cat_names,
|
| 1509 |
+
y=avg_risks,
|
| 1510 |
+
text=counts,
|
| 1511 |
+
textposition='auto',
|
| 1512 |
+
marker_color=['#ff0000' if r >= 7 else '#ff7700' if r >= 4 else '#ffff00' for r in avg_risks]
|
| 1513 |
+
)
|
| 1514 |
+
])
|
| 1515 |
+
|
| 1516 |
+
fig.update_layout(
|
| 1517 |
+
title='Risk Distribution by Category',
|
| 1518 |
+
xaxis_title='Threat Category',
|
| 1519 |
+
yaxis_title='Average Risk Score',
|
| 1520 |
+
plot_bgcolor='#1a1a1a',
|
| 1521 |
+
paper_bgcolor='#1a1a1a',
|
| 1522 |
+
font=dict(color='#ffffff')
|
| 1523 |
+
)
|
| 1524 |
+
|
| 1525 |
+
return fig
|
| 1526 |
+
|
| 1527 |
+
|
| 1528 |
+
═══════════════════════════════════════════════════════════════════════════════
|
| 1529 |
+
PRIVATE RED TEAM WEB RECONNAISSANCE FRAMEWORK v3.0 - PART 2
|
| 1530 |
+
─────────────────────────────────────────────────────────────────────────
|
| 1531 |
+
Bölümler: 8-10 (Reporting Engine, Main Orchestrator, Gradio Interface)
|
| 1532 |
+
═══════════════════════════════════════════════════════════════════════════════
|
| 1533 |
+
"""
|
| 1534 |
+
|
| 1535 |
+
# Part 1'deki importları ve sınıfları tekrar etmek için:
|
| 1536 |
+
# Bu dosyayı çalıştırmadan önce Part 1'i import edin veya birleştirin
|
| 1537 |
|
| 1538 |
# ════════════════════════════════════════════════════════════════════════════
|
| 1539 |
+
# SECTION 8: COMPREHENSIVE REPORTING ENGINE
|
| 1540 |
# ════════════════════════════════════════════════════════════════════════════
|
| 1541 |
|
| 1542 |
class ReportingEngine:
|
| 1543 |
+
"""Professional security assessment reporting"""
|
| 1544 |
+
|
| 1545 |
@staticmethod
|
| 1546 |
def generate_assessment_report(target: str, recon_data: Dict, threat_vectors: List[ThreatVector],
|
| 1547 |
attack_paths: List[AttackPath], stride_report: Dict,
|
| 1548 |
vulnerabilities: List[Vulnerability] = None) -> str:
|
| 1549 |
+
"""Generate comprehensive assessment report"""
|
| 1550 |
|
| 1551 |
vulns = vulnerabilities or []
|
| 1552 |
|
| 1553 |
+
report = f"""
|
| 1554 |
+
╔════════════════════════════════════════════════════════════════════════╗
|
| 1555 |
+
║ PROFESSIONAL SECURITY ASSESSMENT REPORT ║
|
| 1556 |
+
║ [CONFIDENTIAL] ║
|
| 1557 |
+
║ PRIVATE SPACE EDITION v3.0 ║
|
| 1558 |
+
╚════════════════════════════════════════════════════════════════════════╝
|
| 1559 |
+
|
| 1560 |
+
EXECUTIVE SUMMARY
|
| 1561 |
+
─────────────────────────────────────────────────────────────────────────
|
| 1562 |
+
Target: {target}
|
| 1563 |
+
Assessment Date: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
|
| 1564 |
+
Assessed By: Red Team Framework v3.0 (Private Space)
|
| 1565 |
+
Classification: CONFIDENTIAL
|
| 1566 |
+
Assessment Type: Comprehensive Web Application Security Assessment
|
| 1567 |
+
|
| 1568 |
+
RISK OVERVIEW
|
| 1569 |
+
─────────────────────────────────────────────────────────────────────────
|
| 1570 |
+
Critical Findings: {len([t for t in vulns if t.cvss_score >= 9.0])}
|
| 1571 |
+
High Findings: {len([t for t in vulns if 7.0 <= t.cvss_score < 9.0])}
|
| 1572 |
+
Medium Findings: {len([t for t in vulns if 4.0 <= t.cvss_score < 7.0])}
|
| 1573 |
+
Low Findings: {len([t for t in vulns if t.cvss_score < 4.0])}
|
| 1574 |
+
|
| 1575 |
+
Overall Risk Level: {"🔴 CRITICAL" if len([t for t in vulns if t.cvss_score >= 9.0]) > 0 else "🟠 HIGH" if len([t for t in vulns if t.cvss_score >= 7.0]) > 0 else "🟡 MEDIUM"}
|
| 1576 |
+
|
| 1577 |
+
ATTACK SURFACE
|
| 1578 |
+
─────────────────────────────────────────────────────────────────────────
|
| 1579 |
+
Technologies Identified: {len(recon_data.get('technologies', {}).get('cms', [])) + len(recon_data.get('technologies', {}).get('frameworks', []))}
|
| 1580 |
+
API Endpoints: {len(recon_data.get('endpoints', []))}
|
| 1581 |
+
Forms Discovered: {len(recon_data.get('forms', []))}
|
| 1582 |
+
Subdomains Found: {len(recon_data.get('subdomains', []))}
|
| 1583 |
+
JavaScript Files Analyzed: {len(recon_data.get('js_files', []))}
|
| 1584 |
+
Security Headers Score: {recon_data.get('security_headers', {}).get('score', 0):.1f}%
|
| 1585 |
+
|
| 1586 |
+
TECHNOLOGIES DETECTED
|
| 1587 |
+
─────────────────────────────────────────────────────────────────────────
|
| 1588 |
+
Web Server: {recon_data.get('technologies', {}).get('web_server', 'Unknown')}
|
| 1589 |
+
CMS: {', '.join(recon_data.get('technologies', {}).get('cms', ['None detected']))}
|
| 1590 |
+
Frameworks: {', '.join(recon_data.get('technologies', {}).get('frameworks', ['None detected']))}
|
| 1591 |
+
JavaScript Libraries: {', '.join(recon_data.get('technologies', {}).get('javascript', ['None detected']))}
|
| 1592 |
+
CDN: {', '.join(recon_data.get('technologies', {}).get('cdn', ['None detected']))}
|
| 1593 |
+
|
| 1594 |
+
VULNERABILITY DETAILS
|
| 1595 |
+
──────────────────────��──────────────────────────────────────────────────
|
| 1596 |
+
"""
|
| 1597 |
+
|
| 1598 |
for i, vuln in enumerate(vulns, 1):
|
| 1599 |
+
report += f"""
|
| 1600 |
+
[{i}] {vuln.name}
|
| 1601 |
+
Severity: {vuln.severity}
|
| 1602 |
+
CVSS Score: {vuln.cvss_score}
|
| 1603 |
+
CVSS Vector: {vuln.cvss_vector}
|
| 1604 |
+
CWE ID: {vuln.cwe_id or 'N/A'}
|
| 1605 |
+
OWASP Category: {vuln.owasp_category or 'N/A'}
|
| 1606 |
+
Location: {vuln.location}
|
| 1607 |
+
|
| 1608 |
+
Description:
|
| 1609 |
+
{vuln.description}
|
| 1610 |
+
|
| 1611 |
+
Evidence:
|
| 1612 |
+
{vuln.evidence}
|
| 1613 |
+
|
| 1614 |
+
Remediation:
|
| 1615 |
+
{vuln.remediation}
|
| 1616 |
+
|
| 1617 |
+
MITRE ATT&CK Techniques: {', '.join(vuln.mitre_techniques)}
|
| 1618 |
+
|
| 1619 |
+
{'─' * 70}
|
| 1620 |
+
"""
|
| 1621 |
+
|
| 1622 |
+
report += f"""
|
| 1623 |
+
|
| 1624 |
+
THREAT VECTORS
|
| 1625 |
+
─────────────────────────────────────────────────────────────────────────
|
| 1626 |
+
"""
|
| 1627 |
+
|
| 1628 |
+
for i, vector in enumerate(threat_vectors[:10], 1):
|
| 1629 |
+
report += f"""
|
| 1630 |
+
{i}. [{vector.category.upper()}]
|
| 1631 |
+
Location: {vector.location}
|
| 1632 |
+
Risk Score: {vector.risk_score}/10
|
| 1633 |
+
CVSS Score: {vector.cvss_score if vector.cvss_score else 'N/A'}
|
| 1634 |
+
CWE ID: {vector.cwe_id or 'N/A'}
|
| 1635 |
+
MITRE ATT&CK: {', '.join(vector.techniques)}
|
| 1636 |
+
Description: {vector.description}
|
| 1637 |
+
Evidence: {vector.evidence or 'N/A'}
|
| 1638 |
+
"""
|
| 1639 |
+
|
| 1640 |
+
report += f"""
|
| 1641 |
+
|
| 1642 |
+
STRIDE THREAT MODEL
|
| 1643 |
+
─────────────────────────────────────────────────────────────────────────
|
| 1644 |
+
"""
|
| 1645 |
+
|
| 1646 |
+
for threat_type, threat_data in stride_report.items():
|
| 1647 |
+
report += f"""
|
| 1648 |
+
{threat_type}:
|
| 1649 |
+
Risk Level: {threat_data.get('risk_level', 'LOW')}
|
| 1650 |
+
Description: {threat_data['description']}
|
| 1651 |
+
Potential Impacts:
|
| 1652 |
+
"""
|
| 1653 |
+
for impact in threat_data.get('potential_impacts', []):
|
| 1654 |
+
report += f" • {impact}\\n"
|
| 1655 |
+
|
| 1656 |
+
report += f" Affected Components:\\n"
|
| 1657 |
+
for component in threat_data.get('affected_components', []):
|
| 1658 |
+
report += f" • {component}\\n"
|
| 1659 |
+
|
| 1660 |
+
report += f" Mitigations: {', '.join(threat_data['mitigations'])}\\n"
|
| 1661 |
+
|
| 1662 |
+
report += f"""
|
| 1663 |
+
|
| 1664 |
+
ATTACK PATH ANALYSIS
|
| 1665 |
+
─────────────────────────────────────────────────────────────────────────
|
| 1666 |
+
"""
|
| 1667 |
+
|
| 1668 |
+
for i, path in enumerate(attack_paths, 1):
|
| 1669 |
+
report += f"""
|
| 1670 |
+
Attack Path {i}: {path.objective}
|
| 1671 |
+
Entry Point: {path.entry_point}
|
| 1672 |
+
Complexity: {path.complexity}/1.0
|
| 1673 |
+
Risk Level: {path.risk_level}
|
| 1674 |
+
MITRE ATT&CK Techniques: {', '.join(path.mitre_techniques)}
|
| 1675 |
+
Steps:
|
| 1676 |
+
"""
|
| 1677 |
+
for step in path.intermediate_steps:
|
| 1678 |
+
report += f" → {step}\\n"
|
| 1679 |
+
|
| 1680 |
+
report += """
|
| 1681 |
+
|
| 1682 |
+
RECOMMENDATIONS
|
| 1683 |
+
─────────────────────────────────────────────────────────────────────────
|
| 1684 |
+
1. IMMEDIATE (Critical - Fix within 24 hours):
|
| 1685 |
+
• Patch all critical CVEs (CVSS 9.0+)
|
| 1686 |
+
• Disable exposed sensitive files (.env, .git)
|
| 1687 |
+
• Enable WAF rules for SQL injection protection
|
| 1688 |
+
• Implement rate limiting on authentication endpoints
|
| 1689 |
+
• Enable security headers (CSP, HSTS, X-Frame-Options)
|
| 1690 |
+
|
| 1691 |
+
2. SHORT-TERM (High - Fix within 1 week):
|
| 1692 |
+
• Update outdated technologies and frameworks
|
| 1693 |
+
• Implement input validation on all forms
|
| 1694 |
+
• Enable HTTPS enforcement (HSTS)
|
| 1695 |
+
• Setup security monitoring and alerting
|
| 1696 |
+
• Conduct code review for injection vulnerabilities
|
| 1697 |
+
|
| 1698 |
+
3. MEDIUM-TERM (Medium - Fix within 1 month):
|
| 1699 |
+
• Implement Web Application Firewall (WAF)
|
| 1700 |
+
• Conduct penetration testing
|
| 1701 |
+
• Implement secure session management
|
| 1702 |
+
• Setup vulnerability disclosure program
|
| 1703 |
+
• Regular security training for developers
|
| 1704 |
+
|
| 1705 |
+
4. LONG-TERM (Ongoing):
|
| 1706 |
+
• Implement Secure SDLC
|
| 1707 |
+
• Regular automated security scanning
|
| 1708 |
+
• Bug bounty program
|
| 1709 |
+
• Incident response planning
|
| 1710 |
+
• Compliance auditing (OWASP ASVS)
|
| 1711 |
+
|
| 1712 |
+
COMPLIANCE MAPPING
|
| 1713 |
+
─────────────────────────────────────────────────────────────────────────
|
| 1714 |
+
OWASP Top 10 2021:
|
| 1715 |
+
"""
|
| 1716 |
+
|
| 1717 |
+
owasp_categories = defaultdict(list)
|
| 1718 |
+
for vuln in vulns:
|
| 1719 |
+
if vuln.owasp_category:
|
| 1720 |
+
owasp_categories[vuln.owasp_category].append(vuln.name)
|
| 1721 |
+
|
| 1722 |
+
for category, vuln_list in owasp_categories.items():
|
| 1723 |
+
report += f" {category}: {len(vuln_list)} findings\\n"
|
| 1724 |
+
for v in vuln_list[:3]: # Limit to 3 per category
|
| 1725 |
+
report += f" • {v}\\n"
|
| 1726 |
+
|
| 1727 |
+
report += f"""
|
| 1728 |
+
|
| 1729 |
+
MITRE ATT&CK MAPPING
|
| 1730 |
+
─────────────────────────────────────────────────────────────────────────
|
| 1731 |
+
"""
|
| 1732 |
+
|
| 1733 |
+
mitre_techniques = set()
|
| 1734 |
+
for vuln in vulns:
|
| 1735 |
+
mitre_techniques.update(vuln.mitre_techniques)
|
| 1736 |
+
for path in attack_paths:
|
| 1737 |
+
mitre_techniques.update(path.mitre_techniques)
|
| 1738 |
+
|
| 1739 |
+
for tech in sorted(mitre_techniques):
|
| 1740 |
+
report += f" • {tech}"
|
| 1741 |
+
# Add technique name if available
|
| 1742 |
+
for category, techniques in MITRE_TECHNIQUES.items():
|
| 1743 |
+
if tech in techniques:
|
| 1744 |
+
report += f" - {techniques[tech]}"
|
| 1745 |
+
break
|
| 1746 |
+
report += "\\n"
|
| 1747 |
+
|
| 1748 |
+
report += f"""
|
| 1749 |
+
|
| 1750 |
+
METHODOLOGY
|
| 1751 |
+
─────────────────────────────────────────────────────────────────────────
|
| 1752 |
+
1. Passive OSINT (Non-intrusive):
|
| 1753 |
+
• DNS record enumeration (A, AAAA, MX, NS, TXT)
|
| 1754 |
+
• SSL/TLS certificate analysis
|
| 1755 |
+
• Certificate Transparency log queries (crt.sh)
|
| 1756 |
+
• GitHub reconnaissance
|
| 1757 |
+
• Wayback Machine historical data
|
| 1758 |
+
• Shodan/Censys intelligence (if API available)
|
| 1759 |
+
|
| 1760 |
+
2. Active Reconnaissance (Low impact):
|
| 1761 |
+
• HTTP header analysis
|
| 1762 |
+
• Technology fingerprinting
|
| 1763 |
+
• Endpoint discovery
|
| 1764 |
+
• Form analysis
|
| 1765 |
+
• JavaScript endpoint extraction
|
| 1766 |
+
• Security headers assessment
|
| 1767 |
+
|
| 1768 |
+
3. Vulnerability Analysis:
|
| 1769 |
+
• Pattern-based detection
|
| 1770 |
+
• Configuration weakness identification
|
| 1771 |
+
• Information disclosure checks
|
| 1772 |
+
• Injection vulnerability probes (safe)
|
| 1773 |
+
|
| 1774 |
+
4. Threat Modeling:
|
| 1775 |
+
• STRIDE analysis
|
| 1776 |
+
• Attack path generation
|
| 1777 |
+
• MITRE ATT&CK mapping
|
| 1778 |
+
• Risk scoring (CVSS v3.1)
|
| 1779 |
+
|
| 1780 |
+
5. Reporting:
|
| 1781 |
+
• Executive summary
|
| 1782 |
+
• Technical findings
|
| 1783 |
+
• Remediation guidance
|
| 1784 |
+
• Compliance mapping
|
| 1785 |
+
|
| 1786 |
+
TOOLS & TECHNIQUES
|
| 1787 |
+
─────────────────────────────────────────────────────────────────────────
|
| 1788 |
+
• Framework: Red Team Recon Framework v3.0
|
| 1789 |
+
• Standards: OWASP Testing Guide, PTES, CVSS v3.1
|
| 1790 |
+
• Threat Model: STRIDE, MITRE ATT&CK v12
|
| 1791 |
+
• Visualization: NetworkX, Plotly
|
| 1792 |
+
• OSINT: DNS, SSL, crt.sh, GitHub, Wayback
|
| 1793 |
+
|
| 1794 |
+
LIMITATIONS
|
| 1795 |
+
─────────────────────────────────────────────────────────────────────────
|
| 1796 |
+
• Assessment limited to authorized scope
|
| 1797 |
+
• No active exploitation performed
|
| 1798 |
+
• Rate limiting may affect scan completeness
|
| 1799 |
+
• Some checks require manual verification
|
| 1800 |
+
• API keys needed for full OSINT features
|
| 1801 |
+
|
| 1802 |
+
═══════════════════════════════════════════════════════════════════════════
|
| 1803 |
+
Report Generated: {datetime.now().isoformat()}
|
| 1804 |
+
Classification: CONFIDENTIAL - DO NOT DISTRIBUTE
|
| 1805 |
+
Private Space Assessment - Authorized Testing Only
|
| 1806 |
+
═══════════════════════════════════════════════════════════════════════════
|
| 1807 |
+
"""
|
| 1808 |
+
return report
|
| 1809 |
+
|
| 1810 |
+
@staticmethod
|
| 1811 |
+
def generate_executive_summary(target: str, recon_data: Dict, vulnerabilities: List[Vulnerability]) -> str:
|
| 1812 |
+
"""Generate executive summary for C-level"""
|
| 1813 |
+
|
| 1814 |
+
critical = len([v for v in vulnerabilities if v.cvss_score >= 9.0])
|
| 1815 |
+
high = len([v for v in vulnerabilities if 7.0 <= v.cvss_score < 9.0])
|
| 1816 |
+
medium = len([v for v in vulnerabilities if 4.0 <= v.cvss_score < 7.0])
|
| 1817 |
+
|
| 1818 |
+
summary = f"""
|
| 1819 |
+
EXECUTIVE SUMMARY
|
| 1820 |
+
═══════════════════════════════════════════════════════════════════════════
|
| 1821 |
+
|
| 1822 |
+
Target Organization: {target}
|
| 1823 |
+
Assessment Period: {datetime.now().strftime('%Y-%m-%d')}
|
| 1824 |
+
Overall Risk Rating: {"CRITICAL" if critical > 0 else "HIGH" if high > 0 else "MEDIUM"}
|
| 1825 |
+
|
| 1826 |
+
KEY FINDINGS:
|
| 1827 |
+
• {critical} Critical vulnerabilities requiring immediate attention
|
| 1828 |
+
• {high} High-risk vulnerabilities to address within 1 week
|
| 1829 |
+
• {medium} Medium-risk vulnerabilities for next sprint
|
| 1830 |
+
|
| 1831 |
+
BUSINESS IMPACT:
|
| 1832 |
+
"""
|
| 1833 |
+
|
| 1834 |
+
if critical > 0:
|
| 1835 |
+
summary += "• CRITICAL: Immediate risk of data breach or system compromise\\n"
|
| 1836 |
+
if high > 0:
|
| 1837 |
+
summary += "• HIGH: Significant risk to business operations and data integrity\\n"
|
| 1838 |
+
|
| 1839 |
+
summary += f"""
|
| 1840 |
+
IMMEDIATE ACTIONS REQUIRED:
|
| 1841 |
+
1. Convene security incident response team
|
| 1842 |
+
2. Prioritize critical vulnerability remediation
|
| 1843 |
+
3. Review and enhance monitoring capabilities
|
| 1844 |
+
4. Consider temporary WAF rules for protection
|
| 1845 |
+
|
| 1846 |
+
ESTIMATED REMEDIATION EFFORT:
|
| 1847 |
+
• Critical issues: 1-3 days
|
| 1848 |
+
• High issues: 1-2 weeks
|
| 1849 |
+
• Full remediation: 1-3 months
|
| 1850 |
+
|
| 1851 |
+
RECOMMENDED INVESTMENT:
|
| 1852 |
+
• Immediate security patches: $5K-$15K
|
| 1853 |
+
• Security infrastructure improvements: $25K-$75K
|
| 1854 |
+
• Ongoing security program: $100K-$300K annually
|
| 1855 |
+
|
| 1856 |
+
═══════════════════════════════════════════════════════════════════════════
|
| 1857 |
+
"""
|
| 1858 |
+
return summary
|
| 1859 |
|
| 1860 |
# ════════════════════════════════════════════════════════════════════════════
|
| 1861 |
# SECTION 9: MAIN ORCHESTRATOR
|
| 1862 |
# ════════════════════════════════════════════════════════════════════════════
|
| 1863 |
|
| 1864 |
class RedTeamReconFramework:
|
| 1865 |
+
"""Master orchestrator"""
|
| 1866 |
+
|
| 1867 |
def __init__(self):
|
| 1868 |
self.stealth_config = StealthConfig(ThreatLevel.MEDIUM)
|
| 1869 |
self.passive_engine = PassiveOSINTEngine(self.stealth_config)
|
|
|
|
| 1873 |
self.reporting = ReportingEngine()
|
| 1874 |
|
| 1875 |
async def execute_assessment(self, target_url: str) -> Dict:
|
| 1876 |
+
"""Execute full security assessment"""
|
| 1877 |
+
|
| 1878 |
results = {
|
| 1879 |
"target": target_url,
|
| 1880 |
"timestamp": datetime.now().isoformat(),
|
|
|
|
| 1893 |
}
|
| 1894 |
|
| 1895 |
try:
|
| 1896 |
+
# PHASE 1: Passive OSINT
|
| 1897 |
+
print("[1/5] Passive OSINT gathering...")
|
| 1898 |
passive_data = await self.passive_engine.gather_dns_intel(target_url)
|
| 1899 |
results["subdomains"] = passive_data.get("subdomains", [])
|
| 1900 |
|
|
|
|
| 1905 |
for san in ssl_data["subjectAltNames"]
|
| 1906 |
])
|
| 1907 |
|
| 1908 |
+
# Certificate Transparency logs
|
| 1909 |
ct_subdomains = await self.passive_engine.crt_sh_lookup(target_url)
|
| 1910 |
for sub in ct_subdomains:
|
| 1911 |
if sub not in [s.get("subdomain") for s in results["subdomains"]]:
|
| 1912 |
results["subdomains"].append({"subdomain": sub, "ip": "from_ct"})
|
| 1913 |
|
| 1914 |
+
# GitHub recon
|
| 1915 |
github_data = await self.passive_engine.github_reconnaissance(target_url.replace(".com", ""))
|
| 1916 |
results["github_intel"] = github_data
|
| 1917 |
|
| 1918 |
+
# Wayback Machine
|
| 1919 |
wayback_urls = await self.passive_engine.wayback_machine_lookup(target_url)
|
| 1920 |
results["historical_urls"] = wayback_urls
|
| 1921 |
|
| 1922 |
+
# PHASE 2: Active Reconnaissance
|
| 1923 |
+
print("[2/5] Active reconnaissance...")
|
| 1924 |
technologies = await self.active_engine.fingerprint_technologies(target_url)
|
| 1925 |
results["technologies"] = technologies
|
| 1926 |
|
|
|
|
| 1936 |
security_headers = await self.active_engine.analyze_security_headers(target_url)
|
| 1937 |
results["security_headers"] = security_headers
|
| 1938 |
|
| 1939 |
+
# PHASE 3: Vulnerability Analysis
|
| 1940 |
+
print("[3/5] Vulnerability analysis...")
|
| 1941 |
vulnerabilities = await self.active_engine.check_common_vulnerabilities(target_url)
|
| 1942 |
results["vulnerabilities"] = [asdict(v) for v in vulnerabilities]
|
| 1943 |
|
| 1944 |
+
# PHASE 4: Threat Modeling
|
| 1945 |
+
print("[4/5] Threat modeling...")
|
| 1946 |
threat_vectors = self.threat_model.analyze_web_app(results)
|
| 1947 |
results["threat_vectors"] = [asdict(tv) for tv in threat_vectors]
|
| 1948 |
|
|
|
|
| 1952 |
stride_analysis = self.threat_model.generate_stride_report(results)
|
| 1953 |
results["stride_analysis"] = stride_analysis
|
| 1954 |
|
| 1955 |
+
# PHASE 5: Attack Graph
|
| 1956 |
+
print("[5/5] Generating attack graph...")
|
| 1957 |
graph_data = self.graph_engine.create_enhanced_attack_graph(
|
| 1958 |
threat_vectors, attack_paths, vulnerabilities
|
| 1959 |
)
|
| 1960 |
results["graph_data"] = graph_data
|
| 1961 |
|
| 1962 |
+
# PHASE 6: Reporting
|
| 1963 |
+
print("[6/6] Generating report...")
|
| 1964 |
report = self.reporting.generate_assessment_report(
|
| 1965 |
target_url, results, threat_vectors, attack_paths, stride_analysis, vulnerabilities
|
| 1966 |
)
|
| 1967 |
results["report"] = report
|
| 1968 |
|
| 1969 |
+
print("✅ Assessment complete!")
|
| 1970 |
|
| 1971 |
except Exception as e:
|
| 1972 |
results["error"] = str(e)
|
|
|
|
| 1976 |
|
| 1977 |
return results
|
| 1978 |
|
| 1979 |
+
════════════════════════════════════════════════════════════════════════════
|
| 1980 |
# SECTION 10: GRADIO INTERFACE
|
| 1981 |
# ════════════════════════════════════════════════════════════════════════════
|
| 1982 |
|
| 1983 |
+
# Initialize framework
|
| 1984 |
framework = RedTeamReconFramework()
|
| 1985 |
|
| 1986 |
def run_assessment(target_url: str, threat_level: str, progress=gr.Progress(track_tqdm=True)):
|
| 1987 |
+
"""Gradio wrapper function"""
|
| 1988 |
+
|
| 1989 |
try:
|
| 1990 |
if not target_url:
|
| 1991 |
+
return "Error: Please enter a target domain", "{}", go.Figure(), "No report generated"
|
| 1992 |
|
| 1993 |
+
# Clean target URL
|
| 1994 |
target_url = target_url.replace("https://", "").replace("http://", "").strip("/")
|
| 1995 |
|
| 1996 |
+
progress(0.1, desc="🔍 Validating target...")
|
| 1997 |
|
| 1998 |
+
# Update threat level
|
| 1999 |
threat_map = {
|
| 2000 |
"Low (Stealthy)": ThreatLevel.LOW,
|
| 2001 |
"Medium (Balanced)": ThreatLevel.MEDIUM,
|
|
|
|
| 2003 |
}
|
| 2004 |
framework.stealth_config = StealthConfig(threat_map.get(threat_level, ThreatLevel.MEDIUM))
|
| 2005 |
|
| 2006 |
+
progress(0.2, desc="🕵️ Starting passive OSINT...")
|
| 2007 |
+
progress(0.4, desc="📡 Running active reconnaissance...")
|
| 2008 |
+
progress(0.6, desc="🎯 Analyzing threats...")
|
| 2009 |
+
progress(0.8, desc="📊 Generating attack graph...")
|
| 2010 |
|
| 2011 |
+
# Run assessment
|
| 2012 |
loop = asyncio.new_event_loop()
|
| 2013 |
asyncio.set_event_loop(loop)
|
| 2014 |
results = loop.run_until_complete(framework.execute_assessment(target_url))
|
| 2015 |
loop.close()
|
| 2016 |
|
| 2017 |
+
progress(0.95, desc="📝 Finalizing report...")
|
| 2018 |
|
| 2019 |
+
# Create visualization
|
| 2020 |
if results.get("graph_data"):
|
| 2021 |
fig = framework.graph_engine.visualize_attack_graph_plotly(results["graph_data"])
|
| 2022 |
else:
|
| 2023 |
fig = go.Figure()
|
| 2024 |
|
| 2025 |
+
# Calculate stats
|
| 2026 |
vulns = results.get("vulnerabilities", [])
|
| 2027 |
critical = len([v for v in vulns if v.get("cvss_score", 0) >= 9.0])
|
| 2028 |
high = len([v for v in vulns if 7.0 <= v.get("cvss_score", 0) < 9.0])
|
| 2029 |
medium = len([v for v in vulns if 4.0 <= v.get("cvss_score", 0) < 7.0])
|
| 2030 |
|
| 2031 |
+
# Summary
|
| 2032 |
+
summary = f"""
|
| 2033 |
+
## 🔴 ASSESSMENT COMPLETE
|
| 2034 |
|
| 2035 |
**Target:** {target_url}
|
| 2036 |
**Date:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
|
| 2037 |
**Threat Level:** {threat_level}
|
| 2038 |
|
| 2039 |
+
### Quick Stats
|
| 2040 |
+
- 🌐 Subdomains: {len(results.get('subdomains', []))}
|
| 2041 |
+
- 🔧 Technologies: {len(results.get('technologies', {}).get('cms', [])) + len(results.get('technologies', {}).get('frameworks', []))}
|
| 2042 |
+
- 📍 Endpoints: {len(results.get('endpoints', []))}
|
| 2043 |
+
- 📝 Forms: {len(results.get('forms', []))}
|
| 2044 |
+
- 📜 JS Files: {len(results.get('js_files', []))}
|
| 2045 |
+
- ⚠️ Threat Vectors: {len(results.get('threat_vectors', []))}
|
| 2046 |
+
- 🎯 Attack Paths: {len(results.get('attack_paths', []))}
|
| 2047 |
+
|
| 2048 |
+
### Vulnerability Summary
|
| 2049 |
+
- 🔴 **Critical:** {critical}
|
| 2050 |
+
- 🟠 **High:** {high}
|
| 2051 |
+
- 🟡 **Medium:** {medium}
|
| 2052 |
+
|
| 2053 |
+
### Technologies Detected
|
| 2054 |
+
- **Web Server:** {results.get('technologies', {}).get('web_server', 'Unknown')}
|
| 2055 |
+
- **CMS:** {', '.join(results.get('technologies', {}).get('cms', ['None']))}
|
| 2056 |
+
- **Frameworks:** {', '.join(results.get('technologies', {}).get('frameworks', ['None']))}
|
| 2057 |
+
- **Security Headers Score:** {results.get('security_headers', {}).get('score', 0):.1f}%
|
| 2058 |
+
|
| 2059 |
+
### Top Recommendations
|
| 2060 |
+
1. {"Patch critical vulnerabilities immediately" if critical > 0 else "Review security headers"}
|
| 2061 |
+
2. {"Update outdated CMS/plugins" if 'WordPress' in str(results.get('technologies', {}).get('cms', [])) else "Enable security headers"}
|
| 2062 |
+
3. Review exposed endpoints for sensitive information
|
| 2063 |
"""
|
| 2064 |
|
| 2065 |
return (
|
| 2066 |
+
summary,
|
| 2067 |
json.dumps(results, indent=2, default=str),
|
| 2068 |
fig,
|
| 2069 |
results.get("report", "No report generated")
|
|
|
|
| 2073 |
error_msg = f"Error: {str(e)}"
|
| 2074 |
import traceback
|
| 2075 |
error_detail = traceback.format_exc()
|
| 2076 |
+
return error_msg, f"{{\\n \\"error\\": \\"{str(e)}\\",\\n \\"traceback\\": \\"{error_detail}\\"\\n}}", go.Figure(), error_msg
|
| 2077 |
+
|
| 2078 |
+
# ════════════════════════════════════════════════════════════════════════════
|
| 2079 |
+
# GRADIO UI DEFINITION
|
| 2080 |
+
# ════════════════════════════════════════════════════════════════════════════
|
| 2081 |
|
| 2082 |
def create_interface():
|
| 2083 |
+
"""Create Gradio interface"""
|
| 2084 |
+
|
| 2085 |
with gr.Blocks(
|
| 2086 |
theme=gr.themes.Soft(primary_hue="red"),
|
| 2087 |
title="Red Team Recon Framework v3.0",
|
| 2088 |
css="""
|
| 2089 |
+
.main-header { text-align: center; color: #ff0000; }
|
| 2090 |
.disclaimer { background-color: #ffeeee; padding: 10px; border-left: 5px solid #ff0000; }
|
| 2091 |
"""
|
| 2092 |
) as demo:
|
| 2093 |
|
| 2094 |
gr.Markdown("""
|
| 2095 |
+
# 🛡️ RED TEAM ADVANCED WEB RECONNAISSANCE FRAMEWORK v3.0
|
| 2096 |
### Professional Security Assessment Tool - Private Space Edition
|
| 2097 |
|
| 2098 |
<div class="disclaimer">
|
| 2099 |
+
⚠️ <strong>DISCLAIMER:</strong> This tool is intended for authorized security testing only.
|
| 2100 |
+
Unauthorized access to computer systems is illegal. Use only on systems you own or have
|
| 2101 |
+
explicit written permission to test.
|
| 2102 |
</div>
|
| 2103 |
|
| 2104 |
**Features:**
|
| 2105 |
+
- 🕵️ Passive OSINT (DNS, SSL, GitHub, crt.sh, Wayback)
|
| 2106 |
+
- 📡 Active Reconnaissance (Fingerprinting, endpoint discovery)
|
| 2107 |
+
- 🎯 Vulnerability Analysis (Pattern-based detection)
|
| 2108 |
+
- 🧠 Threat Modeling (STRIDE + MITRE ATT&CK)
|
| 2109 |
+
- 📊 Advanced Attack Surface Visualization
|
| 2110 |
+
- 📝 Professional Reporting (CVSS v3.1, OWASP, Compliance)
|
| 2111 |
""")
|
| 2112 |
|
| 2113 |
with gr.Row():
|
|
|
|
| 2121 |
threat_level = gr.Radio(
|
| 2122 |
choices=["Low (Stealthy)", "Medium (Balanced)", "High (Aggressive)"],
|
| 2123 |
value="Medium (Balanced)",
|
| 2124 |
+
label="Threat Level / Scan Intensity"
|
| 2125 |
)
|
| 2126 |
|
| 2127 |
+
scan_button = gr.Button("🚀 START ASSESSMENT", variant="primary", size="lg")
|
| 2128 |
+
|
| 2129 |
+
gr.Markdown("""
|
| 2130 |
+
### About Threat Levels
|
| 2131 |
+
- **Low**: Slow, stealthy scanning with delays (good for evasion)
|
| 2132 |
+
- **Medium**: Balanced speed and stealth (recommended)
|
| 2133 |
+
- **High**: Fast, aggressive scanning (may trigger WAF)
|
| 2134 |
+
""")
|
| 2135 |
|
| 2136 |
with gr.Column(scale=1):
|
| 2137 |
gr.Markdown("""
|
| 2138 |
+
### Assessment Methodology
|
| 2139 |
+
|
| 2140 |
+
1. **Passive OSINT** (Non-intrusive)
|
| 2141 |
+
- DNS enumeration (A, AAAA, MX, NS, TXT)
|
| 2142 |
+
- SSL certificate analysis
|
| 2143 |
+
- Certificate Transparency logs
|
| 2144 |
+
- GitHub reconnaissance
|
| 2145 |
+
- Wayback Machine historical data
|
| 2146 |
+
|
| 2147 |
+
2. **Active Reconnaissance**
|
| 2148 |
+
- Technology fingerprinting
|
| 2149 |
+
- Security headers analysis
|
| 2150 |
+
- Endpoint discovery
|
| 2151 |
+
- Form analysis
|
| 2152 |
+
- JavaScript analysis
|
| 2153 |
+
|
| 2154 |
+
3. **Vulnerability Analysis**
|
| 2155 |
+
- Pattern-based detection
|
| 2156 |
+
- Configuration weaknesses
|
| 2157 |
+
- Information disclosure
|
| 2158 |
+
- Injection vulnerability checks
|
| 2159 |
+
|
| 2160 |
+
4. **Threat Modeling**
|
| 2161 |
+
- STRIDE analysis
|
| 2162 |
+
- Attack path generation
|
| 2163 |
+
- MITRE ATT&CK mapping
|
| 2164 |
+
- CVSS v3.1 scoring
|
| 2165 |
|
| 2166 |
+
5. **Reporting**
|
| 2167 |
+
- Executive summary
|
| 2168 |
+
- Technical findings
|
| 2169 |
+
- Remediation guidance
|
| 2170 |
+
- Compliance mapping
|
| 2171 |
""")
|
| 2172 |
|
| 2173 |
with gr.Tabs():
|
| 2174 |
+
with gr.Tab("📊 Summary"):
|
| 2175 |
summary_output = gr.Markdown(label="Assessment Summary")
|
| 2176 |
|
| 2177 |
+
with gr.Tab("📈 Attack Graph"):
|
| 2178 |
graph_output = gr.Plot(label="Attack Surface Visualization")
|
| 2179 |
|
| 2180 |
+
with gr.Tab("🔍 Raw Data"):
|
| 2181 |
+
json_output = gr.Code(
|
| 2182 |
+
language="json",
|
| 2183 |
+
label="Detailed Findings (JSON)",
|
| 2184 |
+
lines=30
|
| 2185 |
+
)
|
| 2186 |
+
|
| 2187 |
+
with gr.Tab("📋 Full Report"):
|
| 2188 |
+
report_output = gr.Textbox(
|
| 2189 |
+
label="Security Assessment Report",
|
| 2190 |
+
lines=40,
|
| 2191 |
+
max_lines=100,
|
| 2192 |
+
interactive=False
|
| 2193 |
+
)
|
| 2194 |
+
|
| 2195 |
+
with gr.Tab("⚠️ Vulnerabilities"):
|
| 2196 |
+
vulns_output = gr.Dataframe(
|
| 2197 |
+
headers=["Name", "Severity", "CVSS", "Location", "CWE"],
|
| 2198 |
+
label="Discovered Vulnerabilities"
|
| 2199 |
+
)
|
| 2200 |
|
| 2201 |
+
with gr.Tab("🎯 MITRE ATT&CK"):
|
| 2202 |
+
mitre_output = gr.JSON(label="MITRE ATT&CK Mapping")
|
| 2203 |
|
| 2204 |
+
# Button click handler
|
| 2205 |
scan_button.click(
|
| 2206 |
fn=run_assessment,
|
| 2207 |
inputs=[target_input, threat_level],
|
| 2208 |
outputs=[summary_output, json_output, graph_output, report_output]
|
| 2209 |
)
|
| 2210 |
+
|
| 2211 |
+
gr.Markdown("""
|
| 2212 |
+
---
|
| 2213 |
+
**Red Team Recon Framework v3.0** | Private Space Edition | Generated: {datetime.now().strftime('%Y-%m-%d')}
|
| 2214 |
+
""")
|
| 2215 |
|
| 2216 |
return demo
|
| 2217 |
|
| 2218 |
+
# ════════════════════════════════════════════════════════════════════════════
|
| 2219 |
+
# LAUNCH
|
| 2220 |
+
# ════════════════════════════════════════════════════════════════════════════
|
| 2221 |
+
|
| 2222 |
if __name__ == "__main__":
|
| 2223 |
demo = create_interface()
|
| 2224 |
demo.launch(
|
| 2225 |
+
share=False, # Set to True for public sharing (not recommended for private space)
|
| 2226 |
server_name="0.0.0.0",
|
| 2227 |
server_port=7860,
|
| 2228 |
show_error=True
|
| 2229 |
)
|
| 2230 |
+
|
| 2231 |
+
print("PART 2 KODU HAZIR (Bölümler 8-10)")
|
| 2232 |
+
print("=" * 60)
|
| 2233 |
+
print("Bu kodu app_part2.py olarak kaydedin")
|
| 2234 |
+
print("İçerik:")
|
| 2235 |
+
print(" - Bölüm 8: Comprehensive Reporting Engine")
|
| 2236 |
+
print(" - Bölüm 9: Main Orchestrator")
|
| 2237 |
+
print(" - Bölüm 10: Gradio Interface")
|
| 2238 |
+
'''
|
| 2239 |
+
|
| 2240 |
+
print(part2_code)
|