souleyez 2.43.29__py3-none-any.whl → 3.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.
- souleyez/__init__.py +1 -2
- souleyez/ai/__init__.py +21 -15
- souleyez/ai/action_mapper.py +249 -150
- souleyez/ai/chain_advisor.py +116 -100
- souleyez/ai/claude_provider.py +29 -28
- souleyez/ai/context_builder.py +80 -62
- souleyez/ai/executor.py +158 -117
- souleyez/ai/feedback_handler.py +136 -121
- souleyez/ai/llm_factory.py +27 -20
- souleyez/ai/llm_provider.py +4 -2
- souleyez/ai/ollama_provider.py +6 -9
- souleyez/ai/ollama_service.py +44 -37
- souleyez/ai/path_scorer.py +91 -76
- souleyez/ai/recommender.py +176 -144
- souleyez/ai/report_context.py +74 -73
- souleyez/ai/report_service.py +84 -66
- souleyez/ai/result_parser.py +222 -229
- souleyez/ai/safety.py +67 -44
- souleyez/auth/__init__.py +23 -22
- souleyez/auth/audit.py +36 -26
- souleyez/auth/engagement_access.py +65 -48
- souleyez/auth/permissions.py +14 -3
- souleyez/auth/session_manager.py +54 -37
- souleyez/auth/user_manager.py +109 -64
- souleyez/commands/audit.py +40 -43
- souleyez/commands/auth.py +35 -15
- souleyez/commands/deliverables.py +55 -50
- souleyez/commands/engagement.py +47 -28
- souleyez/commands/license.py +32 -23
- souleyez/commands/screenshots.py +36 -32
- souleyez/commands/user.py +82 -36
- souleyez/config.py +52 -44
- souleyez/core/credential_tester.py +87 -81
- souleyez/core/cve_mappings.py +179 -192
- souleyez/core/cve_matcher.py +162 -148
- souleyez/core/msf_auto_mapper.py +100 -83
- souleyez/core/msf_chain_engine.py +294 -256
- souleyez/core/msf_database.py +153 -70
- souleyez/core/msf_integration.py +679 -673
- souleyez/core/msf_rpc_client.py +40 -42
- souleyez/core/msf_rpc_manager.py +77 -79
- souleyez/core/msf_sync_manager.py +241 -181
- souleyez/core/network_utils.py +22 -15
- souleyez/core/parser_handler.py +34 -25
- souleyez/core/pending_chains.py +114 -63
- souleyez/core/templates.py +158 -107
- souleyez/core/tool_chaining.py +9564 -2881
- souleyez/core/version_utils.py +79 -94
- souleyez/core/vuln_correlation.py +136 -89
- souleyez/core/web_utils.py +33 -32
- souleyez/data/wordlists/ad_users.txt +378 -0
- souleyez/data/wordlists/api_endpoints_large.txt +769 -0
- souleyez/data/wordlists/home_dir_sensitive.txt +39 -0
- souleyez/data/wordlists/lfi_payloads.txt +82 -0
- souleyez/data/wordlists/passwords_brute.txt +1548 -0
- souleyez/data/wordlists/passwords_crack.txt +2479 -0
- souleyez/data/wordlists/passwords_spray.txt +386 -0
- souleyez/data/wordlists/subdomains_large.txt +5057 -0
- souleyez/data/wordlists/usernames_common.txt +694 -0
- souleyez/data/wordlists/web_dirs_large.txt +4769 -0
- souleyez/detection/__init__.py +1 -1
- souleyez/detection/attack_signatures.py +12 -17
- souleyez/detection/mitre_mappings.py +61 -55
- souleyez/detection/validator.py +97 -86
- souleyez/devtools.py +23 -10
- souleyez/docs/README.md +4 -4
- souleyez/docs/api-reference/cli-commands.md +2 -2
- souleyez/docs/developer-guide/adding-new-tools.md +562 -0
- souleyez/docs/user-guide/auto-chaining.md +30 -8
- souleyez/docs/user-guide/getting-started.md +1 -1
- souleyez/docs/user-guide/installation.md +26 -3
- souleyez/docs/user-guide/metasploit-integration.md +2 -2
- souleyez/docs/user-guide/rbac.md +1 -1
- souleyez/docs/user-guide/scope-management.md +1 -1
- souleyez/docs/user-guide/siem-integration.md +1 -1
- souleyez/docs/user-guide/tools-reference.md +1 -8
- souleyez/docs/user-guide/worker-management.md +1 -1
- souleyez/engine/background.py +1239 -535
- souleyez/engine/base.py +4 -1
- souleyez/engine/job_status.py +17 -49
- souleyez/engine/log_sanitizer.py +103 -77
- souleyez/engine/manager.py +38 -7
- souleyez/engine/result_handler.py +2200 -1550
- souleyez/engine/worker_manager.py +50 -41
- souleyez/export/evidence_bundle.py +72 -62
- souleyez/feature_flags/features.py +16 -20
- souleyez/feature_flags.py +5 -9
- souleyez/handlers/__init__.py +11 -0
- souleyez/handlers/base.py +188 -0
- souleyez/handlers/bash_handler.py +277 -0
- souleyez/handlers/bloodhound_handler.py +243 -0
- souleyez/handlers/certipy_handler.py +311 -0
- souleyez/handlers/crackmapexec_handler.py +486 -0
- souleyez/handlers/dnsrecon_handler.py +344 -0
- souleyez/handlers/enum4linux_handler.py +400 -0
- souleyez/handlers/evil_winrm_handler.py +493 -0
- souleyez/handlers/ffuf_handler.py +815 -0
- souleyez/handlers/gobuster_handler.py +1114 -0
- souleyez/handlers/gpp_extract_handler.py +334 -0
- souleyez/handlers/hashcat_handler.py +444 -0
- souleyez/handlers/hydra_handler.py +564 -0
- souleyez/handlers/impacket_getuserspns_handler.py +343 -0
- souleyez/handlers/impacket_psexec_handler.py +222 -0
- souleyez/handlers/impacket_secretsdump_handler.py +426 -0
- souleyez/handlers/john_handler.py +286 -0
- souleyez/handlers/katana_handler.py +425 -0
- souleyez/handlers/kerbrute_handler.py +298 -0
- souleyez/handlers/ldapsearch_handler.py +636 -0
- souleyez/handlers/lfi_extract_handler.py +464 -0
- souleyez/handlers/msf_auxiliary_handler.py +409 -0
- souleyez/handlers/msf_exploit_handler.py +380 -0
- souleyez/handlers/nikto_handler.py +413 -0
- souleyez/handlers/nmap_handler.py +821 -0
- souleyez/handlers/nuclei_handler.py +359 -0
- souleyez/handlers/nxc_handler.py +417 -0
- souleyez/handlers/rdp_sec_check_handler.py +353 -0
- souleyez/handlers/registry.py +292 -0
- souleyez/handlers/responder_handler.py +232 -0
- souleyez/handlers/service_explorer_handler.py +434 -0
- souleyez/handlers/smbclient_handler.py +344 -0
- souleyez/handlers/smbmap_handler.py +510 -0
- souleyez/handlers/smbpasswd_handler.py +296 -0
- souleyez/handlers/sqlmap_handler.py +1116 -0
- souleyez/handlers/theharvester_handler.py +601 -0
- souleyez/handlers/web_login_test_handler.py +327 -0
- souleyez/handlers/whois_handler.py +277 -0
- souleyez/handlers/wpscan_handler.py +554 -0
- souleyez/history.py +32 -16
- souleyez/importers/msf_importer.py +106 -75
- souleyez/importers/smart_importer.py +208 -147
- souleyez/integrations/siem/__init__.py +10 -10
- souleyez/integrations/siem/base.py +17 -18
- souleyez/integrations/siem/elastic.py +108 -122
- souleyez/integrations/siem/factory.py +207 -80
- souleyez/integrations/siem/googlesecops.py +146 -154
- souleyez/integrations/siem/rule_mappings/__init__.py +1 -1
- souleyez/integrations/siem/rule_mappings/wazuh_rules.py +8 -5
- souleyez/integrations/siem/sentinel.py +107 -109
- souleyez/integrations/siem/splunk.py +246 -212
- souleyez/integrations/siem/wazuh.py +65 -71
- souleyez/integrations/wazuh/__init__.py +5 -5
- souleyez/integrations/wazuh/client.py +70 -93
- souleyez/integrations/wazuh/config.py +85 -57
- souleyez/integrations/wazuh/host_mapper.py +28 -36
- souleyez/integrations/wazuh/sync.py +78 -68
- souleyez/intelligence/__init__.py +4 -5
- souleyez/intelligence/correlation_analyzer.py +309 -295
- souleyez/intelligence/exploit_knowledge.py +661 -623
- souleyez/intelligence/exploit_suggestions.py +159 -139
- souleyez/intelligence/gap_analyzer.py +132 -97
- souleyez/intelligence/gap_detector.py +251 -214
- souleyez/intelligence/sensitive_tables.py +266 -129
- souleyez/intelligence/service_parser.py +137 -123
- souleyez/intelligence/surface_analyzer.py +407 -268
- souleyez/intelligence/target_parser.py +159 -162
- souleyez/licensing/__init__.py +6 -6
- souleyez/licensing/validator.py +17 -19
- souleyez/log_config.py +79 -54
- souleyez/main.py +1505 -687
- souleyez/migrations/fix_job_counter.py +16 -14
- souleyez/parsers/bloodhound_parser.py +41 -39
- souleyez/parsers/crackmapexec_parser.py +178 -111
- souleyez/parsers/dalfox_parser.py +72 -77
- souleyez/parsers/dnsrecon_parser.py +103 -91
- souleyez/parsers/enum4linux_parser.py +183 -153
- souleyez/parsers/ffuf_parser.py +29 -25
- souleyez/parsers/gobuster_parser.py +301 -41
- souleyez/parsers/hashcat_parser.py +324 -79
- souleyez/parsers/http_fingerprint_parser.py +350 -103
- souleyez/parsers/hydra_parser.py +131 -111
- souleyez/parsers/impacket_parser.py +231 -178
- souleyez/parsers/john_parser.py +98 -86
- souleyez/parsers/katana_parser.py +316 -0
- souleyez/parsers/msf_parser.py +943 -498
- souleyez/parsers/nikto_parser.py +346 -65
- souleyez/parsers/nmap_parser.py +262 -174
- souleyez/parsers/nuclei_parser.py +40 -44
- souleyez/parsers/responder_parser.py +26 -26
- souleyez/parsers/searchsploit_parser.py +74 -74
- souleyez/parsers/service_explorer_parser.py +279 -0
- souleyez/parsers/smbmap_parser.py +180 -124
- souleyez/parsers/sqlmap_parser.py +434 -308
- souleyez/parsers/theharvester_parser.py +75 -57
- souleyez/parsers/whois_parser.py +135 -94
- souleyez/parsers/wpscan_parser.py +278 -190
- souleyez/plugins/afp.py +44 -36
- souleyez/plugins/afp_brute.py +114 -46
- souleyez/plugins/ard.py +48 -37
- souleyez/plugins/bloodhound.py +95 -61
- souleyez/plugins/certipy.py +303 -0
- souleyez/plugins/crackmapexec.py +186 -85
- souleyez/plugins/dalfox.py +120 -59
- souleyez/plugins/dns_hijack.py +146 -41
- souleyez/plugins/dnsrecon.py +97 -61
- souleyez/plugins/enum4linux.py +91 -66
- souleyez/plugins/evil_winrm.py +291 -0
- souleyez/plugins/ffuf.py +166 -90
- souleyez/plugins/firmware_extract.py +133 -29
- souleyez/plugins/gobuster.py +387 -190
- souleyez/plugins/gpp_extract.py +393 -0
- souleyez/plugins/hashcat.py +100 -73
- souleyez/plugins/http_fingerprint.py +913 -267
- souleyez/plugins/hydra.py +566 -200
- souleyez/plugins/impacket_getnpusers.py +117 -69
- souleyez/plugins/impacket_psexec.py +84 -64
- souleyez/plugins/impacket_secretsdump.py +103 -69
- souleyez/plugins/impacket_smbclient.py +89 -75
- souleyez/plugins/john.py +86 -69
- souleyez/plugins/katana.py +313 -0
- souleyez/plugins/kerbrute.py +237 -0
- souleyez/plugins/lfi_extract.py +541 -0
- souleyez/plugins/macos_ssh.py +117 -48
- souleyez/plugins/mdns.py +35 -30
- souleyez/plugins/msf_auxiliary.py +253 -130
- souleyez/plugins/msf_exploit.py +239 -161
- souleyez/plugins/nikto.py +134 -78
- souleyez/plugins/nmap.py +275 -91
- souleyez/plugins/nuclei.py +180 -89
- souleyez/plugins/nxc.py +285 -0
- souleyez/plugins/plugin_base.py +35 -36
- souleyez/plugins/plugin_template.py +13 -5
- souleyez/plugins/rdp_sec_check.py +130 -0
- souleyez/plugins/responder.py +112 -71
- souleyez/plugins/router_http_brute.py +76 -65
- souleyez/plugins/router_ssh_brute.py +118 -41
- souleyez/plugins/router_telnet_brute.py +124 -42
- souleyez/plugins/routersploit.py +91 -59
- souleyez/plugins/routersploit_exploit.py +77 -55
- souleyez/plugins/searchsploit.py +91 -77
- souleyez/plugins/service_explorer.py +1160 -0
- souleyez/plugins/smbmap.py +122 -72
- souleyez/plugins/smbpasswd.py +215 -0
- souleyez/plugins/sqlmap.py +301 -113
- souleyez/plugins/theharvester.py +127 -75
- souleyez/plugins/tr069.py +79 -57
- souleyez/plugins/upnp.py +65 -47
- souleyez/plugins/upnp_abuse.py +73 -55
- souleyez/plugins/vnc_access.py +129 -42
- souleyez/plugins/vnc_brute.py +109 -38
- souleyez/plugins/web_login_test.py +417 -0
- souleyez/plugins/whois.py +77 -58
- souleyez/plugins/wpscan.py +219 -69
- souleyez/reporting/__init__.py +2 -1
- souleyez/reporting/attack_chain.py +411 -346
- souleyez/reporting/charts.py +436 -501
- souleyez/reporting/compliance_mappings.py +334 -201
- souleyez/reporting/detection_report.py +126 -125
- souleyez/reporting/formatters.py +828 -591
- souleyez/reporting/generator.py +386 -302
- souleyez/reporting/metrics.py +72 -75
- souleyez/scanner.py +35 -29
- souleyez/security/__init__.py +37 -11
- souleyez/security/scope_validator.py +175 -106
- souleyez/security/validation.py +237 -149
- souleyez/security.py +22 -6
- souleyez/storage/credentials.py +247 -186
- souleyez/storage/crypto.py +296 -129
- souleyez/storage/database.py +73 -50
- souleyez/storage/db.py +58 -36
- souleyez/storage/deliverable_evidence.py +177 -128
- souleyez/storage/deliverable_exporter.py +282 -246
- souleyez/storage/deliverable_templates.py +134 -116
- souleyez/storage/deliverables.py +135 -130
- souleyez/storage/engagements.py +109 -56
- souleyez/storage/evidence.py +181 -152
- souleyez/storage/execution_log.py +31 -17
- souleyez/storage/exploit_attempts.py +93 -57
- souleyez/storage/exploits.py +67 -36
- souleyez/storage/findings.py +48 -61
- souleyez/storage/hosts.py +176 -144
- souleyez/storage/migrate_to_engagements.py +43 -19
- souleyez/storage/migrations/_001_add_credential_enhancements.py +22 -12
- souleyez/storage/migrations/_002_add_status_tracking.py +10 -7
- souleyez/storage/migrations/_003_add_execution_log.py +14 -8
- souleyez/storage/migrations/_005_screenshots.py +13 -5
- souleyez/storage/migrations/_006_deliverables.py +13 -5
- souleyez/storage/migrations/_007_deliverable_templates.py +12 -7
- souleyez/storage/migrations/_008_add_nuclei_table.py +10 -4
- souleyez/storage/migrations/_010_evidence_linking.py +17 -10
- souleyez/storage/migrations/_011_timeline_tracking.py +20 -13
- souleyez/storage/migrations/_012_team_collaboration.py +34 -21
- souleyez/storage/migrations/_013_add_host_tags.py +12 -6
- souleyez/storage/migrations/_014_exploit_attempts.py +22 -10
- souleyez/storage/migrations/_015_add_mac_os_fields.py +15 -7
- souleyez/storage/migrations/_016_add_domain_field.py +10 -4
- souleyez/storage/migrations/_017_msf_sessions.py +16 -8
- souleyez/storage/migrations/_018_add_osint_target.py +10 -6
- souleyez/storage/migrations/_019_add_engagement_type.py +10 -6
- souleyez/storage/migrations/_020_add_rbac.py +36 -15
- souleyez/storage/migrations/_021_wazuh_integration.py +20 -8
- souleyez/storage/migrations/_022_wazuh_indexer_columns.py +6 -4
- souleyez/storage/migrations/_023_fix_detection_results_fk.py +16 -6
- souleyez/storage/migrations/_024_wazuh_vulnerabilities.py +26 -10
- souleyez/storage/migrations/_025_multi_siem_support.py +3 -5
- souleyez/storage/migrations/_026_add_engagement_scope.py +31 -12
- souleyez/storage/migrations/_027_multi_siem_persistence.py +32 -15
- souleyez/storage/migrations/__init__.py +26 -26
- souleyez/storage/migrations/migration_manager.py +19 -19
- souleyez/storage/msf_sessions.py +100 -65
- souleyez/storage/osint.py +17 -24
- souleyez/storage/recommendation_engine.py +269 -235
- souleyez/storage/screenshots.py +33 -32
- souleyez/storage/smb_shares.py +136 -92
- souleyez/storage/sqlmap_data.py +183 -128
- souleyez/storage/team_collaboration.py +135 -141
- souleyez/storage/timeline_tracker.py +122 -94
- souleyez/storage/wazuh_vulns.py +64 -66
- souleyez/storage/web_paths.py +33 -37
- souleyez/testing/credential_tester.py +221 -205
- souleyez/ui/__init__.py +1 -1
- souleyez/ui/ai_quotes.py +12 -12
- souleyez/ui/attack_surface.py +2439 -1516
- souleyez/ui/chain_rules_view.py +914 -382
- souleyez/ui/correlation_view.py +312 -230
- souleyez/ui/dashboard.py +2382 -1130
- souleyez/ui/deliverables_view.py +148 -62
- souleyez/ui/design_system.py +13 -13
- souleyez/ui/errors.py +49 -49
- souleyez/ui/evidence_linking_view.py +284 -179
- souleyez/ui/evidence_vault.py +393 -285
- souleyez/ui/exploit_suggestions_view.py +555 -349
- souleyez/ui/export_view.py +100 -66
- souleyez/ui/gap_analysis_view.py +315 -171
- souleyez/ui/help_system.py +105 -97
- souleyez/ui/intelligence_view.py +436 -293
- souleyez/ui/interactive.py +23034 -10679
- souleyez/ui/interactive_selector.py +75 -68
- souleyez/ui/log_formatter.py +47 -39
- souleyez/ui/menu_components.py +22 -13
- souleyez/ui/msf_auxiliary_menu.py +184 -133
- souleyez/ui/pending_chains_view.py +336 -172
- souleyez/ui/progress_indicators.py +5 -3
- souleyez/ui/recommendations_view.py +195 -137
- souleyez/ui/rule_builder.py +343 -225
- souleyez/ui/setup_wizard.py +678 -284
- souleyez/ui/shortcuts.py +217 -165
- souleyez/ui/splunk_gap_analysis_view.py +452 -270
- souleyez/ui/splunk_vulns_view.py +139 -86
- souleyez/ui/team_dashboard.py +498 -335
- souleyez/ui/template_selector.py +196 -105
- souleyez/ui/terminal.py +6 -6
- souleyez/ui/timeline_view.py +198 -127
- souleyez/ui/tool_setup.py +264 -164
- souleyez/ui/tutorial.py +202 -72
- souleyez/ui/tutorial_state.py +40 -40
- souleyez/ui/wazuh_vulns_view.py +235 -141
- souleyez/ui/wordlist_browser.py +260 -107
- souleyez/ui.py +464 -312
- souleyez/utils/tool_checker.py +427 -367
- souleyez/utils.py +33 -29
- souleyez/wordlists.py +134 -167
- {souleyez-2.43.29.dist-info → souleyez-3.0.0.dist-info}/METADATA +2 -2
- souleyez-3.0.0.dist-info/RECORD +443 -0
- {souleyez-2.43.29.dist-info → souleyez-3.0.0.dist-info}/WHEEL +1 -1
- souleyez-2.43.29.dist-info/RECORD +0 -379
- {souleyez-2.43.29.dist-info → souleyez-3.0.0.dist-info}/entry_points.txt +0 -0
- {souleyez-2.43.29.dist-info → souleyez-3.0.0.dist-info}/licenses/LICENSE +0 -0
- {souleyez-2.43.29.dist-info → souleyez-3.0.0.dist-info}/top_level.txt +0 -0
souleyez/storage/sqlmap_data.py
CHANGED
|
@@ -16,162 +16,182 @@ logger = get_logger(__name__)
|
|
|
16
16
|
|
|
17
17
|
class SQLMapDataManager:
|
|
18
18
|
"""Manager for storing and retrieving SQLMap discoveries."""
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
def __init__(self, db_path: str = None):
|
|
21
21
|
self.db = Database(db_path)
|
|
22
|
-
|
|
23
|
-
def add_database(
|
|
24
|
-
|
|
22
|
+
|
|
23
|
+
def add_database(
|
|
24
|
+
self,
|
|
25
|
+
engagement_id: int,
|
|
26
|
+
host_id: int,
|
|
27
|
+
database_name: str,
|
|
28
|
+
dbms_type: str = None,
|
|
29
|
+
) -> Optional[int]:
|
|
25
30
|
"""
|
|
26
31
|
Add a discovered database.
|
|
27
|
-
|
|
32
|
+
|
|
28
33
|
Args:
|
|
29
34
|
engagement_id: Engagement ID
|
|
30
35
|
host_id: Host ID
|
|
31
36
|
database_name: Name of the database
|
|
32
37
|
dbms_type: Type of DBMS (MySQL, PostgreSQL, etc.)
|
|
33
|
-
|
|
38
|
+
|
|
34
39
|
Returns:
|
|
35
40
|
Database ID if successful, None otherwise
|
|
36
41
|
"""
|
|
37
42
|
try:
|
|
38
43
|
conn = sqlite3.connect(self.db.db_path, timeout=30.0)
|
|
39
44
|
cursor = conn.cursor()
|
|
40
|
-
|
|
45
|
+
|
|
41
46
|
# Try to insert, or get existing ID
|
|
42
|
-
cursor.execute(
|
|
47
|
+
cursor.execute(
|
|
48
|
+
"""
|
|
43
49
|
INSERT OR IGNORE INTO sqli_databases
|
|
44
50
|
(engagement_id, host_id, database_name, dbms_type)
|
|
45
51
|
VALUES (?, ?, ?, ?)
|
|
46
|
-
""",
|
|
47
|
-
|
|
52
|
+
""",
|
|
53
|
+
(engagement_id, host_id, database_name, dbms_type),
|
|
54
|
+
)
|
|
55
|
+
|
|
48
56
|
if cursor.rowcount > 0:
|
|
49
57
|
db_id = cursor.lastrowid
|
|
50
58
|
else:
|
|
51
59
|
# Get existing ID
|
|
52
|
-
cursor.execute(
|
|
60
|
+
cursor.execute(
|
|
61
|
+
"""
|
|
53
62
|
SELECT id FROM sqli_databases
|
|
54
63
|
WHERE engagement_id = ? AND host_id = ? AND database_name = ?
|
|
55
|
-
""",
|
|
64
|
+
""",
|
|
65
|
+
(engagement_id, host_id, database_name),
|
|
66
|
+
)
|
|
56
67
|
row = cursor.fetchone()
|
|
57
68
|
db_id = row[0] if row else None
|
|
58
|
-
|
|
69
|
+
|
|
59
70
|
conn.commit()
|
|
60
71
|
conn.close()
|
|
61
|
-
|
|
62
|
-
logger.info(
|
|
63
|
-
"
|
|
64
|
-
"dbms_type": dbms_type
|
|
65
|
-
|
|
72
|
+
|
|
73
|
+
logger.info(
|
|
74
|
+
f"Added database: {database_name}",
|
|
75
|
+
extra={"db_id": db_id, "dbms_type": dbms_type},
|
|
76
|
+
)
|
|
66
77
|
return db_id
|
|
67
|
-
|
|
78
|
+
|
|
68
79
|
except Exception as e:
|
|
69
80
|
logger.error(f"Failed to add database: {e}")
|
|
70
81
|
return None
|
|
71
|
-
|
|
72
|
-
def add_table(
|
|
73
|
-
|
|
82
|
+
|
|
83
|
+
def add_table(
|
|
84
|
+
self, database_id: int, table_name: str, row_count: int = None
|
|
85
|
+
) -> Optional[int]:
|
|
74
86
|
"""
|
|
75
87
|
Add a discovered table.
|
|
76
|
-
|
|
88
|
+
|
|
77
89
|
Args:
|
|
78
90
|
database_id: Database ID
|
|
79
91
|
table_name: Name of the table
|
|
80
92
|
row_count: Number of rows in the table
|
|
81
|
-
|
|
93
|
+
|
|
82
94
|
Returns:
|
|
83
95
|
Table ID if successful, None otherwise
|
|
84
96
|
"""
|
|
85
97
|
try:
|
|
86
98
|
conn = sqlite3.connect(self.db.db_path, timeout=30.0)
|
|
87
99
|
cursor = conn.cursor()
|
|
88
|
-
|
|
89
|
-
cursor.execute(
|
|
100
|
+
|
|
101
|
+
cursor.execute(
|
|
102
|
+
"""
|
|
90
103
|
INSERT OR IGNORE INTO sqli_tables
|
|
91
104
|
(database_id, table_name, row_count)
|
|
92
105
|
VALUES (?, ?, ?)
|
|
93
|
-
""",
|
|
94
|
-
|
|
106
|
+
""",
|
|
107
|
+
(database_id, table_name, row_count),
|
|
108
|
+
)
|
|
109
|
+
|
|
95
110
|
if cursor.rowcount > 0:
|
|
96
111
|
table_id = cursor.lastrowid
|
|
97
112
|
else:
|
|
98
|
-
cursor.execute(
|
|
113
|
+
cursor.execute(
|
|
114
|
+
"""
|
|
99
115
|
SELECT id FROM sqli_tables
|
|
100
116
|
WHERE database_id = ? AND table_name = ?
|
|
101
|
-
""",
|
|
117
|
+
""",
|
|
118
|
+
(database_id, table_name),
|
|
119
|
+
)
|
|
102
120
|
row = cursor.fetchone()
|
|
103
121
|
table_id = row[0] if row else None
|
|
104
|
-
|
|
122
|
+
|
|
105
123
|
conn.commit()
|
|
106
124
|
conn.close()
|
|
107
|
-
|
|
108
|
-
logger.info(
|
|
109
|
-
"
|
|
110
|
-
"row_count": row_count
|
|
111
|
-
|
|
125
|
+
|
|
126
|
+
logger.info(
|
|
127
|
+
f"Added table: {table_name}",
|
|
128
|
+
extra={"table_id": table_id, "row_count": row_count},
|
|
129
|
+
)
|
|
112
130
|
return table_id
|
|
113
|
-
|
|
131
|
+
|
|
114
132
|
except Exception as e:
|
|
115
133
|
logger.error(f"Failed to add table: {e}")
|
|
116
134
|
return None
|
|
117
|
-
|
|
135
|
+
|
|
118
136
|
def add_columns(self, table_id: int, columns: List[Dict[str, str]]) -> bool:
|
|
119
137
|
"""
|
|
120
138
|
Add discovered columns for a table.
|
|
121
|
-
|
|
139
|
+
|
|
122
140
|
Args:
|
|
123
141
|
table_id: Table ID
|
|
124
142
|
columns: List of column dicts with 'name' and optionally 'type'
|
|
125
|
-
|
|
143
|
+
|
|
126
144
|
Returns:
|
|
127
145
|
True if successful, False otherwise
|
|
128
146
|
"""
|
|
129
147
|
try:
|
|
130
148
|
conn = sqlite3.connect(self.db.db_path, timeout=30.0)
|
|
131
149
|
cursor = conn.cursor()
|
|
132
|
-
|
|
150
|
+
|
|
133
151
|
for col in columns:
|
|
134
|
-
col_name = col.get(
|
|
135
|
-
col_type = col.get(
|
|
136
|
-
|
|
137
|
-
cursor.execute(
|
|
152
|
+
col_name = col.get("name") or col.get("column_name")
|
|
153
|
+
col_type = col.get("type") or col.get("column_type")
|
|
154
|
+
|
|
155
|
+
cursor.execute(
|
|
156
|
+
"""
|
|
138
157
|
INSERT OR IGNORE INTO sqli_columns
|
|
139
158
|
(table_id, column_name, column_type)
|
|
140
159
|
VALUES (?, ?, ?)
|
|
141
|
-
""",
|
|
142
|
-
|
|
160
|
+
""",
|
|
161
|
+
(table_id, col_name, col_type),
|
|
162
|
+
)
|
|
163
|
+
|
|
143
164
|
conn.commit()
|
|
144
165
|
conn.close()
|
|
145
|
-
|
|
146
|
-
logger.info(f"Added {len(columns)} columns", extra={
|
|
147
|
-
"table_id": table_id
|
|
148
|
-
})
|
|
166
|
+
|
|
167
|
+
logger.info(f"Added {len(columns)} columns", extra={"table_id": table_id})
|
|
149
168
|
return True
|
|
150
|
-
|
|
169
|
+
|
|
151
170
|
except Exception as e:
|
|
152
171
|
logger.error(f"Failed to add columns: {e}")
|
|
153
172
|
return False
|
|
154
|
-
|
|
155
|
-
def add_dumped_data(
|
|
156
|
-
|
|
173
|
+
|
|
174
|
+
def add_dumped_data(
|
|
175
|
+
self, table_id: int, data: List[Dict[str, Any]], csv_file_path: str = None
|
|
176
|
+
) -> Optional[int]:
|
|
157
177
|
"""
|
|
158
178
|
Add dumped table data.
|
|
159
|
-
|
|
179
|
+
|
|
160
180
|
Args:
|
|
161
181
|
table_id: Table ID
|
|
162
182
|
data: List of row dicts
|
|
163
183
|
csv_file_path: Path to SQLMap's CSV dump file
|
|
164
|
-
|
|
184
|
+
|
|
165
185
|
Returns:
|
|
166
186
|
Dump ID if successful, None otherwise
|
|
167
187
|
"""
|
|
168
188
|
try:
|
|
169
189
|
conn = sqlite3.connect(self.db.db_path, timeout=30.0)
|
|
170
190
|
cursor = conn.cursor()
|
|
171
|
-
|
|
191
|
+
|
|
172
192
|
data_json = json.dumps(data)
|
|
173
193
|
row_count = len(data)
|
|
174
|
-
|
|
194
|
+
|
|
175
195
|
# Try to encrypt if crypto is available
|
|
176
196
|
is_encrypted = 0
|
|
177
197
|
try:
|
|
@@ -183,38 +203,47 @@ class SQLMapDataManager:
|
|
|
183
203
|
except Exception as e:
|
|
184
204
|
logger.warning(f"Could not encrypt dumped data: {e}")
|
|
185
205
|
# Continue with unencrypted data
|
|
186
|
-
|
|
187
|
-
cursor.execute(
|
|
206
|
+
|
|
207
|
+
cursor.execute(
|
|
208
|
+
"""
|
|
188
209
|
INSERT INTO sqli_dumped_data
|
|
189
210
|
(table_id, data_json, csv_file_path, row_count, is_encrypted)
|
|
190
211
|
VALUES (?, ?, ?, ?, ?)
|
|
191
|
-
""",
|
|
192
|
-
|
|
212
|
+
""",
|
|
213
|
+
(table_id, data_json, csv_file_path, row_count, is_encrypted),
|
|
214
|
+
)
|
|
215
|
+
|
|
193
216
|
dump_id = cursor.lastrowid
|
|
194
217
|
conn.commit()
|
|
195
218
|
conn.close()
|
|
196
|
-
|
|
197
|
-
logger.info(
|
|
198
|
-
"
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
219
|
+
|
|
220
|
+
logger.info(
|
|
221
|
+
f"Added dumped data",
|
|
222
|
+
extra={
|
|
223
|
+
"table_id": table_id,
|
|
224
|
+
"row_count": row_count,
|
|
225
|
+
"dump_id": dump_id,
|
|
226
|
+
"encrypted": is_encrypted,
|
|
227
|
+
},
|
|
228
|
+
)
|
|
203
229
|
return dump_id
|
|
204
|
-
|
|
230
|
+
|
|
205
231
|
except Exception as e:
|
|
206
232
|
logger.error(f"Failed to add dumped data: {e}")
|
|
207
233
|
return None
|
|
208
|
-
|
|
209
|
-
def get_databases(
|
|
234
|
+
|
|
235
|
+
def get_databases(
|
|
236
|
+
self, engagement_id: int, host_id: int = None
|
|
237
|
+
) -> List[Dict[str, Any]]:
|
|
210
238
|
"""Get all discovered databases for an engagement."""
|
|
211
239
|
try:
|
|
212
240
|
conn = sqlite3.connect(self.db.db_path, timeout=30.0)
|
|
213
241
|
conn.row_factory = sqlite3.Row
|
|
214
242
|
cursor = conn.cursor()
|
|
215
|
-
|
|
243
|
+
|
|
216
244
|
if host_id:
|
|
217
|
-
cursor.execute(
|
|
245
|
+
cursor.execute(
|
|
246
|
+
"""
|
|
218
247
|
SELECT d.*, h.ip_address, h.hostname,
|
|
219
248
|
COUNT(DISTINCT t.id) as table_count
|
|
220
249
|
FROM sqli_databases d
|
|
@@ -223,9 +252,12 @@ class SQLMapDataManager:
|
|
|
223
252
|
WHERE d.engagement_id = ? AND d.host_id = ?
|
|
224
253
|
GROUP BY d.id
|
|
225
254
|
ORDER BY d.discovered_at DESC
|
|
226
|
-
""",
|
|
255
|
+
""",
|
|
256
|
+
(engagement_id, host_id),
|
|
257
|
+
)
|
|
227
258
|
else:
|
|
228
|
-
cursor.execute(
|
|
259
|
+
cursor.execute(
|
|
260
|
+
"""
|
|
229
261
|
SELECT d.*, h.ip_address, h.hostname,
|
|
230
262
|
COUNT(DISTINCT t.id) as table_count
|
|
231
263
|
FROM sqli_databases d
|
|
@@ -234,25 +266,28 @@ class SQLMapDataManager:
|
|
|
234
266
|
WHERE d.engagement_id = ?
|
|
235
267
|
GROUP BY d.id
|
|
236
268
|
ORDER BY d.discovered_at DESC
|
|
237
|
-
""",
|
|
238
|
-
|
|
269
|
+
""",
|
|
270
|
+
(engagement_id,),
|
|
271
|
+
)
|
|
272
|
+
|
|
239
273
|
rows = cursor.fetchall()
|
|
240
274
|
conn.close()
|
|
241
|
-
|
|
275
|
+
|
|
242
276
|
return [dict(row) for row in rows]
|
|
243
|
-
|
|
277
|
+
|
|
244
278
|
except Exception as e:
|
|
245
279
|
logger.error(f"Failed to get databases: {e}")
|
|
246
280
|
return []
|
|
247
|
-
|
|
281
|
+
|
|
248
282
|
def get_tables(self, database_id: int) -> List[Dict[str, Any]]:
|
|
249
283
|
"""Get all tables for a database."""
|
|
250
284
|
try:
|
|
251
285
|
conn = sqlite3.connect(self.db.db_path, timeout=30.0)
|
|
252
286
|
conn.row_factory = sqlite3.Row
|
|
253
287
|
cursor = conn.cursor()
|
|
254
|
-
|
|
255
|
-
cursor.execute(
|
|
288
|
+
|
|
289
|
+
cursor.execute(
|
|
290
|
+
"""
|
|
256
291
|
SELECT t.*,
|
|
257
292
|
COUNT(DISTINCT c.id) as column_count,
|
|
258
293
|
CASE WHEN d.id IS NOT NULL THEN 1 ELSE 0 END as has_dumped_data
|
|
@@ -262,62 +297,70 @@ class SQLMapDataManager:
|
|
|
262
297
|
WHERE t.database_id = ?
|
|
263
298
|
GROUP BY t.id
|
|
264
299
|
ORDER BY t.table_name
|
|
265
|
-
""",
|
|
266
|
-
|
|
300
|
+
""",
|
|
301
|
+
(database_id,),
|
|
302
|
+
)
|
|
303
|
+
|
|
267
304
|
rows = cursor.fetchall()
|
|
268
305
|
conn.close()
|
|
269
|
-
|
|
306
|
+
|
|
270
307
|
return [dict(row) for row in rows]
|
|
271
|
-
|
|
308
|
+
|
|
272
309
|
except Exception as e:
|
|
273
310
|
logger.error(f"Failed to get tables: {e}")
|
|
274
311
|
return []
|
|
275
|
-
|
|
312
|
+
|
|
276
313
|
def get_columns(self, table_id: int) -> List[Dict[str, Any]]:
|
|
277
314
|
"""Get all columns for a table."""
|
|
278
315
|
try:
|
|
279
316
|
conn = sqlite3.connect(self.db.db_path, timeout=30.0)
|
|
280
317
|
conn.row_factory = sqlite3.Row
|
|
281
318
|
cursor = conn.cursor()
|
|
282
|
-
|
|
283
|
-
cursor.execute(
|
|
319
|
+
|
|
320
|
+
cursor.execute(
|
|
321
|
+
"""
|
|
284
322
|
SELECT * FROM sqli_columns
|
|
285
323
|
WHERE table_id = ?
|
|
286
324
|
ORDER BY column_name
|
|
287
|
-
""",
|
|
288
|
-
|
|
325
|
+
""",
|
|
326
|
+
(table_id,),
|
|
327
|
+
)
|
|
328
|
+
|
|
289
329
|
rows = cursor.fetchall()
|
|
290
330
|
conn.close()
|
|
291
|
-
|
|
331
|
+
|
|
292
332
|
return [dict(row) for row in rows]
|
|
293
|
-
|
|
333
|
+
|
|
294
334
|
except Exception as e:
|
|
295
335
|
logger.error(f"Failed to get columns: {e}")
|
|
296
336
|
return []
|
|
297
|
-
|
|
337
|
+
|
|
298
338
|
def get_dumped_data(self, table_id: int) -> Optional[Dict[str, Any]]:
|
|
299
339
|
"""Get dumped data for a table."""
|
|
300
340
|
try:
|
|
301
341
|
conn = sqlite3.connect(self.db.db_path, timeout=30.0)
|
|
302
342
|
conn.row_factory = sqlite3.Row
|
|
303
343
|
cursor = conn.cursor()
|
|
304
|
-
|
|
305
|
-
cursor.execute(
|
|
344
|
+
|
|
345
|
+
cursor.execute(
|
|
346
|
+
"""
|
|
306
347
|
SELECT * FROM sqli_dumped_data
|
|
307
348
|
WHERE table_id = ?
|
|
308
349
|
ORDER BY dumped_at DESC
|
|
309
350
|
LIMIT 1
|
|
310
|
-
""",
|
|
311
|
-
|
|
351
|
+
""",
|
|
352
|
+
(table_id,),
|
|
353
|
+
)
|
|
354
|
+
|
|
312
355
|
row = cursor.fetchone()
|
|
313
356
|
conn.close()
|
|
314
|
-
|
|
357
|
+
|
|
315
358
|
if row:
|
|
316
359
|
result = dict(row)
|
|
317
|
-
data_json = result[
|
|
318
|
-
|
|
360
|
+
data_json = result["data_json"]
|
|
361
|
+
|
|
319
362
|
# Decrypt if encrypted
|
|
320
|
-
if result.get(
|
|
363
|
+
if result.get("is_encrypted"):
|
|
321
364
|
try:
|
|
322
365
|
crypto = get_crypto_manager()
|
|
323
366
|
if crypto.is_encryption_enabled():
|
|
@@ -328,63 +371,75 @@ class SQLMapDataManager:
|
|
|
328
371
|
except Exception as e:
|
|
329
372
|
logger.error(f"Failed to decrypt dumped data: {e}")
|
|
330
373
|
return None
|
|
331
|
-
|
|
332
|
-
result[
|
|
374
|
+
|
|
375
|
+
result["data"] = json.loads(data_json)
|
|
333
376
|
return result
|
|
334
377
|
return None
|
|
335
|
-
|
|
378
|
+
|
|
336
379
|
except Exception as e:
|
|
337
380
|
logger.error(f"Failed to get dumped data: {e}")
|
|
338
381
|
return None
|
|
339
|
-
|
|
382
|
+
|
|
340
383
|
def get_summary(self, engagement_id: int) -> Dict[str, int]:
|
|
341
384
|
"""Get summary statistics for SQLMap discoveries."""
|
|
342
385
|
try:
|
|
343
386
|
conn = sqlite3.connect(self.db.db_path, timeout=30.0)
|
|
344
387
|
cursor = conn.cursor()
|
|
345
|
-
|
|
388
|
+
|
|
346
389
|
# Count databases
|
|
347
|
-
cursor.execute(
|
|
390
|
+
cursor.execute(
|
|
391
|
+
"""
|
|
348
392
|
SELECT COUNT(*) FROM sqli_databases
|
|
349
393
|
WHERE engagement_id = ?
|
|
350
|
-
""",
|
|
394
|
+
""",
|
|
395
|
+
(engagement_id,),
|
|
396
|
+
)
|
|
351
397
|
db_count = cursor.fetchone()[0]
|
|
352
|
-
|
|
398
|
+
|
|
353
399
|
# Count tables
|
|
354
|
-
cursor.execute(
|
|
400
|
+
cursor.execute(
|
|
401
|
+
"""
|
|
355
402
|
SELECT COUNT(*) FROM sqli_tables t
|
|
356
403
|
JOIN sqli_databases d ON t.database_id = d.id
|
|
357
404
|
WHERE d.engagement_id = ?
|
|
358
|
-
""",
|
|
405
|
+
""",
|
|
406
|
+
(engagement_id,),
|
|
407
|
+
)
|
|
359
408
|
table_count = cursor.fetchone()[0]
|
|
360
|
-
|
|
409
|
+
|
|
361
410
|
# Count columns
|
|
362
|
-
cursor.execute(
|
|
411
|
+
cursor.execute(
|
|
412
|
+
"""
|
|
363
413
|
SELECT COUNT(*) FROM sqli_columns c
|
|
364
414
|
JOIN sqli_tables t ON c.table_id = t.id
|
|
365
415
|
JOIN sqli_databases d ON t.database_id = d.id
|
|
366
416
|
WHERE d.engagement_id = ?
|
|
367
|
-
""",
|
|
417
|
+
""",
|
|
418
|
+
(engagement_id,),
|
|
419
|
+
)
|
|
368
420
|
column_count = cursor.fetchone()[0]
|
|
369
|
-
|
|
421
|
+
|
|
370
422
|
# Count dumped tables
|
|
371
|
-
cursor.execute(
|
|
423
|
+
cursor.execute(
|
|
424
|
+
"""
|
|
372
425
|
SELECT COUNT(DISTINCT table_id) FROM sqli_dumped_data dd
|
|
373
426
|
JOIN sqli_tables t ON dd.table_id = t.id
|
|
374
427
|
JOIN sqli_databases d ON t.database_id = d.id
|
|
375
428
|
WHERE d.engagement_id = ?
|
|
376
|
-
""",
|
|
429
|
+
""",
|
|
430
|
+
(engagement_id,),
|
|
431
|
+
)
|
|
377
432
|
dumped_count = cursor.fetchone()[0]
|
|
378
|
-
|
|
433
|
+
|
|
379
434
|
conn.close()
|
|
380
|
-
|
|
435
|
+
|
|
381
436
|
return {
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
437
|
+
"databases": db_count,
|
|
438
|
+
"tables": table_count,
|
|
439
|
+
"columns": column_count,
|
|
440
|
+
"dumped_tables": dumped_count,
|
|
386
441
|
}
|
|
387
|
-
|
|
442
|
+
|
|
388
443
|
except Exception as e:
|
|
389
444
|
logger.error(f"Failed to get summary: {e}")
|
|
390
|
-
return {
|
|
445
|
+
return {"databases": 0, "tables": 0, "columns": 0, "dumped_tables": 0}
|