zen-ai-pentest 2.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agents/__init__.py +28 -0
- agents/agent_base.py +239 -0
- agents/agent_orchestrator.py +346 -0
- agents/analysis_agent.py +225 -0
- agents/cli.py +258 -0
- agents/exploit_agent.py +224 -0
- agents/integration.py +211 -0
- agents/post_scan_agent.py +937 -0
- agents/react_agent.py +384 -0
- agents/react_agent_enhanced.py +616 -0
- agents/react_agent_vm.py +298 -0
- agents/research_agent.py +176 -0
- api/__init__.py +11 -0
- api/auth.py +123 -0
- api/main.py +1027 -0
- api/schemas.py +357 -0
- api/websocket.py +97 -0
- autonomous/__init__.py +122 -0
- autonomous/agent.py +253 -0
- autonomous/agent_loop.py +1370 -0
- autonomous/exploit_validator.py +1537 -0
- autonomous/memory.py +448 -0
- autonomous/react.py +339 -0
- autonomous/tool_executor.py +488 -0
- backends/__init__.py +16 -0
- backends/chatgpt_direct.py +133 -0
- backends/claude_direct.py +130 -0
- backends/duckduckgo.py +138 -0
- backends/openrouter.py +120 -0
- benchmarks/__init__.py +149 -0
- benchmarks/benchmark_engine.py +904 -0
- benchmarks/ci_benchmark.py +785 -0
- benchmarks/comparison.py +729 -0
- benchmarks/metrics.py +553 -0
- benchmarks/run_benchmarks.py +809 -0
- ci_cd/__init__.py +2 -0
- core/__init__.py +17 -0
- core/async_pool.py +282 -0
- core/asyncio_fix.py +222 -0
- core/cache.py +472 -0
- core/container.py +277 -0
- core/database.py +114 -0
- core/input_validator.py +353 -0
- core/models.py +288 -0
- core/orchestrator.py +611 -0
- core/plugin_manager.py +571 -0
- core/rate_limiter.py +405 -0
- core/secure_config.py +328 -0
- core/shield_integration.py +296 -0
- modules/__init__.py +46 -0
- modules/cve_database.py +362 -0
- modules/exploit_assist.py +330 -0
- modules/nuclei_integration.py +480 -0
- modules/osint.py +604 -0
- modules/protonvpn.py +554 -0
- modules/recon.py +165 -0
- modules/sql_injection_db.py +826 -0
- modules/tool_orchestrator.py +498 -0
- modules/vuln_scanner.py +292 -0
- modules/wordlist_generator.py +566 -0
- risk_engine/__init__.py +99 -0
- risk_engine/business_impact.py +267 -0
- risk_engine/business_impact_calculator.py +563 -0
- risk_engine/cvss.py +156 -0
- risk_engine/epss.py +190 -0
- risk_engine/example_usage.py +294 -0
- risk_engine/false_positive_engine.py +1073 -0
- risk_engine/scorer.py +304 -0
- web_ui/backend/main.py +471 -0
- zen_ai_pentest-2.0.0.dist-info/METADATA +795 -0
- zen_ai_pentest-2.0.0.dist-info/RECORD +75 -0
- zen_ai_pentest-2.0.0.dist-info/WHEEL +5 -0
- zen_ai_pentest-2.0.0.dist-info/entry_points.txt +2 -0
- zen_ai_pentest-2.0.0.dist-info/licenses/LICENSE +21 -0
- zen_ai_pentest-2.0.0.dist-info/top_level.txt +10 -0
risk_engine/cvss.py
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CVSS (Common Vulnerability Scoring System) Calculator
|
|
3
|
+
|
|
4
|
+
Supports CVSS v3.1
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import re
|
|
8
|
+
from typing import Dict, Optional
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class CVSSCalculator:
|
|
12
|
+
"""Calculate CVSS v3.1 base scores."""
|
|
13
|
+
|
|
14
|
+
# CVSS v3.1 weights
|
|
15
|
+
WEIGHTS = {
|
|
16
|
+
'AV': {'N': 0.85, 'A': 0.62, 'L': 0.55, 'P': 0.2},
|
|
17
|
+
'AC': {'L': 0.77, 'H': 0.44},
|
|
18
|
+
'PR': {'N': 0.85, 'L': 0.62, 'H': 0.27},
|
|
19
|
+
'UI': {'N': 0.85, 'R': 0.62},
|
|
20
|
+
'S': {'U': 6.42, 'C': 7.52},
|
|
21
|
+
'C': {'H': 0.56, 'L': 0.22, 'N': 0},
|
|
22
|
+
'I': {'H': 0.56, 'L': 0.22, 'N': 0},
|
|
23
|
+
'A': {'H': 0.56, 'L': 0.22, 'N': 0}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
def calculate(self, metrics: Dict[str, str]) -> float:
|
|
27
|
+
"""
|
|
28
|
+
Calculate CVSS v3.1 base score from metrics.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
metrics: Dict with keys AV, AC, PR, UI, S, C, I, A
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
CVSS score 0.0-10.0
|
|
35
|
+
"""
|
|
36
|
+
try:
|
|
37
|
+
# Exploitability
|
|
38
|
+
av = self.WEIGHTS['AV'].get(metrics.get('AV', 'N'), 0.85)
|
|
39
|
+
ac = self.WEIGHTS['AC'].get(metrics.get('AC', 'L'), 0.77)
|
|
40
|
+
pr = self.WEIGHTS['PR'].get(metrics.get('PR', 'N'), 0.85)
|
|
41
|
+
ui = self.WEIGHTS['UI'].get(metrics.get('UI', 'N'), 0.85)
|
|
42
|
+
|
|
43
|
+
# Impact
|
|
44
|
+
c = self.WEIGHTS['C'].get(metrics.get('C', 'N'), 0)
|
|
45
|
+
i = self.WEIGHTS['I'].get(metrics.get('I', 'N'), 0)
|
|
46
|
+
a = self.WEIGHTS['A'].get(metrics.get('A', 'N'), 0)
|
|
47
|
+
s = self.WEIGHTS['S'].get(metrics.get('S', 'U'), 6.42)
|
|
48
|
+
|
|
49
|
+
# Calculate Impact Sub-Score (ISS)
|
|
50
|
+
iss = 1 - ((1 - c) * (1 - i) * (1 - a))
|
|
51
|
+
|
|
52
|
+
# Calculate Impact
|
|
53
|
+
if metrics.get('S', 'U') == 'C':
|
|
54
|
+
impact = 7.52 * (iss - 0.029) - 3.25 * (iss - 0.02) ** 15
|
|
55
|
+
else:
|
|
56
|
+
impact = 6.42 * iss
|
|
57
|
+
|
|
58
|
+
# Calculate Exploitability
|
|
59
|
+
exploitability = 8.22 * av * ac * pr * ui
|
|
60
|
+
|
|
61
|
+
# Calculate Base Score
|
|
62
|
+
if impact <= 0:
|
|
63
|
+
base_score = 0.0
|
|
64
|
+
else:
|
|
65
|
+
if metrics.get('S', 'U') == 'C':
|
|
66
|
+
base_score = min(1.08 * (impact + exploitability), 10)
|
|
67
|
+
else:
|
|
68
|
+
base_score = min(impact + exploitability, 10)
|
|
69
|
+
|
|
70
|
+
# Round to one decimal place
|
|
71
|
+
return round(base_score, 1)
|
|
72
|
+
|
|
73
|
+
except Exception as e:
|
|
74
|
+
return 5.0 # Default on error
|
|
75
|
+
|
|
76
|
+
def from_cve(self, cve_id: str) -> float:
|
|
77
|
+
"""
|
|
78
|
+
Get CVSS score from CVE ID.
|
|
79
|
+
In production, query NVD API or local database.
|
|
80
|
+
"""
|
|
81
|
+
# Simulated lookup - in production query NVD
|
|
82
|
+
# Common CVEs for testing
|
|
83
|
+
known_scores = {
|
|
84
|
+
'CVE-2021-44228': 10.0, # Log4j
|
|
85
|
+
'CVE-2017-0144': 8.1, # EternalBlue
|
|
86
|
+
'CVE-2014-0160': 5.0, # Heartbleed
|
|
87
|
+
'CVE-2019-11358': 6.1, # jQuery
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return known_scores.get(cve_id.upper(), 5.0)
|
|
91
|
+
|
|
92
|
+
def estimate(self, description: str) -> float:
|
|
93
|
+
"""
|
|
94
|
+
Estimate CVSS score from vulnerability description.
|
|
95
|
+
Uses keyword matching for quick estimation.
|
|
96
|
+
"""
|
|
97
|
+
description_lower = description.lower()
|
|
98
|
+
score = 5.0 # Default
|
|
99
|
+
|
|
100
|
+
# Critical indicators
|
|
101
|
+
if any(kw in description_lower for kw in ['rce', 'remote code execution', 'arbitrary code']):
|
|
102
|
+
score = 9.8
|
|
103
|
+
elif 'sql injection' in description_lower:
|
|
104
|
+
score = 8.6
|
|
105
|
+
elif 'xss' in description_lower or 'cross-site scripting' in description_lower:
|
|
106
|
+
score = 6.1
|
|
107
|
+
elif 'denial of service' in description_lower or 'dos' in description_lower:
|
|
108
|
+
score = 7.5
|
|
109
|
+
elif 'information disclosure' in description_lower:
|
|
110
|
+
score = 5.3
|
|
111
|
+
elif 'authentication bypass' in description_lower:
|
|
112
|
+
score = 8.1
|
|
113
|
+
|
|
114
|
+
# Adjust for network accessibility
|
|
115
|
+
if 'network' in description_lower or 'remote' in description_lower:
|
|
116
|
+
score = min(score + 0.5, 10.0)
|
|
117
|
+
|
|
118
|
+
# Adjust for no auth required
|
|
119
|
+
if 'unauthenticated' in description_lower or 'without authentication' in description_lower:
|
|
120
|
+
score = min(score + 0.3, 10.0)
|
|
121
|
+
|
|
122
|
+
return round(score, 1)
|
|
123
|
+
|
|
124
|
+
def get_details(self, finding: Dict) -> Dict:
|
|
125
|
+
"""Get detailed CVSS breakdown."""
|
|
126
|
+
score = finding.get('cvss_score', 5.0)
|
|
127
|
+
|
|
128
|
+
# Determine severity rating
|
|
129
|
+
if score >= 9.0:
|
|
130
|
+
severity = 'Critical'
|
|
131
|
+
elif score >= 7.0:
|
|
132
|
+
severity = 'High'
|
|
133
|
+
elif score >= 4.0:
|
|
134
|
+
severity = 'Medium'
|
|
135
|
+
elif score >= 0.1:
|
|
136
|
+
severity = 'Low'
|
|
137
|
+
else:
|
|
138
|
+
severity = 'None'
|
|
139
|
+
|
|
140
|
+
return {
|
|
141
|
+
'base_score': score,
|
|
142
|
+
'severity': severity,
|
|
143
|
+
'vector': finding.get('cvss_vector', 'Unknown'),
|
|
144
|
+
'version': finding.get('cvss_version', '3.1')
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
def get_vector_from_metrics(self, metrics: Dict[str, str]) -> str:
|
|
148
|
+
"""Generate CVSS vector string from metrics."""
|
|
149
|
+
parts = ['CVSS:3.1']
|
|
150
|
+
|
|
151
|
+
metric_order = ['AV', 'AC', 'PR', 'UI', 'S', 'C', 'I', 'A']
|
|
152
|
+
for metric in metric_order:
|
|
153
|
+
if metric in metrics:
|
|
154
|
+
parts.append(f"{metric}:{metrics[metric]}")
|
|
155
|
+
|
|
156
|
+
return '/'.join(parts)
|
risk_engine/epss.py
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
"""
|
|
2
|
+
EPSS (Exploit Prediction Scoring System) Client
|
|
3
|
+
|
|
4
|
+
Fetches exploit probability scores from FIRST EPSS API.
|
|
5
|
+
https://www.first.org/epss/
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import asyncio
|
|
9
|
+
import json
|
|
10
|
+
import logging
|
|
11
|
+
from datetime import datetime, timedelta
|
|
12
|
+
from typing import Dict, List, Optional
|
|
13
|
+
|
|
14
|
+
import requests
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class EPSSClient:
|
|
18
|
+
"""
|
|
19
|
+
Client for FIRST EPSS API.
|
|
20
|
+
|
|
21
|
+
EPSS provides the probability that a vulnerability will be exploited
|
|
22
|
+
in the wild within the next 30 days.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
API_URL = "https://api.first.org/data/v1/epss"
|
|
26
|
+
|
|
27
|
+
def __init__(self, cache_duration: int = 24):
|
|
28
|
+
"""
|
|
29
|
+
Initialize EPSS client.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
cache_duration: Hours to cache results
|
|
33
|
+
"""
|
|
34
|
+
self.cache: Dict[str, Dict] = {}
|
|
35
|
+
self.cache_duration = timedelta(hours=cache_duration)
|
|
36
|
+
self.logger = logging.getLogger(__name__)
|
|
37
|
+
|
|
38
|
+
def get_score(self, cve_id: str) -> float:
|
|
39
|
+
"""
|
|
40
|
+
Get EPSS score for a CVE.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
cve_id: CVE ID (e.g., "CVE-2021-44228")
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
EPSS score 0.0-1.0 (probability of exploitation)
|
|
47
|
+
"""
|
|
48
|
+
cve_id = cve_id.upper()
|
|
49
|
+
|
|
50
|
+
# Check cache
|
|
51
|
+
if cve_id in self.cache:
|
|
52
|
+
cached = self.cache[cve_id]
|
|
53
|
+
if datetime.now() - cached['timestamp'] < self.cache_duration:
|
|
54
|
+
return cached['score']
|
|
55
|
+
|
|
56
|
+
# Fetch from API
|
|
57
|
+
try:
|
|
58
|
+
score = self._fetch_epss(cve_id)
|
|
59
|
+
self.cache[cve_id] = {
|
|
60
|
+
'score': score,
|
|
61
|
+
'timestamp': datetime.now()
|
|
62
|
+
}
|
|
63
|
+
return score
|
|
64
|
+
|
|
65
|
+
except Exception as e:
|
|
66
|
+
self.logger.warning(f"Failed to fetch EPSS for {cve_id}: {e}")
|
|
67
|
+
return 0.0
|
|
68
|
+
|
|
69
|
+
def _fetch_epss(self, cve_id: str) -> float:
|
|
70
|
+
"""Fetch EPSS score from API."""
|
|
71
|
+
try:
|
|
72
|
+
response = requests.get(
|
|
73
|
+
self.API_URL,
|
|
74
|
+
params={'cve': cve_id},
|
|
75
|
+
timeout=10
|
|
76
|
+
)
|
|
77
|
+
response.raise_for_status()
|
|
78
|
+
|
|
79
|
+
data = response.json()
|
|
80
|
+
|
|
81
|
+
if data.get('data') and len(data['data']) > 0:
|
|
82
|
+
epss_data = data['data'][0]
|
|
83
|
+
return float(epss_data.get('epss', 0))
|
|
84
|
+
|
|
85
|
+
return 0.0
|
|
86
|
+
|
|
87
|
+
except requests.RequestException as e:
|
|
88
|
+
self.logger.error(f"EPSS API request failed: {e}")
|
|
89
|
+
raise
|
|
90
|
+
|
|
91
|
+
def get_batch_scores(self, cve_ids: List[str]) -> Dict[str, float]:
|
|
92
|
+
"""
|
|
93
|
+
Get EPSS scores for multiple CVEs in one request.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
cve_ids: List of CVE IDs
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
Dict mapping CVE ID to EPSS score
|
|
100
|
+
"""
|
|
101
|
+
if not cve_ids:
|
|
102
|
+
return {}
|
|
103
|
+
|
|
104
|
+
try:
|
|
105
|
+
response = requests.get(
|
|
106
|
+
self.API_URL,
|
|
107
|
+
params={'cve': ','.join(cve_ids[:100])}, # API limit
|
|
108
|
+
timeout=30
|
|
109
|
+
)
|
|
110
|
+
response.raise_for_status()
|
|
111
|
+
|
|
112
|
+
data = response.json()
|
|
113
|
+
results = {}
|
|
114
|
+
|
|
115
|
+
for item in data.get('data', []):
|
|
116
|
+
cve = item.get('cve', '').upper()
|
|
117
|
+
score = float(item.get('epss', 0))
|
|
118
|
+
results[cve] = score
|
|
119
|
+
|
|
120
|
+
# Update cache
|
|
121
|
+
self.cache[cve] = {
|
|
122
|
+
'score': score,
|
|
123
|
+
'timestamp': datetime.now()
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
# Fill in missing CVEs with 0
|
|
127
|
+
for cve in cve_ids:
|
|
128
|
+
if cve.upper() not in results:
|
|
129
|
+
results[cve.upper()] = 0.0
|
|
130
|
+
|
|
131
|
+
return results
|
|
132
|
+
|
|
133
|
+
except Exception as e:
|
|
134
|
+
self.logger.error(f"Batch EPSS fetch failed: {e}")
|
|
135
|
+
return {cve.upper(): 0.0 for cve in cve_ids}
|
|
136
|
+
|
|
137
|
+
def get_percentile(self, cve_id: str) -> Optional[float]:
|
|
138
|
+
"""
|
|
139
|
+
Get EPSS percentile for a CVE.
|
|
140
|
+
|
|
141
|
+
Indicates how this CVE ranks compared to all others.
|
|
142
|
+
"""
|
|
143
|
+
try:
|
|
144
|
+
response = requests.get(
|
|
145
|
+
self.API_URL,
|
|
146
|
+
params={'cve': cve_id.upper()},
|
|
147
|
+
timeout=10
|
|
148
|
+
)
|
|
149
|
+
response.raise_for_status()
|
|
150
|
+
|
|
151
|
+
data = response.json()
|
|
152
|
+
|
|
153
|
+
if data.get('data') and len(data['data']) > 0:
|
|
154
|
+
percentile = data['data'][0].get('percentile')
|
|
155
|
+
return float(percentile) if percentile else None
|
|
156
|
+
|
|
157
|
+
return None
|
|
158
|
+
|
|
159
|
+
except Exception as e:
|
|
160
|
+
self.logger.warning(f"Failed to fetch EPSS percentile: {e}")
|
|
161
|
+
return None
|
|
162
|
+
|
|
163
|
+
def interpret_score(self, score: float) -> str:
|
|
164
|
+
"""
|
|
165
|
+
Provide human-readable interpretation of EPSS score.
|
|
166
|
+
"""
|
|
167
|
+
if score >= 0.5:
|
|
168
|
+
return "Very High - Active exploitation likely"
|
|
169
|
+
elif score >= 0.3:
|
|
170
|
+
return "High - Exploitation probable"
|
|
171
|
+
elif score >= 0.1:
|
|
172
|
+
return "Medium - Some exploitation risk"
|
|
173
|
+
elif score >= 0.05:
|
|
174
|
+
return "Low - Limited exploitation risk"
|
|
175
|
+
else:
|
|
176
|
+
return "Very Low - Unlikely to be exploited"
|
|
177
|
+
|
|
178
|
+
def should_prioritize(self, cve_id: str, threshold: float = 0.2) -> bool:
|
|
179
|
+
"""
|
|
180
|
+
Determine if a CVE should be prioritized based on EPSS.
|
|
181
|
+
|
|
182
|
+
Args:
|
|
183
|
+
cve_id: CVE to check
|
|
184
|
+
threshold: EPSS threshold for prioritization (default 20%)
|
|
185
|
+
|
|
186
|
+
Returns:
|
|
187
|
+
True if should prioritize
|
|
188
|
+
"""
|
|
189
|
+
score = self.get_score(cve_id)
|
|
190
|
+
return score >= threshold
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Beispiel für die Verwendung der False-Positive-Reduction Engine.
|
|
3
|
+
|
|
4
|
+
Dieses Beispiel zeigt, wie die Engine zur Validierung und Priorisierung
|
|
5
|
+
von Security Findings verwendet wird.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import asyncio
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
|
|
11
|
+
from risk_engine import (
|
|
12
|
+
FalsePositiveEngine,
|
|
13
|
+
BusinessImpactCalculator,
|
|
14
|
+
Finding,
|
|
15
|
+
RiskFactors,
|
|
16
|
+
CVSSData,
|
|
17
|
+
AssetContext,
|
|
18
|
+
AssetCriticality,
|
|
19
|
+
DataClassification,
|
|
20
|
+
ComplianceFramework,
|
|
21
|
+
create_finding_from_scan_result,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
async def example_false_positive_detection():
|
|
26
|
+
"""Beispiel: False-Positive-Erkennung."""
|
|
27
|
+
print("=" * 60)
|
|
28
|
+
print("Beispiel 1: False-Positive-Erkennung")
|
|
29
|
+
print("=" * 60)
|
|
30
|
+
|
|
31
|
+
# Engine initialisieren
|
|
32
|
+
engine = FalsePositiveEngine(
|
|
33
|
+
fp_database_path="fp_database.json",
|
|
34
|
+
enable_llm_voting=False # In Produktion auf True setzen
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
# Beispiel-Finding 1: SQL Injection (echte Schwachstelle)
|
|
38
|
+
finding_real = Finding(
|
|
39
|
+
id="FIND-001",
|
|
40
|
+
title="SQL Injection in Login-Form",
|
|
41
|
+
description="Die Login-Formular ist anfällig für SQL-Injection-Angriffe. "
|
|
42
|
+
"Ein Angreifer kann durch Manipulation des Benutzernamen-Feldes "
|
|
43
|
+
"authentifizierte Zugriffe erlangen.",
|
|
44
|
+
severity="critical",
|
|
45
|
+
vulnerability_type="sql_injection",
|
|
46
|
+
risk_factors=RiskFactors(
|
|
47
|
+
cvss_data=CVSSData(
|
|
48
|
+
base_score=9.8,
|
|
49
|
+
vector_string="CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"
|
|
50
|
+
),
|
|
51
|
+
epss_score=0.95,
|
|
52
|
+
business_impact=0.9,
|
|
53
|
+
exploitability=0.95,
|
|
54
|
+
asset_criticality=1.0,
|
|
55
|
+
internet_exposed=True,
|
|
56
|
+
data_classification="restricted",
|
|
57
|
+
patch_available=False,
|
|
58
|
+
exploit_code_available=True,
|
|
59
|
+
),
|
|
60
|
+
raw_evidence={
|
|
61
|
+
"payload": "' OR '1'='1",
|
|
62
|
+
"response": "Login successful",
|
|
63
|
+
"endpoint": "/api/login"
|
|
64
|
+
},
|
|
65
|
+
target="https://example.com/api/login",
|
|
66
|
+
cve_ids=["CVE-2023-1234"]
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
# Beispiel-Finding 2: Informational (wahrscheinlich FP)
|
|
70
|
+
finding_info = Finding(
|
|
71
|
+
id="FIND-002",
|
|
72
|
+
title="Informational: Server Banner Detected",
|
|
73
|
+
description="Der Webserver sendet einen Server-Header mit Versionsinformationen. "
|
|
74
|
+
"Dies ist eine informative Feststellung und stellt nicht direkt eine "
|
|
75
|
+
"Schwachstelle dar, könnte aber für Reconnaissance genutzt werden.",
|
|
76
|
+
severity="info",
|
|
77
|
+
vulnerability_type="information_disclosure",
|
|
78
|
+
risk_factors=RiskFactors(
|
|
79
|
+
cvss_data=CVSSData(base_score=2.3),
|
|
80
|
+
epss_score=0.05,
|
|
81
|
+
business_impact=0.1,
|
|
82
|
+
exploitability=0.1,
|
|
83
|
+
asset_criticality=0.3,
|
|
84
|
+
internet_exposed=True,
|
|
85
|
+
data_classification="public",
|
|
86
|
+
patch_available=True,
|
|
87
|
+
),
|
|
88
|
+
raw_evidence={
|
|
89
|
+
"header": "Server: Apache/2.4.41"
|
|
90
|
+
},
|
|
91
|
+
target="https://example.com"
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
# Validierung durchführen
|
|
95
|
+
result1 = await engine.validate_finding(finding_real)
|
|
96
|
+
result2 = await engine.validate_finding(finding_info)
|
|
97
|
+
|
|
98
|
+
# Ergebnisse anzeigen
|
|
99
|
+
print("\n--- Finding 1: SQL Injection ---")
|
|
100
|
+
print(f"False Positive: {result1.is_false_positive}")
|
|
101
|
+
print(f"Konfidenz: {result1.confidence:.2%}")
|
|
102
|
+
print(f"Risiko-Score: {result1.risk_score:.2f}")
|
|
103
|
+
print(f"Priorität: {result1.priority}")
|
|
104
|
+
print(f"Status: {result1.finding.status.value}")
|
|
105
|
+
print(f"Begründung: {result1.reasoning}")
|
|
106
|
+
print("Empfehlungen:")
|
|
107
|
+
for rec in result1.recommendations:
|
|
108
|
+
print(f" - {rec}")
|
|
109
|
+
|
|
110
|
+
print("\n--- Finding 2: Informational ---")
|
|
111
|
+
print(f"False Positive: {result2.is_false_positive}")
|
|
112
|
+
print(f"Konfidenz: {result2.confidence:.2%}")
|
|
113
|
+
print(f"Risiko-Score: {result2.risk_score:.2f}")
|
|
114
|
+
print(f"Priorität: {result2.priority}")
|
|
115
|
+
print(f"Status: {result2.finding.status.value}")
|
|
116
|
+
print(f"Begründung: {result2.reasoning}")
|
|
117
|
+
print("Empfehlungen:")
|
|
118
|
+
for rec in result2.recommendations:
|
|
119
|
+
print(f" - {rec}")
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
async def example_business_impact_calculation():
|
|
123
|
+
"""Beispiel: Business-Impact-Berechnung."""
|
|
124
|
+
print("\n" + "=" * 60)
|
|
125
|
+
print("Beispiel 2: Business-Impact-Berechnung")
|
|
126
|
+
print("=" * 60)
|
|
127
|
+
|
|
128
|
+
# Calculator initialisieren
|
|
129
|
+
calculator = BusinessImpactCalculator(
|
|
130
|
+
organization_size="large",
|
|
131
|
+
annual_revenue=500000000, # 500M EUR
|
|
132
|
+
industry="finance"
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
# Asset-Kontext erstellen
|
|
136
|
+
asset = AssetContext(
|
|
137
|
+
asset_id="PROD-DB-001",
|
|
138
|
+
asset_name="Production Customer Database",
|
|
139
|
+
asset_type="database",
|
|
140
|
+
criticality=AssetCriticality.CRITICAL,
|
|
141
|
+
data_classification=DataClassification.RESTRICTED,
|
|
142
|
+
compliance_frameworks={
|
|
143
|
+
ComplianceFramework.GDPR,
|
|
144
|
+
ComplianceFramework.PCI_DSS
|
|
145
|
+
},
|
|
146
|
+
internet_exposed=False,
|
|
147
|
+
user_count=5000000,
|
|
148
|
+
revenue_dependency=40.0
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
# Impact berechnen
|
|
152
|
+
impact = calculator.calculate_overall_impact(
|
|
153
|
+
asset_context=asset,
|
|
154
|
+
finding_type="sql_injection",
|
|
155
|
+
severity="critical",
|
|
156
|
+
breach_likelihood=0.8,
|
|
157
|
+
data_volume_records=5000000
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
# Ergebnisse anzeigen
|
|
161
|
+
print(f"\nAsset: {asset.asset_name}")
|
|
162
|
+
print(f"Gesamt-Impact-Score: {impact.overall_score:.2f}")
|
|
163
|
+
print(f"Risiko-Kategorie: {impact.get_risk_category()}")
|
|
164
|
+
|
|
165
|
+
print(f"\nFinanzieller Impact:")
|
|
166
|
+
print(f" Direkte Kosten: €{impact.financial_impact.direct_costs:,.2f}")
|
|
167
|
+
print(f" Indirekte Kosten: €{impact.financial_impact.indirect_costs:,.2f}")
|
|
168
|
+
print(f" Regulatorische Strafen: €{impact.financial_impact.regulatory_fines:,.2f}")
|
|
169
|
+
print(f" Rechtskosten: €{impact.financial_impact.legal_costs:,.2f}")
|
|
170
|
+
print(f" Reputationskosten: €{impact.financial_impact.reputation_costs:,.2f}")
|
|
171
|
+
print(f" GESAMT: €{impact.financial_impact.total_costs:,.2f}")
|
|
172
|
+
|
|
173
|
+
print(f"\nCompliance-Impact:")
|
|
174
|
+
print(f" Betroffene Frameworks: {', '.join(f.framework_name for f in impact.compliance_impact.frameworks)}")
|
|
175
|
+
print(f" Verletzte Controls: {', '.join(impact.compliance_impact.violated_controls[:5])}")
|
|
176
|
+
print(f" Maximale Strafe: €{impact.compliance_impact.get_max_fine():,.2f}")
|
|
177
|
+
|
|
178
|
+
print(f"\nReputation-Impact: {impact.reputation_impact.name}")
|
|
179
|
+
print(f" Beschreibung: {impact.reputation_impact.description}")
|
|
180
|
+
|
|
181
|
+
print(f"\nEinzelfaktoren:")
|
|
182
|
+
print(f" Asset-Kritikalität: {impact.asset_criticality_score:.2f}")
|
|
183
|
+
print(f" Daten-Sensitivität: {impact.data_sensitivity_score:.2f}")
|
|
184
|
+
print(f" Expositions-Score: {impact.exposure_score:.2f}")
|
|
185
|
+
|
|
186
|
+
print("\nPriorisierte Empfehlungen:")
|
|
187
|
+
for rec in impact.get_prioritized_remediation():
|
|
188
|
+
print(f" - {rec}")
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
async def example_prioritization():
|
|
192
|
+
"""Beispiel: Finding-Priorisierung."""
|
|
193
|
+
print("\n" + "=" * 60)
|
|
194
|
+
print("Beispiel 3: Finding-Priorisierung")
|
|
195
|
+
print("=" * 60)
|
|
196
|
+
|
|
197
|
+
engine = FalsePositiveEngine(enable_llm_voting=False)
|
|
198
|
+
|
|
199
|
+
# Mehrere Findings erstellen
|
|
200
|
+
findings = [
|
|
201
|
+
Finding(
|
|
202
|
+
id="F001",
|
|
203
|
+
title="Critical SQL Injection",
|
|
204
|
+
description="Remote code execution via SQL injection",
|
|
205
|
+
severity="critical",
|
|
206
|
+
risk_factors=RiskFactors(
|
|
207
|
+
cvss_data=CVSSData(base_score=9.8),
|
|
208
|
+
epss_score=0.9,
|
|
209
|
+
business_impact=0.95,
|
|
210
|
+
exploitability=0.95,
|
|
211
|
+
asset_criticality=1.0,
|
|
212
|
+
internet_exposed=True
|
|
213
|
+
)
|
|
214
|
+
),
|
|
215
|
+
Finding(
|
|
216
|
+
id="F002",
|
|
217
|
+
title="XSS in Admin Panel",
|
|
218
|
+
description="Stored XSS vulnerability",
|
|
219
|
+
severity="high",
|
|
220
|
+
risk_factors=RiskFactors(
|
|
221
|
+
cvss_data=CVSSData(base_score=7.5),
|
|
222
|
+
epss_score=0.6,
|
|
223
|
+
business_impact=0.7,
|
|
224
|
+
exploitability=0.7,
|
|
225
|
+
asset_criticality=0.8,
|
|
226
|
+
internet_exposed=False
|
|
227
|
+
)
|
|
228
|
+
),
|
|
229
|
+
Finding(
|
|
230
|
+
id="F003",
|
|
231
|
+
title="Outdated TLS Version",
|
|
232
|
+
description="TLS 1.0 still supported",
|
|
233
|
+
severity="medium",
|
|
234
|
+
risk_factors=RiskFactors(
|
|
235
|
+
cvss_data=CVSSData(base_score=5.0),
|
|
236
|
+
epss_score=0.2,
|
|
237
|
+
business_impact=0.4,
|
|
238
|
+
exploitability=0.3,
|
|
239
|
+
asset_criticality=0.5,
|
|
240
|
+
internet_exposed=True
|
|
241
|
+
)
|
|
242
|
+
),
|
|
243
|
+
Finding(
|
|
244
|
+
id="F004",
|
|
245
|
+
title="Information Disclosure",
|
|
246
|
+
description="Server version in headers",
|
|
247
|
+
severity="info",
|
|
248
|
+
risk_factors=RiskFactors(
|
|
249
|
+
cvss_data=CVSSData(base_score=2.0),
|
|
250
|
+
epss_score=0.05,
|
|
251
|
+
business_impact=0.1,
|
|
252
|
+
exploitability=0.1,
|
|
253
|
+
asset_criticality=0.3,
|
|
254
|
+
internet_exposed=True
|
|
255
|
+
)
|
|
256
|
+
),
|
|
257
|
+
]
|
|
258
|
+
|
|
259
|
+
# Findings priorisieren
|
|
260
|
+
prioritized = engine.prioritize_findings(findings)
|
|
261
|
+
|
|
262
|
+
print("\nPriorisierte Findings:")
|
|
263
|
+
print(f"{'Rank':<6} {'ID':<8} {'Title':<30} {'Severity':<10} {'Risk Score'}")
|
|
264
|
+
print("-" * 70)
|
|
265
|
+
|
|
266
|
+
for i, finding in enumerate(prioritized, 1):
|
|
267
|
+
risk = engine.calculate_risk_score(finding.risk_factors)
|
|
268
|
+
print(f"{i:<6} {finding.id:<8} {finding.title[:28]:<30} "
|
|
269
|
+
f"{finding.severity:<10} {risk:.2f}")
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
async def main():
|
|
273
|
+
"""Hauptfunktion mit allen Beispielen."""
|
|
274
|
+
print("\n")
|
|
275
|
+
print("╔" + "═" * 58 + "╗")
|
|
276
|
+
print("║" + " Zen-AI-Pentest False-Positive Engine Demo ".center(58) + "║")
|
|
277
|
+
print("╚" + "═" * 58 + "╝")
|
|
278
|
+
|
|
279
|
+
try:
|
|
280
|
+
await example_false_positive_detection()
|
|
281
|
+
await example_business_impact_calculation()
|
|
282
|
+
await example_prioritization()
|
|
283
|
+
|
|
284
|
+
print("\n" + "=" * 60)
|
|
285
|
+
print("Alle Beispiele erfolgreich abgeschlossen!")
|
|
286
|
+
print("=" * 60)
|
|
287
|
+
|
|
288
|
+
except Exception as e:
|
|
289
|
+
print(f"\nFehler: {e}")
|
|
290
|
+
raise
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
if __name__ == "__main__":
|
|
294
|
+
asyncio.run(main())
|