aiptx 2.0.7__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 (187) hide show
  1. aipt_v2/__init__.py +110 -0
  2. aipt_v2/__main__.py +24 -0
  3. aipt_v2/agents/AIPTxAgent/__init__.py +10 -0
  4. aipt_v2/agents/AIPTxAgent/aiptx_agent.py +211 -0
  5. aipt_v2/agents/__init__.py +46 -0
  6. aipt_v2/agents/base.py +520 -0
  7. aipt_v2/agents/exploit_agent.py +688 -0
  8. aipt_v2/agents/ptt.py +406 -0
  9. aipt_v2/agents/state.py +168 -0
  10. aipt_v2/app.py +957 -0
  11. aipt_v2/browser/__init__.py +31 -0
  12. aipt_v2/browser/automation.py +458 -0
  13. aipt_v2/browser/crawler.py +453 -0
  14. aipt_v2/cli.py +2933 -0
  15. aipt_v2/compliance/__init__.py +71 -0
  16. aipt_v2/compliance/compliance_report.py +449 -0
  17. aipt_v2/compliance/framework_mapper.py +424 -0
  18. aipt_v2/compliance/nist_mapping.py +345 -0
  19. aipt_v2/compliance/owasp_mapping.py +330 -0
  20. aipt_v2/compliance/pci_mapping.py +297 -0
  21. aipt_v2/config.py +341 -0
  22. aipt_v2/core/__init__.py +43 -0
  23. aipt_v2/core/agent.py +630 -0
  24. aipt_v2/core/llm.py +395 -0
  25. aipt_v2/core/memory.py +305 -0
  26. aipt_v2/core/ptt.py +329 -0
  27. aipt_v2/database/__init__.py +14 -0
  28. aipt_v2/database/models.py +232 -0
  29. aipt_v2/database/repository.py +384 -0
  30. aipt_v2/docker/__init__.py +23 -0
  31. aipt_v2/docker/builder.py +260 -0
  32. aipt_v2/docker/manager.py +222 -0
  33. aipt_v2/docker/sandbox.py +371 -0
  34. aipt_v2/evasion/__init__.py +58 -0
  35. aipt_v2/evasion/request_obfuscator.py +272 -0
  36. aipt_v2/evasion/tls_fingerprint.py +285 -0
  37. aipt_v2/evasion/ua_rotator.py +301 -0
  38. aipt_v2/evasion/waf_bypass.py +439 -0
  39. aipt_v2/execution/__init__.py +23 -0
  40. aipt_v2/execution/executor.py +302 -0
  41. aipt_v2/execution/parser.py +544 -0
  42. aipt_v2/execution/terminal.py +337 -0
  43. aipt_v2/health.py +437 -0
  44. aipt_v2/intelligence/__init__.py +194 -0
  45. aipt_v2/intelligence/adaptation.py +474 -0
  46. aipt_v2/intelligence/auth.py +520 -0
  47. aipt_v2/intelligence/chaining.py +775 -0
  48. aipt_v2/intelligence/correlation.py +536 -0
  49. aipt_v2/intelligence/cve_aipt.py +334 -0
  50. aipt_v2/intelligence/cve_info.py +1111 -0
  51. aipt_v2/intelligence/knowledge_graph.py +590 -0
  52. aipt_v2/intelligence/learning.py +626 -0
  53. aipt_v2/intelligence/llm_analyzer.py +502 -0
  54. aipt_v2/intelligence/llm_tool_selector.py +518 -0
  55. aipt_v2/intelligence/payload_generator.py +562 -0
  56. aipt_v2/intelligence/rag.py +239 -0
  57. aipt_v2/intelligence/scope.py +442 -0
  58. aipt_v2/intelligence/searchers/__init__.py +5 -0
  59. aipt_v2/intelligence/searchers/exploitdb_searcher.py +523 -0
  60. aipt_v2/intelligence/searchers/github_searcher.py +467 -0
  61. aipt_v2/intelligence/searchers/google_searcher.py +281 -0
  62. aipt_v2/intelligence/tools.json +443 -0
  63. aipt_v2/intelligence/triage.py +670 -0
  64. aipt_v2/interactive_shell.py +559 -0
  65. aipt_v2/interface/__init__.py +5 -0
  66. aipt_v2/interface/cli.py +230 -0
  67. aipt_v2/interface/main.py +501 -0
  68. aipt_v2/interface/tui.py +1276 -0
  69. aipt_v2/interface/utils.py +583 -0
  70. aipt_v2/llm/__init__.py +39 -0
  71. aipt_v2/llm/config.py +26 -0
  72. aipt_v2/llm/llm.py +514 -0
  73. aipt_v2/llm/memory.py +214 -0
  74. aipt_v2/llm/request_queue.py +89 -0
  75. aipt_v2/llm/utils.py +89 -0
  76. aipt_v2/local_tool_installer.py +1467 -0
  77. aipt_v2/models/__init__.py +15 -0
  78. aipt_v2/models/findings.py +295 -0
  79. aipt_v2/models/phase_result.py +224 -0
  80. aipt_v2/models/scan_config.py +207 -0
  81. aipt_v2/monitoring/grafana/dashboards/aipt-dashboard.json +355 -0
  82. aipt_v2/monitoring/grafana/dashboards/default.yml +17 -0
  83. aipt_v2/monitoring/grafana/datasources/prometheus.yml +17 -0
  84. aipt_v2/monitoring/prometheus.yml +60 -0
  85. aipt_v2/orchestration/__init__.py +52 -0
  86. aipt_v2/orchestration/pipeline.py +398 -0
  87. aipt_v2/orchestration/progress.py +300 -0
  88. aipt_v2/orchestration/scheduler.py +296 -0
  89. aipt_v2/orchestrator.py +2427 -0
  90. aipt_v2/payloads/__init__.py +27 -0
  91. aipt_v2/payloads/cmdi.py +150 -0
  92. aipt_v2/payloads/sqli.py +263 -0
  93. aipt_v2/payloads/ssrf.py +204 -0
  94. aipt_v2/payloads/templates.py +222 -0
  95. aipt_v2/payloads/traversal.py +166 -0
  96. aipt_v2/payloads/xss.py +204 -0
  97. aipt_v2/prompts/__init__.py +60 -0
  98. aipt_v2/proxy/__init__.py +29 -0
  99. aipt_v2/proxy/history.py +352 -0
  100. aipt_v2/proxy/interceptor.py +452 -0
  101. aipt_v2/recon/__init__.py +44 -0
  102. aipt_v2/recon/dns.py +241 -0
  103. aipt_v2/recon/osint.py +367 -0
  104. aipt_v2/recon/subdomain.py +372 -0
  105. aipt_v2/recon/tech_detect.py +311 -0
  106. aipt_v2/reports/__init__.py +17 -0
  107. aipt_v2/reports/generator.py +313 -0
  108. aipt_v2/reports/html_report.py +378 -0
  109. aipt_v2/runtime/__init__.py +53 -0
  110. aipt_v2/runtime/base.py +30 -0
  111. aipt_v2/runtime/docker.py +401 -0
  112. aipt_v2/runtime/local.py +346 -0
  113. aipt_v2/runtime/tool_server.py +205 -0
  114. aipt_v2/runtime/vps.py +830 -0
  115. aipt_v2/scanners/__init__.py +28 -0
  116. aipt_v2/scanners/base.py +273 -0
  117. aipt_v2/scanners/nikto.py +244 -0
  118. aipt_v2/scanners/nmap.py +402 -0
  119. aipt_v2/scanners/nuclei.py +273 -0
  120. aipt_v2/scanners/web.py +454 -0
  121. aipt_v2/scripts/security_audit.py +366 -0
  122. aipt_v2/setup_wizard.py +941 -0
  123. aipt_v2/skills/__init__.py +80 -0
  124. aipt_v2/skills/agents/__init__.py +14 -0
  125. aipt_v2/skills/agents/api_tester.py +706 -0
  126. aipt_v2/skills/agents/base.py +477 -0
  127. aipt_v2/skills/agents/code_review.py +459 -0
  128. aipt_v2/skills/agents/security_agent.py +336 -0
  129. aipt_v2/skills/agents/web_pentest.py +818 -0
  130. aipt_v2/skills/prompts/__init__.py +647 -0
  131. aipt_v2/system_detector.py +539 -0
  132. aipt_v2/telemetry/__init__.py +7 -0
  133. aipt_v2/telemetry/tracer.py +347 -0
  134. aipt_v2/terminal/__init__.py +28 -0
  135. aipt_v2/terminal/executor.py +400 -0
  136. aipt_v2/terminal/sandbox.py +350 -0
  137. aipt_v2/tools/__init__.py +44 -0
  138. aipt_v2/tools/active_directory/__init__.py +78 -0
  139. aipt_v2/tools/active_directory/ad_config.py +238 -0
  140. aipt_v2/tools/active_directory/bloodhound_wrapper.py +447 -0
  141. aipt_v2/tools/active_directory/kerberos_attacks.py +430 -0
  142. aipt_v2/tools/active_directory/ldap_enum.py +533 -0
  143. aipt_v2/tools/active_directory/smb_attacks.py +505 -0
  144. aipt_v2/tools/agents_graph/__init__.py +19 -0
  145. aipt_v2/tools/agents_graph/agents_graph_actions.py +69 -0
  146. aipt_v2/tools/api_security/__init__.py +76 -0
  147. aipt_v2/tools/api_security/api_discovery.py +608 -0
  148. aipt_v2/tools/api_security/graphql_scanner.py +622 -0
  149. aipt_v2/tools/api_security/jwt_analyzer.py +577 -0
  150. aipt_v2/tools/api_security/openapi_fuzzer.py +761 -0
  151. aipt_v2/tools/browser/__init__.py +5 -0
  152. aipt_v2/tools/browser/browser_actions.py +238 -0
  153. aipt_v2/tools/browser/browser_instance.py +535 -0
  154. aipt_v2/tools/browser/tab_manager.py +344 -0
  155. aipt_v2/tools/cloud/__init__.py +70 -0
  156. aipt_v2/tools/cloud/cloud_config.py +273 -0
  157. aipt_v2/tools/cloud/cloud_scanner.py +639 -0
  158. aipt_v2/tools/cloud/prowler_tool.py +571 -0
  159. aipt_v2/tools/cloud/scoutsuite_tool.py +359 -0
  160. aipt_v2/tools/executor.py +307 -0
  161. aipt_v2/tools/parser.py +408 -0
  162. aipt_v2/tools/proxy/__init__.py +5 -0
  163. aipt_v2/tools/proxy/proxy_actions.py +103 -0
  164. aipt_v2/tools/proxy/proxy_manager.py +789 -0
  165. aipt_v2/tools/registry.py +196 -0
  166. aipt_v2/tools/scanners/__init__.py +343 -0
  167. aipt_v2/tools/scanners/acunetix_tool.py +712 -0
  168. aipt_v2/tools/scanners/burp_tool.py +631 -0
  169. aipt_v2/tools/scanners/config.py +156 -0
  170. aipt_v2/tools/scanners/nessus_tool.py +588 -0
  171. aipt_v2/tools/scanners/zap_tool.py +612 -0
  172. aipt_v2/tools/terminal/__init__.py +5 -0
  173. aipt_v2/tools/terminal/terminal_actions.py +37 -0
  174. aipt_v2/tools/terminal/terminal_manager.py +153 -0
  175. aipt_v2/tools/terminal/terminal_session.py +449 -0
  176. aipt_v2/tools/tool_processing.py +108 -0
  177. aipt_v2/utils/__init__.py +17 -0
  178. aipt_v2/utils/logging.py +202 -0
  179. aipt_v2/utils/model_manager.py +187 -0
  180. aipt_v2/utils/searchers/__init__.py +269 -0
  181. aipt_v2/verify_install.py +793 -0
  182. aiptx-2.0.7.dist-info/METADATA +345 -0
  183. aiptx-2.0.7.dist-info/RECORD +187 -0
  184. aiptx-2.0.7.dist-info/WHEEL +5 -0
  185. aiptx-2.0.7.dist-info/entry_points.txt +7 -0
  186. aiptx-2.0.7.dist-info/licenses/LICENSE +21 -0
  187. aiptx-2.0.7.dist-info/top_level.txt +1 -0
@@ -0,0 +1,626 @@
1
+ """
2
+ AIPT Feedback Learning System
3
+
4
+ Learns from exploitation attempts to improve future scans:
5
+ - Records successful/failed exploitation attempts
6
+ - Builds knowledge of what works for specific contexts
7
+ - Suggests optimal payloads based on historical success
8
+ - Tracks WAF bypass techniques that work
9
+
10
+ This creates a feedback loop that makes AIPT smarter over time.
11
+ """
12
+ from __future__ import annotations
13
+
14
+ import json
15
+ import logging
16
+ import sqlite3
17
+ from dataclasses import dataclass, field
18
+ from datetime import datetime
19
+ from pathlib import Path
20
+ from typing import Any, Optional
21
+
22
+ from aipt_v2.models.findings import VulnerabilityType
23
+
24
+ logger = logging.getLogger(__name__)
25
+
26
+
27
+ @dataclass
28
+ class ExploitAttempt:
29
+ """Record of an exploitation attempt."""
30
+ vuln_type: str
31
+ target_url: str
32
+ payload: str
33
+ success: bool
34
+ tech_stack: Optional[str] = None
35
+ waf: Optional[str] = None
36
+ response_code: Optional[int] = None
37
+ response_time_ms: Optional[int] = None
38
+ error_message: Optional[str] = None
39
+ notes: Optional[str] = None
40
+ timestamp: datetime = field(default_factory=datetime.utcnow)
41
+
42
+ def to_dict(self) -> dict[str, Any]:
43
+ return {
44
+ "vuln_type": self.vuln_type,
45
+ "target_url": self.target_url,
46
+ "payload": self.payload,
47
+ "success": self.success,
48
+ "tech_stack": self.tech_stack,
49
+ "waf": self.waf,
50
+ "response_code": self.response_code,
51
+ "response_time_ms": self.response_time_ms,
52
+ "error_message": self.error_message,
53
+ "notes": self.notes,
54
+ "timestamp": self.timestamp.isoformat(),
55
+ }
56
+
57
+
58
+ @dataclass
59
+ class PayloadSuggestion:
60
+ """A suggested payload based on historical success."""
61
+ payload: str
62
+ success_count: int
63
+ total_attempts: int
64
+ success_rate: float
65
+ avg_response_time_ms: Optional[float] = None
66
+ common_waf: Optional[str] = None
67
+ common_tech: Optional[str] = None
68
+
69
+ @property
70
+ def confidence(self) -> float:
71
+ """Calculate confidence score."""
72
+ # Higher success rate and more attempts = higher confidence
73
+ sample_bonus = min(self.total_attempts / 10, 1.0) # Max bonus at 10 attempts
74
+ return self.success_rate * (0.5 + 0.5 * sample_bonus)
75
+
76
+
77
+ @dataclass
78
+ class TechniqueStats:
79
+ """Statistics for a vulnerability type."""
80
+ vuln_type: str
81
+ total_attempts: int
82
+ successful_attempts: int
83
+ success_rate: float
84
+ best_payload: Optional[str] = None
85
+ best_payload_success_rate: Optional[float] = None
86
+ common_waf_bypasses: list[str] = field(default_factory=list)
87
+
88
+
89
+ class ExploitationLearner:
90
+ """
91
+ Learns from exploitation attempts to improve future scans.
92
+
93
+ Maintains a SQLite database of exploitation attempts and their outcomes,
94
+ allowing AIPT to learn which techniques work best in different contexts.
95
+
96
+ Example:
97
+ learner = ExploitationLearner()
98
+
99
+ # Record an attempt
100
+ learner.record_attempt(ExploitAttempt(
101
+ vuln_type="sql_injection",
102
+ target_url="https://example.com/login",
103
+ payload="' OR '1'='1",
104
+ success=True,
105
+ waf="cloudflare",
106
+ tech_stack="php/mysql"
107
+ ))
108
+
109
+ # Get suggestions for future attempts
110
+ suggestions = learner.get_payload_suggestions(
111
+ vuln_type="sql_injection",
112
+ waf="cloudflare"
113
+ )
114
+ """
115
+
116
+ def __init__(self, db_path: str = None):
117
+ if db_path is None:
118
+ # Default to ~/.aiptx/learning.db
119
+ aiptx_dir = Path.home() / ".aiptx"
120
+ aiptx_dir.mkdir(parents=True, exist_ok=True)
121
+ db_path = str(aiptx_dir / "learning.db")
122
+
123
+ self.db_path = db_path
124
+ self._init_database()
125
+
126
+ def _init_database(self):
127
+ """Initialize the SQLite database schema."""
128
+ conn = sqlite3.connect(self.db_path)
129
+ cursor = conn.cursor()
130
+
131
+ # Exploitation attempts table
132
+ cursor.execute("""
133
+ CREATE TABLE IF NOT EXISTS exploit_attempts (
134
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
135
+ vuln_type TEXT NOT NULL,
136
+ target_url TEXT NOT NULL,
137
+ payload TEXT NOT NULL,
138
+ success INTEGER NOT NULL,
139
+ tech_stack TEXT,
140
+ waf TEXT,
141
+ response_code INTEGER,
142
+ response_time_ms INTEGER,
143
+ error_message TEXT,
144
+ notes TEXT,
145
+ timestamp TEXT NOT NULL,
146
+ created_at TEXT DEFAULT CURRENT_TIMESTAMP
147
+ )
148
+ """)
149
+
150
+ # Index for faster queries
151
+ cursor.execute("""
152
+ CREATE INDEX IF NOT EXISTS idx_vuln_type ON exploit_attempts(vuln_type)
153
+ """)
154
+ cursor.execute("""
155
+ CREATE INDEX IF NOT EXISTS idx_success ON exploit_attempts(success)
156
+ """)
157
+ cursor.execute("""
158
+ CREATE INDEX IF NOT EXISTS idx_waf ON exploit_attempts(waf)
159
+ """)
160
+
161
+ # WAF bypass techniques table
162
+ cursor.execute("""
163
+ CREATE TABLE IF NOT EXISTS waf_bypasses (
164
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
165
+ waf_name TEXT NOT NULL,
166
+ vuln_type TEXT NOT NULL,
167
+ original_payload TEXT NOT NULL,
168
+ bypass_payload TEXT NOT NULL,
169
+ success INTEGER NOT NULL,
170
+ notes TEXT,
171
+ created_at TEXT DEFAULT CURRENT_TIMESTAMP
172
+ )
173
+ """)
174
+
175
+ # Payload effectiveness table (aggregated stats)
176
+ cursor.execute("""
177
+ CREATE TABLE IF NOT EXISTS payload_stats (
178
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
179
+ vuln_type TEXT NOT NULL,
180
+ payload_hash TEXT NOT NULL,
181
+ payload TEXT NOT NULL,
182
+ success_count INTEGER DEFAULT 0,
183
+ failure_count INTEGER DEFAULT 0,
184
+ avg_response_time_ms REAL,
185
+ last_success TEXT,
186
+ last_failure TEXT,
187
+ UNIQUE(vuln_type, payload_hash)
188
+ )
189
+ """)
190
+
191
+ conn.commit()
192
+ conn.close()
193
+
194
+ def record_attempt(self, attempt: ExploitAttempt):
195
+ """
196
+ Record an exploitation attempt.
197
+
198
+ Args:
199
+ attempt: The exploitation attempt to record
200
+ """
201
+ conn = sqlite3.connect(self.db_path)
202
+ cursor = conn.cursor()
203
+
204
+ # Insert attempt
205
+ cursor.execute("""
206
+ INSERT INTO exploit_attempts
207
+ (vuln_type, target_url, payload, success, tech_stack, waf,
208
+ response_code, response_time_ms, error_message, notes, timestamp)
209
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
210
+ """, (
211
+ attempt.vuln_type,
212
+ attempt.target_url,
213
+ attempt.payload,
214
+ 1 if attempt.success else 0,
215
+ attempt.tech_stack,
216
+ attempt.waf,
217
+ attempt.response_code,
218
+ attempt.response_time_ms,
219
+ attempt.error_message,
220
+ attempt.notes,
221
+ attempt.timestamp.isoformat(),
222
+ ))
223
+
224
+ # Update payload stats
225
+ payload_hash = self._hash_payload(attempt.payload)
226
+ if attempt.success:
227
+ cursor.execute("""
228
+ INSERT INTO payload_stats (vuln_type, payload_hash, payload, success_count, last_success)
229
+ VALUES (?, ?, ?, 1, ?)
230
+ ON CONFLICT(vuln_type, payload_hash) DO UPDATE SET
231
+ success_count = success_count + 1,
232
+ last_success = ?
233
+ """, (attempt.vuln_type, payload_hash, attempt.payload,
234
+ attempt.timestamp.isoformat(), attempt.timestamp.isoformat()))
235
+ else:
236
+ cursor.execute("""
237
+ INSERT INTO payload_stats (vuln_type, payload_hash, payload, failure_count, last_failure)
238
+ VALUES (?, ?, ?, 1, ?)
239
+ ON CONFLICT(vuln_type, payload_hash) DO UPDATE SET
240
+ failure_count = failure_count + 1,
241
+ last_failure = ?
242
+ """, (attempt.vuln_type, payload_hash, attempt.payload,
243
+ attempt.timestamp.isoformat(), attempt.timestamp.isoformat()))
244
+
245
+ conn.commit()
246
+ conn.close()
247
+
248
+ logger.debug(f"Recorded {'successful' if attempt.success else 'failed'} "
249
+ f"attempt for {attempt.vuln_type}")
250
+
251
+ def record_waf_bypass(
252
+ self,
253
+ waf_name: str,
254
+ vuln_type: str,
255
+ original_payload: str,
256
+ bypass_payload: str,
257
+ success: bool,
258
+ notes: str = "",
259
+ ):
260
+ """
261
+ Record a WAF bypass technique.
262
+
263
+ Args:
264
+ waf_name: Name of the WAF (e.g., "cloudflare", "akamai")
265
+ vuln_type: Type of vulnerability being exploited
266
+ original_payload: The blocked payload
267
+ bypass_payload: The modified payload that bypassed the WAF
268
+ success: Whether the bypass was successful
269
+ notes: Additional notes
270
+ """
271
+ conn = sqlite3.connect(self.db_path)
272
+ cursor = conn.cursor()
273
+
274
+ cursor.execute("""
275
+ INSERT INTO waf_bypasses
276
+ (waf_name, vuln_type, original_payload, bypass_payload, success, notes)
277
+ VALUES (?, ?, ?, ?, ?, ?)
278
+ """, (waf_name, vuln_type, original_payload, bypass_payload,
279
+ 1 if success else 0, notes))
280
+
281
+ conn.commit()
282
+ conn.close()
283
+
284
+ logger.info(f"Recorded WAF bypass for {waf_name}: {'success' if success else 'failure'}")
285
+
286
+ def get_payload_suggestions(
287
+ self,
288
+ vuln_type: str,
289
+ waf: str = None,
290
+ tech_stack: str = None,
291
+ limit: int = 10,
292
+ ) -> list[PayloadSuggestion]:
293
+ """
294
+ Get payload suggestions based on historical success.
295
+
296
+ Args:
297
+ vuln_type: Type of vulnerability (e.g., "sql_injection")
298
+ waf: Optional WAF name to filter for
299
+ tech_stack: Optional tech stack to filter for
300
+ limit: Maximum number of suggestions
301
+
302
+ Returns:
303
+ List of PayloadSuggestion objects ordered by success rate
304
+ """
305
+ conn = sqlite3.connect(self.db_path)
306
+ cursor = conn.cursor()
307
+
308
+ # Build query based on filters
309
+ query = """
310
+ SELECT
311
+ payload,
312
+ SUM(CASE WHEN success = 1 THEN 1 ELSE 0 END) as success_count,
313
+ COUNT(*) as total_attempts,
314
+ AVG(CASE WHEN success = 1 THEN response_time_ms ELSE NULL END) as avg_time,
315
+ waf,
316
+ tech_stack
317
+ FROM exploit_attempts
318
+ WHERE vuln_type = ?
319
+ """
320
+ params = [vuln_type]
321
+
322
+ if waf:
323
+ query += " AND (waf = ? OR waf IS NULL)"
324
+ params.append(waf)
325
+
326
+ if tech_stack:
327
+ query += " AND (tech_stack LIKE ? OR tech_stack IS NULL)"
328
+ params.append(f"%{tech_stack}%")
329
+
330
+ query += """
331
+ GROUP BY payload
332
+ HAVING total_attempts >= 1
333
+ ORDER BY (CAST(success_count AS FLOAT) / total_attempts) DESC,
334
+ success_count DESC
335
+ LIMIT ?
336
+ """
337
+ params.append(limit)
338
+
339
+ cursor.execute(query, params)
340
+ rows = cursor.fetchall()
341
+ conn.close()
342
+
343
+ suggestions = []
344
+ for row in rows:
345
+ payload, success_count, total, avg_time, common_waf, common_tech = row
346
+ suggestions.append(PayloadSuggestion(
347
+ payload=payload,
348
+ success_count=success_count,
349
+ total_attempts=total,
350
+ success_rate=success_count / total if total > 0 else 0,
351
+ avg_response_time_ms=avg_time,
352
+ common_waf=common_waf,
353
+ common_tech=common_tech,
354
+ ))
355
+
356
+ return suggestions
357
+
358
+ def get_waf_bypass_payloads(
359
+ self,
360
+ waf_name: str,
361
+ vuln_type: str = None,
362
+ limit: int = 10,
363
+ ) -> list[dict[str, Any]]:
364
+ """
365
+ Get successful WAF bypass payloads.
366
+
367
+ Args:
368
+ waf_name: Name of the WAF
369
+ vuln_type: Optional vulnerability type filter
370
+ limit: Maximum results
371
+
372
+ Returns:
373
+ List of bypass payload dictionaries
374
+ """
375
+ conn = sqlite3.connect(self.db_path)
376
+ cursor = conn.cursor()
377
+
378
+ query = """
379
+ SELECT vuln_type, original_payload, bypass_payload, notes
380
+ FROM waf_bypasses
381
+ WHERE waf_name = ? AND success = 1
382
+ """
383
+ params = [waf_name]
384
+
385
+ if vuln_type:
386
+ query += " AND vuln_type = ?"
387
+ params.append(vuln_type)
388
+
389
+ query += " ORDER BY created_at DESC LIMIT ?"
390
+ params.append(limit)
391
+
392
+ cursor.execute(query, params)
393
+ rows = cursor.fetchall()
394
+ conn.close()
395
+
396
+ return [
397
+ {
398
+ "vuln_type": row[0],
399
+ "original_payload": row[1],
400
+ "bypass_payload": row[2],
401
+ "notes": row[3],
402
+ }
403
+ for row in rows
404
+ ]
405
+
406
+ def get_technique_stats(self, vuln_type: str) -> TechniqueStats:
407
+ """
408
+ Get statistics for a vulnerability type.
409
+
410
+ Args:
411
+ vuln_type: The vulnerability type to analyze
412
+
413
+ Returns:
414
+ TechniqueStats with aggregated information
415
+ """
416
+ conn = sqlite3.connect(self.db_path)
417
+ cursor = conn.cursor()
418
+
419
+ # Get overall stats
420
+ cursor.execute("""
421
+ SELECT
422
+ COUNT(*) as total,
423
+ SUM(CASE WHEN success = 1 THEN 1 ELSE 0 END) as successes
424
+ FROM exploit_attempts
425
+ WHERE vuln_type = ?
426
+ """, (vuln_type,))
427
+ total, successes = cursor.fetchone()
428
+ total = total or 0
429
+ successes = successes or 0
430
+
431
+ # Get best payload
432
+ cursor.execute("""
433
+ SELECT payload,
434
+ CAST(SUM(CASE WHEN success = 1 THEN 1 ELSE 0 END) AS FLOAT) / COUNT(*) as rate
435
+ FROM exploit_attempts
436
+ WHERE vuln_type = ?
437
+ GROUP BY payload
438
+ HAVING COUNT(*) >= 3
439
+ ORDER BY rate DESC
440
+ LIMIT 1
441
+ """, (vuln_type,))
442
+ best_row = cursor.fetchone()
443
+
444
+ # Get common WAF bypasses
445
+ cursor.execute("""
446
+ SELECT DISTINCT waf
447
+ FROM exploit_attempts
448
+ WHERE vuln_type = ? AND waf IS NOT NULL AND success = 1
449
+ LIMIT 5
450
+ """, (vuln_type,))
451
+ waf_rows = cursor.fetchall()
452
+
453
+ conn.close()
454
+
455
+ return TechniqueStats(
456
+ vuln_type=vuln_type,
457
+ total_attempts=total,
458
+ successful_attempts=successes,
459
+ success_rate=successes / total if total > 0 else 0,
460
+ best_payload=best_row[0] if best_row else None,
461
+ best_payload_success_rate=best_row[1] if best_row else None,
462
+ common_waf_bypasses=[row[0] for row in waf_rows],
463
+ )
464
+
465
+ def get_success_rate(
466
+ self,
467
+ vuln_type: str,
468
+ tech_stack: str = None,
469
+ waf: str = None,
470
+ ) -> float:
471
+ """
472
+ Get historical success rate for a vulnerability type.
473
+
474
+ Args:
475
+ vuln_type: Vulnerability type
476
+ tech_stack: Optional tech stack filter
477
+ waf: Optional WAF filter
478
+
479
+ Returns:
480
+ Success rate as a float (0.0 to 1.0)
481
+ """
482
+ conn = sqlite3.connect(self.db_path)
483
+ cursor = conn.cursor()
484
+
485
+ query = """
486
+ SELECT
487
+ SUM(CASE WHEN success = 1 THEN 1 ELSE 0 END) as successes,
488
+ COUNT(*) as total
489
+ FROM exploit_attempts
490
+ WHERE vuln_type = ?
491
+ """
492
+ params = [vuln_type]
493
+
494
+ if tech_stack:
495
+ query += " AND tech_stack LIKE ?"
496
+ params.append(f"%{tech_stack}%")
497
+
498
+ if waf:
499
+ query += " AND waf = ?"
500
+ params.append(waf)
501
+
502
+ cursor.execute(query, params)
503
+ successes, total = cursor.fetchone()
504
+ conn.close()
505
+
506
+ if total and total > 0:
507
+ return successes / total
508
+ return 0.0
509
+
510
+ def export_knowledge(self, output_path: str):
511
+ """
512
+ Export learned knowledge to JSON file.
513
+
514
+ Args:
515
+ output_path: Path to write JSON export
516
+ """
517
+ conn = sqlite3.connect(self.db_path)
518
+ cursor = conn.cursor()
519
+
520
+ # Get all payload stats
521
+ cursor.execute("""
522
+ SELECT vuln_type, payload, success_count, failure_count
523
+ FROM payload_stats
524
+ ORDER BY vuln_type, (success_count * 1.0 / (success_count + failure_count + 1)) DESC
525
+ """)
526
+ payload_rows = cursor.fetchall()
527
+
528
+ # Get all WAF bypasses
529
+ cursor.execute("""
530
+ SELECT waf_name, vuln_type, original_payload, bypass_payload, success
531
+ FROM waf_bypasses
532
+ WHERE success = 1
533
+ """)
534
+ bypass_rows = cursor.fetchall()
535
+
536
+ conn.close()
537
+
538
+ export_data = {
539
+ "exported_at": datetime.utcnow().isoformat(),
540
+ "payload_knowledge": [
541
+ {
542
+ "vuln_type": row[0],
543
+ "payload": row[1],
544
+ "success_count": row[2],
545
+ "failure_count": row[3],
546
+ "success_rate": row[2] / (row[2] + row[3]) if (row[2] + row[3]) > 0 else 0,
547
+ }
548
+ for row in payload_rows
549
+ ],
550
+ "waf_bypasses": [
551
+ {
552
+ "waf": row[0],
553
+ "vuln_type": row[1],
554
+ "original": row[2],
555
+ "bypass": row[3],
556
+ }
557
+ for row in bypass_rows
558
+ ],
559
+ }
560
+
561
+ with open(output_path, "w") as f:
562
+ json.dump(export_data, f, indent=2)
563
+
564
+ logger.info(f"Exported knowledge to {output_path}")
565
+
566
+ def import_knowledge(self, input_path: str):
567
+ """
568
+ Import knowledge from JSON file.
569
+
570
+ Args:
571
+ input_path: Path to JSON file to import
572
+ """
573
+ with open(input_path, "r") as f:
574
+ data = json.load(f)
575
+
576
+ conn = sqlite3.connect(self.db_path)
577
+ cursor = conn.cursor()
578
+
579
+ # Import payload knowledge
580
+ for payload_data in data.get("payload_knowledge", []):
581
+ payload_hash = self._hash_payload(payload_data["payload"])
582
+ cursor.execute("""
583
+ INSERT OR REPLACE INTO payload_stats
584
+ (vuln_type, payload_hash, payload, success_count, failure_count)
585
+ VALUES (?, ?, ?, ?, ?)
586
+ """, (
587
+ payload_data["vuln_type"],
588
+ payload_hash,
589
+ payload_data["payload"],
590
+ payload_data["success_count"],
591
+ payload_data["failure_count"],
592
+ ))
593
+
594
+ # Import WAF bypasses
595
+ for bypass in data.get("waf_bypasses", []):
596
+ cursor.execute("""
597
+ INSERT INTO waf_bypasses
598
+ (waf_name, vuln_type, original_payload, bypass_payload, success)
599
+ VALUES (?, ?, ?, ?, 1)
600
+ """, (
601
+ bypass["waf"],
602
+ bypass["vuln_type"],
603
+ bypass["original"],
604
+ bypass["bypass"],
605
+ ))
606
+
607
+ conn.commit()
608
+ conn.close()
609
+
610
+ logger.info(f"Imported knowledge from {input_path}")
611
+
612
+ def _hash_payload(self, payload: str) -> str:
613
+ """Create a hash of a payload for deduplication."""
614
+ import hashlib
615
+ return hashlib.sha256(payload.encode()).hexdigest()[:16]
616
+
617
+ def clear_all(self):
618
+ """Clear all learned data (use with caution)."""
619
+ conn = sqlite3.connect(self.db_path)
620
+ cursor = conn.cursor()
621
+ cursor.execute("DELETE FROM exploit_attempts")
622
+ cursor.execute("DELETE FROM waf_bypasses")
623
+ cursor.execute("DELETE FROM payload_stats")
624
+ conn.commit()
625
+ conn.close()
626
+ logger.warning("Cleared all learning data")