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.
Files changed (75) hide show
  1. agents/__init__.py +28 -0
  2. agents/agent_base.py +239 -0
  3. agents/agent_orchestrator.py +346 -0
  4. agents/analysis_agent.py +225 -0
  5. agents/cli.py +258 -0
  6. agents/exploit_agent.py +224 -0
  7. agents/integration.py +211 -0
  8. agents/post_scan_agent.py +937 -0
  9. agents/react_agent.py +384 -0
  10. agents/react_agent_enhanced.py +616 -0
  11. agents/react_agent_vm.py +298 -0
  12. agents/research_agent.py +176 -0
  13. api/__init__.py +11 -0
  14. api/auth.py +123 -0
  15. api/main.py +1027 -0
  16. api/schemas.py +357 -0
  17. api/websocket.py +97 -0
  18. autonomous/__init__.py +122 -0
  19. autonomous/agent.py +253 -0
  20. autonomous/agent_loop.py +1370 -0
  21. autonomous/exploit_validator.py +1537 -0
  22. autonomous/memory.py +448 -0
  23. autonomous/react.py +339 -0
  24. autonomous/tool_executor.py +488 -0
  25. backends/__init__.py +16 -0
  26. backends/chatgpt_direct.py +133 -0
  27. backends/claude_direct.py +130 -0
  28. backends/duckduckgo.py +138 -0
  29. backends/openrouter.py +120 -0
  30. benchmarks/__init__.py +149 -0
  31. benchmarks/benchmark_engine.py +904 -0
  32. benchmarks/ci_benchmark.py +785 -0
  33. benchmarks/comparison.py +729 -0
  34. benchmarks/metrics.py +553 -0
  35. benchmarks/run_benchmarks.py +809 -0
  36. ci_cd/__init__.py +2 -0
  37. core/__init__.py +17 -0
  38. core/async_pool.py +282 -0
  39. core/asyncio_fix.py +222 -0
  40. core/cache.py +472 -0
  41. core/container.py +277 -0
  42. core/database.py +114 -0
  43. core/input_validator.py +353 -0
  44. core/models.py +288 -0
  45. core/orchestrator.py +611 -0
  46. core/plugin_manager.py +571 -0
  47. core/rate_limiter.py +405 -0
  48. core/secure_config.py +328 -0
  49. core/shield_integration.py +296 -0
  50. modules/__init__.py +46 -0
  51. modules/cve_database.py +362 -0
  52. modules/exploit_assist.py +330 -0
  53. modules/nuclei_integration.py +480 -0
  54. modules/osint.py +604 -0
  55. modules/protonvpn.py +554 -0
  56. modules/recon.py +165 -0
  57. modules/sql_injection_db.py +826 -0
  58. modules/tool_orchestrator.py +498 -0
  59. modules/vuln_scanner.py +292 -0
  60. modules/wordlist_generator.py +566 -0
  61. risk_engine/__init__.py +99 -0
  62. risk_engine/business_impact.py +267 -0
  63. risk_engine/business_impact_calculator.py +563 -0
  64. risk_engine/cvss.py +156 -0
  65. risk_engine/epss.py +190 -0
  66. risk_engine/example_usage.py +294 -0
  67. risk_engine/false_positive_engine.py +1073 -0
  68. risk_engine/scorer.py +304 -0
  69. web_ui/backend/main.py +471 -0
  70. zen_ai_pentest-2.0.0.dist-info/METADATA +795 -0
  71. zen_ai_pentest-2.0.0.dist-info/RECORD +75 -0
  72. zen_ai_pentest-2.0.0.dist-info/WHEEL +5 -0
  73. zen_ai_pentest-2.0.0.dist-info/entry_points.txt +2 -0
  74. zen_ai_pentest-2.0.0.dist-info/licenses/LICENSE +21 -0
  75. zen_ai_pentest-2.0.0.dist-info/top_level.txt +10 -0
agents/react_agent.py ADDED
@@ -0,0 +1,384 @@
1
+ """
2
+ ReAct Agent Loop für Zen-AI-Pentest
3
+ Implementiert Reasoning-Acting-Observing-Reflecting Pattern mit LangGraph
4
+
5
+ Phase 1: Echter agentischer Loop (2026 Roadmap)
6
+ """
7
+
8
+ from typing import List, TypedDict, Annotated, Literal
9
+ from dataclasses import dataclass
10
+ import json
11
+ import logging
12
+
13
+ from langchain_core.tools import tool, BaseTool
14
+ from langchain_core.messages import BaseMessage, HumanMessage, AIMessage, ToolMessage, SystemMessage
15
+ from langchain_core.prompts import ChatPromptTemplate
16
+ from langchain_core.runnables import RunnableConfig
17
+ from langgraph.graph import StateGraph, START, END, add_messages
18
+ from langgraph.checkpoint.memory import MemorySaver
19
+
20
+ # Zen-AI-Pentest Imports
21
+ from ..core.llm_backend import LLMBackend
22
+ from ..tools.nmap_integration import NmapTool
23
+ from ..tools.nuclei_integration import NucleiTool
24
+ from ..tools.ffuf_integration import FfufTool
25
+ from ..database.cve_database import CVEDatabase
26
+
27
+
28
+ logger = logging.getLogger(__name__)
29
+
30
+
31
+ class AgentState(TypedDict):
32
+ """
33
+ State für den Agent-Loop.
34
+ Persistiert über Iterationen via LangGraph.
35
+ """
36
+ messages: Annotated[List[BaseMessage], add_messages]
37
+ findings: List[dict] # Pentest-Ergebnisse strukturiert
38
+ target: str # Aktuelles Ziel
39
+ iteration: int # Loop-Counter
40
+ max_iterations: int # Safety-Limit
41
+ status: Literal["running", "paused", "completed", "error"]
42
+
43
+
44
+ @dataclass
45
+ class ReActAgentConfig:
46
+ """Konfiguration für den ReAct-Agenten"""
47
+ max_iterations: int = 10
48
+ enable_sandbox: bool = True
49
+ auto_approve_dangerous: bool = False
50
+ use_human_in_the_loop: bool = True
51
+ llm_model: str = "gpt-4o"
52
+
53
+
54
+ class ReActAgent:
55
+ """
56
+ ReAct Agent für autonomes Pentesting.
57
+
58
+ Flow:
59
+ 1. Reason/Plan -> LLM entscheidet nächsten Schritt
60
+ 2. Act -> Führt Tools aus (sandboxed)
61
+ 3. Observe -> Sammelt Ergebnisse
62
+ 4. Reflect -> Bewertet Fortschritt
63
+ 5. Loop oder End
64
+ """
65
+
66
+ def __init__(self, config: ReActAgentConfig = None):
67
+ self.config = config or ReActAgentConfig()
68
+ self.llm = LLMBackend(model=self.config.llm_model)
69
+ self.cve_db = CVEDatabase()
70
+
71
+ # Tools initialisieren
72
+ self.tools = self._initialize_tools()
73
+ self.tools_by_name = {t.name: t for t in self.tools}
74
+
75
+ # LangGraph Workflow
76
+ self.graph = self._build_graph()
77
+
78
+ logger.info(f"ReActAgent initialisiert mit {len(self.tools)} Tools")
79
+
80
+ def _initialize_tools(self) -> List[BaseTool]:
81
+ """Initialisiert Pentest-Tools"""
82
+ tools = []
83
+
84
+ # Port Scanning
85
+ @tool
86
+ def scan_ports(target: str, ports: str = "top-1000") -> str:
87
+ """Scannt Ports auf dem Target mit Nmap"""
88
+ nmap = NmapTool()
89
+ result = nmap.scan(target, ports)
90
+ return json.dumps(result, indent=2)
91
+
92
+ # Vulnerability Scanning
93
+ @tool
94
+ def scan_vulnerabilities(target: str, templates: str = "critical,high") -> str:
95
+ """Scannt nach CVEs mit Nuclei"""
96
+ nuclei = NucleiTool()
97
+ result = nuclei.scan(target, severity=templates)
98
+ return json.dumps(result, indent=2)
99
+
100
+ # Directory Bruteforce
101
+ @tool
102
+ def enumerate_directories(target: str, wordlist: str = "common.txt") -> str:
103
+ """Enumerate directories mit ffuf"""
104
+ ffuf = FfufTool()
105
+ result = ffuf.directory_bruteforce(target, wordlist)
106
+ return json.dumps(result, indent=2)
107
+
108
+ # CVE Lookup
109
+ @tool
110
+ def lookup_cve(cve_id: str) -> str:
111
+ """Sucht CVE-Details in der Datenbank"""
112
+ cve = self.cve_db.get_cve(cve_id)
113
+ if cve:
114
+ return json.dumps({
115
+ "id": cve.id,
116
+ "severity": cve.severity,
117
+ "cvss": cve.cvss_score,
118
+ "description": cve.description,
119
+ "epss": cve.epss_score
120
+ }, indent=2)
121
+ return f"CVE {cve_id} nicht gefunden"
122
+
123
+ # Exploit Validation
124
+ @tool
125
+ def validate_exploit(cve_id: str, target: str) -> str:
126
+ """Validiert ob ein Exploit auf dem Target funktioniert (read-only)"""
127
+ # TODO: Implementiere sichere Validierung
128
+ return f"Exploit-Validierung für {cve_id} auf {target}: Noch nicht implementiert"
129
+
130
+ tools = [scan_ports, scan_vulnerabilities, enumerate_directories,
131
+ lookup_cve, validate_exploit]
132
+ return tools
133
+
134
+ def _build_graph(self) -> StateGraph:
135
+ """Baut den LangGraph Workflow"""
136
+
137
+ # LLM mit Tool-Binding
138
+ llm_with_tools = self.llm.bind_tools(self.tools)
139
+
140
+ # System Prompt
141
+ system_prompt = """Du bist ein autonomer Pentest-Agent für Zen-AI-Pentest.
142
+
143
+ Deine Aufgabe:
144
+ 1. Analysiere das Target und plane den Angriff (Reconnaissance)
145
+ 2. Führe Scans durch (Port, Vulnerability, Directory Enumeration)
146
+ 3. Analysiere Ergebnisse auf Schwachstellen
147
+ 4. Erstelle einen strukturierten Report
148
+
149
+ REGELN:
150
+ - Arbeite Schritt für Schritt (Reasoning)
151
+ - Nutze Tools für externe Aktionen
152
+ - Validiere Ergebnisse (CVSS + EPSS)
153
+ - Never execute destructive exploits without explicit approval
154
+ - Halte max 10 Iterationen ein
155
+
156
+ Wenn du fertig bist, gib eine finale Zusammenfassung aus."""
157
+
158
+ def agent_node(state: AgentState) -> AgentState:
159
+ """Agent Node: Reason/Plan"""
160
+ # Check iteration limit
161
+ if state["iteration"] >= state["max_iterations"]:
162
+ return {
163
+ **state,
164
+ "messages": state["messages"] + [
165
+ AIMessage(content="Maximale Iterationen erreicht. Beende Scan.")
166
+ ],
167
+ "status": "completed"
168
+ }
169
+
170
+ # Prepare messages
171
+ messages = [SystemMessage(content=system_prompt)] + state["messages"]
172
+
173
+ # LLM Call
174
+ response = llm_with_tools.invoke(messages)
175
+
176
+ return {
177
+ **state,
178
+ "messages": [response],
179
+ "iteration": state["iteration"] + 1
180
+ }
181
+
182
+ def tools_node(state: AgentState) -> AgentState:
183
+ """Tools Node: Act/Observe"""
184
+ last_message = state["messages"][-1]
185
+
186
+ if not hasattr(last_message, 'tool_calls') or not last_message.tool_calls:
187
+ return state
188
+
189
+ tool_messages = []
190
+ new_findings = []
191
+
192
+ for tool_call in last_message.tool_calls:
193
+ tool_name = tool_call["name"]
194
+ args = tool_call["args"]
195
+ tool_id = tool_call["id"]
196
+
197
+ logger.info(f"Tool-Aufruf: {tool_name} mit Args: {args}")
198
+
199
+ # Sicherheits-Check
200
+ if self._is_dangerous_tool(tool_name) and self.config.use_human_in_the_loop:
201
+ if not self.config.auto_approve_dangerous:
202
+ result = f"[PENDING APPROVAL] Tool {tool_name} erfordert manuelle Freigabe"
203
+ tool_messages.append(ToolMessage(content=result, tool_call_id=tool_id))
204
+ continue
205
+
206
+ # Tool ausführen
207
+ try:
208
+ tool_func = self.tools_by_name.get(tool_name)
209
+ if tool_func:
210
+ result = tool_func.invoke(args)
211
+
212
+ # Finding speichern
213
+ finding = {
214
+ "tool": tool_name,
215
+ "args": args,
216
+ "result": result,
217
+ "iteration": state["iteration"]
218
+ }
219
+ new_findings.append(finding)
220
+ else:
221
+ result = f"Tool {tool_name} nicht gefunden"
222
+
223
+ tool_messages.append(ToolMessage(content=result, tool_call_id=tool_id))
224
+
225
+ except Exception as e:
226
+ error_msg = f"Fehler bei {tool_name}: {str(e)}"
227
+ logger.error(error_msg)
228
+ tool_messages.append(ToolMessage(content=error_msg, tool_call_id=tool_id))
229
+
230
+ return {
231
+ **state,
232
+ "messages": tool_messages,
233
+ "findings": state["findings"] + new_findings
234
+ }
235
+
236
+ def should_continue(state: AgentState) -> Literal["tools", "agent", "end"]:
237
+ """Conditional Edge: Entscheidet über Loop-Fortsetzung"""
238
+ last_message = state["messages"][-1]
239
+
240
+ # Wenn fertig (keine Tool-Calls mehr)
241
+ if state.get("status") == "completed":
242
+ return "end"
243
+
244
+ # Wenn Tools aufgerufen wurden
245
+ if hasattr(last_message, 'tool_calls') and last_message.tool_calls:
246
+ return "tools"
247
+
248
+ # Wenn Tool-Ergebnisse da sind -> zurück zum Agent
249
+ if isinstance(last_message, ToolMessage):
250
+ return "agent"
251
+
252
+ # Sonst Ende
253
+ return "end"
254
+
255
+ # Graph bauen
256
+ workflow = StateGraph(AgentState)
257
+
258
+ workflow.add_node("agent", agent_node)
259
+ workflow.add_node("tools", tools_node)
260
+
261
+ workflow.add_edge(START, "agent")
262
+
263
+ workflow.add_conditional_edges(
264
+ "agent",
265
+ should_continue,
266
+ {
267
+ "tools": "tools",
268
+ "agent": "agent",
269
+ "end": END
270
+ }
271
+ )
272
+
273
+ workflow.add_conditional_edges(
274
+ "tools",
275
+ should_continue,
276
+ {
277
+ "tools": "tools",
278
+ "agent": "agent",
279
+ "end": END
280
+ }
281
+ )
282
+
283
+ # Mit Memory für Human-in-the-Loop
284
+ checkpointer = MemorySaver()
285
+ return workflow.compile(checkpointer=checkpointer)
286
+
287
+ def _is_dangerous_tool(self, tool_name: str) -> bool:
288
+ """Prüft ob ein Tool als gefährlich eingestuft wird"""
289
+ dangerous = ["validate_exploit", "exploit", "sqlmap_exploit"]
290
+ return any(d in tool_name.lower() for d in dangerous)
291
+
292
+ def run(self, target: str, objective: str = "comprehensive scan") -> dict:
293
+ """
294
+ Führt den Agent-Loop aus.
295
+
296
+ Args:
297
+ target: Ziel-URL/IP
298
+ objective: Scan-Ziel (z.B. "port scan", "vulnerability assessment")
299
+
300
+ Returns:
301
+ dict mit findings, messages, status
302
+ """
303
+ initial_state: AgentState = {
304
+ "messages": [HumanMessage(content=f"{objective} on {target}")],
305
+ "findings": [],
306
+ "target": target,
307
+ "iteration": 0,
308
+ "max_iterations": self.config.max_iterations,
309
+ "status": "running"
310
+ }
311
+
312
+ logger.info(f"Starte ReAct-Agent für {target}")
313
+
314
+ # Graph ausführen
315
+ result = self.graph.invoke(
316
+ initial_state,
317
+ config={"configurable": {"thread_id": f"pentest_{target}"}}
318
+ )
319
+
320
+ logger.info(f"Agent beendet nach {result['iteration']} Iterationen")
321
+
322
+ return {
323
+ "findings": result["findings"],
324
+ "final_message": result["messages"][-1].content if result["messages"] else "",
325
+ "iterations": result["iteration"],
326
+ "status": result["status"],
327
+ "target": target
328
+ }
329
+
330
+ def generate_report(self, result: dict) -> str:
331
+ """Generiert einen strukturierten Report aus den Findings"""
332
+ report = []
333
+ report.append("=" * 70)
334
+ report.append("ZEN-AI-PENTEST REPORT")
335
+ report.append("=" * 70)
336
+ report.append(f"\nTarget: {result['target']}")
337
+ report.append(f"Status: {result['status']}")
338
+ report.append(f"Iterations: {result['iterations']}")
339
+ report.append("")
340
+
341
+ if result['findings']:
342
+ report.append("FINDINGS:")
343
+ report.append("-" * 70)
344
+ for i, finding in enumerate(result['findings'], 1):
345
+ report.append(f"\n{i}. {finding['tool']}")
346
+ report.append(f" Args: {finding['args']}")
347
+ report.append(f" Result: {finding['result'][:200]}...")
348
+ else:
349
+ report.append("No findings detected.")
350
+
351
+ report.append("")
352
+ report.append("=" * 70)
353
+ report.append("FINAL ANALYSIS:")
354
+ report.append("=" * 70)
355
+ report.append(result['final_message'])
356
+
357
+ return "\n".join(report)
358
+
359
+
360
+ # Singleton-Instanz für einfachen Zugriff
361
+ _default_agent = None
362
+
363
+ def get_agent(config: ReActAgentConfig = None) -> ReActAgent:
364
+ """Gibt die default Agent-Instanz zurück"""
365
+ global _default_agent
366
+ if _default_agent is None or config is not None:
367
+ _default_agent = ReActAgent(config)
368
+ return _default_agent
369
+
370
+
371
+ if __name__ == "__main__":
372
+ # Test
373
+ logging.basicConfig(level=logging.INFO)
374
+
375
+ config = ReActAgentConfig(
376
+ max_iterations=5,
377
+ enable_sandbox=True,
378
+ auto_approve_dangerous=False
379
+ )
380
+
381
+ agent = ReActAgent(config)
382
+ result = agent.run("scanme.nmap.org", objective="Port scan and vulnerability assessment")
383
+
384
+ print(agent.generate_report(result))