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
|
@@ -9,6 +9,7 @@ Columns added:
|
|
|
9
9
|
- engagements.scope_enforcement: Enforcement mode (off, warn, block)
|
|
10
10
|
- hosts.scope_status: Host scope status (in_scope, out_of_scope, unknown)
|
|
11
11
|
"""
|
|
12
|
+
|
|
12
13
|
import os
|
|
13
14
|
|
|
14
15
|
|
|
@@ -16,7 +17,8 @@ def upgrade(conn):
|
|
|
16
17
|
"""Add scope validation tables and columns."""
|
|
17
18
|
|
|
18
19
|
# Engagement scope definitions table
|
|
19
|
-
conn.execute(
|
|
20
|
+
conn.execute(
|
|
21
|
+
"""
|
|
20
22
|
CREATE TABLE IF NOT EXISTS engagement_scope (
|
|
21
23
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
22
24
|
engagement_id INTEGER NOT NULL,
|
|
@@ -29,10 +31,12 @@ def upgrade(conn):
|
|
|
29
31
|
FOREIGN KEY (engagement_id) REFERENCES engagements(id) ON DELETE CASCADE,
|
|
30
32
|
UNIQUE(engagement_id, scope_type, value)
|
|
31
33
|
)
|
|
32
|
-
"""
|
|
34
|
+
"""
|
|
35
|
+
)
|
|
33
36
|
|
|
34
37
|
# Scope validation audit log
|
|
35
|
-
conn.execute(
|
|
38
|
+
conn.execute(
|
|
39
|
+
"""
|
|
36
40
|
CREATE TABLE IF NOT EXISTS scope_validation_log (
|
|
37
41
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
38
42
|
engagement_id INTEGER NOT NULL,
|
|
@@ -45,11 +49,14 @@ def upgrade(conn):
|
|
|
45
49
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
46
50
|
FOREIGN KEY (engagement_id) REFERENCES engagements(id) ON DELETE CASCADE
|
|
47
51
|
)
|
|
48
|
-
"""
|
|
52
|
+
"""
|
|
53
|
+
)
|
|
49
54
|
|
|
50
55
|
# Add scope_enforcement column to engagements
|
|
51
56
|
try:
|
|
52
|
-
conn.execute(
|
|
57
|
+
conn.execute(
|
|
58
|
+
"ALTER TABLE engagements ADD COLUMN scope_enforcement TEXT DEFAULT 'off'"
|
|
59
|
+
)
|
|
53
60
|
except Exception:
|
|
54
61
|
pass # Column may already exist
|
|
55
62
|
|
|
@@ -60,16 +67,28 @@ def upgrade(conn):
|
|
|
60
67
|
pass # Column may already exist
|
|
61
68
|
|
|
62
69
|
# Indexes for performance
|
|
63
|
-
conn.execute(
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
conn.execute(
|
|
67
|
-
|
|
68
|
-
|
|
70
|
+
conn.execute(
|
|
71
|
+
"CREATE INDEX IF NOT EXISTS idx_scope_engagement ON engagement_scope(engagement_id)"
|
|
72
|
+
)
|
|
73
|
+
conn.execute(
|
|
74
|
+
"CREATE INDEX IF NOT EXISTS idx_scope_type ON engagement_scope(scope_type)"
|
|
75
|
+
)
|
|
76
|
+
conn.execute(
|
|
77
|
+
"CREATE INDEX IF NOT EXISTS idx_scope_log_engagement ON scope_validation_log(engagement_id)"
|
|
78
|
+
)
|
|
79
|
+
conn.execute(
|
|
80
|
+
"CREATE INDEX IF NOT EXISTS idx_scope_log_result ON scope_validation_log(validation_result)"
|
|
81
|
+
)
|
|
82
|
+
conn.execute(
|
|
83
|
+
"CREATE INDEX IF NOT EXISTS idx_scope_log_timestamp ON scope_validation_log(created_at DESC)"
|
|
84
|
+
)
|
|
85
|
+
conn.execute(
|
|
86
|
+
"CREATE INDEX IF NOT EXISTS idx_hosts_scope_status ON hosts(scope_status)"
|
|
87
|
+
)
|
|
69
88
|
|
|
70
89
|
conn.commit()
|
|
71
90
|
|
|
72
|
-
if not os.environ.get(
|
|
91
|
+
if not os.environ.get("SOULEYEZ_MIGRATION_SILENT"):
|
|
73
92
|
print("Migration 026: Engagement scope validation tables created")
|
|
74
93
|
|
|
75
94
|
|
|
@@ -6,6 +6,7 @@ Changes wazuh_config table to support multiple SIEM configs per engagement.
|
|
|
6
6
|
- Adds UNIQUE constraint on (engagement_id, siem_type)
|
|
7
7
|
- Allows each engagement to have separate configs for Wazuh, Splunk, etc.
|
|
8
8
|
"""
|
|
9
|
+
|
|
9
10
|
import os
|
|
10
11
|
|
|
11
12
|
|
|
@@ -17,13 +18,16 @@ def upgrade(conn):
|
|
|
17
18
|
cursor.execute("PRAGMA table_info(wazuh_config)")
|
|
18
19
|
columns = [col[1] for col in cursor.fetchall()]
|
|
19
20
|
|
|
20
|
-
if
|
|
21
|
-
cursor.execute(
|
|
22
|
-
|
|
21
|
+
if "siem_type" not in columns:
|
|
22
|
+
cursor.execute(
|
|
23
|
+
"ALTER TABLE wazuh_config ADD COLUMN siem_type TEXT DEFAULT 'wazuh'"
|
|
24
|
+
)
|
|
25
|
+
if "config_json" not in columns:
|
|
23
26
|
cursor.execute("ALTER TABLE wazuh_config ADD COLUMN config_json TEXT")
|
|
24
27
|
|
|
25
28
|
# Create new table with correct constraint
|
|
26
|
-
cursor.execute(
|
|
29
|
+
cursor.execute(
|
|
30
|
+
"""
|
|
27
31
|
CREATE TABLE IF NOT EXISTS siem_config_new (
|
|
28
32
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
29
33
|
engagement_id INTEGER NOT NULL,
|
|
@@ -42,10 +46,12 @@ def upgrade(conn):
|
|
|
42
46
|
FOREIGN KEY (engagement_id) REFERENCES engagements(id) ON DELETE CASCADE,
|
|
43
47
|
UNIQUE(engagement_id, siem_type)
|
|
44
48
|
)
|
|
45
|
-
"""
|
|
49
|
+
"""
|
|
50
|
+
)
|
|
46
51
|
|
|
47
52
|
# Copy existing data
|
|
48
|
-
cursor.execute(
|
|
53
|
+
cursor.execute(
|
|
54
|
+
"""
|
|
49
55
|
INSERT OR IGNORE INTO siem_config_new (
|
|
50
56
|
id, engagement_id, siem_type, api_url, api_user, api_password,
|
|
51
57
|
indexer_url, indexer_user, indexer_password, verify_ssl, enabled,
|
|
@@ -56,19 +62,24 @@ def upgrade(conn):
|
|
|
56
62
|
indexer_url, indexer_user, indexer_password, verify_ssl, enabled,
|
|
57
63
|
config_json, created_at, updated_at
|
|
58
64
|
FROM wazuh_config
|
|
59
|
-
"""
|
|
65
|
+
"""
|
|
66
|
+
)
|
|
60
67
|
|
|
61
68
|
# Drop old table and rename new one
|
|
62
69
|
cursor.execute("DROP TABLE wazuh_config")
|
|
63
70
|
cursor.execute("ALTER TABLE siem_config_new RENAME TO wazuh_config")
|
|
64
71
|
|
|
65
72
|
# Recreate index
|
|
66
|
-
cursor.execute(
|
|
67
|
-
|
|
73
|
+
cursor.execute(
|
|
74
|
+
"CREATE INDEX IF NOT EXISTS idx_wazuh_config_engagement ON wazuh_config(engagement_id)"
|
|
75
|
+
)
|
|
76
|
+
cursor.execute(
|
|
77
|
+
"CREATE INDEX IF NOT EXISTS idx_wazuh_config_siem_type ON wazuh_config(siem_type)"
|
|
78
|
+
)
|
|
68
79
|
|
|
69
80
|
conn.commit()
|
|
70
81
|
|
|
71
|
-
if not os.environ.get(
|
|
82
|
+
if not os.environ.get("SOULEYEZ_MIGRATION_SILENT"):
|
|
72
83
|
print("Migration 027: Multi-SIEM persistence enabled")
|
|
73
84
|
|
|
74
85
|
|
|
@@ -76,7 +87,8 @@ def downgrade(conn):
|
|
|
76
87
|
"""Revert to single SIEM per engagement (lossy - keeps only first config per engagement)."""
|
|
77
88
|
cursor = conn.cursor()
|
|
78
89
|
|
|
79
|
-
cursor.execute(
|
|
90
|
+
cursor.execute(
|
|
91
|
+
"""
|
|
80
92
|
CREATE TABLE IF NOT EXISTS wazuh_config_old (
|
|
81
93
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
82
94
|
engagement_id INTEGER NOT NULL UNIQUE,
|
|
@@ -94,10 +106,12 @@ def downgrade(conn):
|
|
|
94
106
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
95
107
|
FOREIGN KEY (engagement_id) REFERENCES engagements(id) ON DELETE CASCADE
|
|
96
108
|
)
|
|
97
|
-
"""
|
|
109
|
+
"""
|
|
110
|
+
)
|
|
98
111
|
|
|
99
112
|
# Copy only first config per engagement
|
|
100
|
-
cursor.execute(
|
|
113
|
+
cursor.execute(
|
|
114
|
+
"""
|
|
101
115
|
INSERT OR IGNORE INTO wazuh_config_old (
|
|
102
116
|
engagement_id, api_url, api_user, api_password,
|
|
103
117
|
indexer_url, indexer_user, indexer_password, verify_ssl, enabled,
|
|
@@ -109,11 +123,14 @@ def downgrade(conn):
|
|
|
109
123
|
siem_type, config_json, created_at, updated_at
|
|
110
124
|
FROM wazuh_config
|
|
111
125
|
GROUP BY engagement_id
|
|
112
|
-
"""
|
|
126
|
+
"""
|
|
127
|
+
)
|
|
113
128
|
|
|
114
129
|
cursor.execute("DROP TABLE wazuh_config")
|
|
115
130
|
cursor.execute("ALTER TABLE wazuh_config_old RENAME TO wazuh_config")
|
|
116
|
-
cursor.execute(
|
|
131
|
+
cursor.execute(
|
|
132
|
+
"CREATE INDEX IF NOT EXISTS idx_wazuh_config_engagement ON wazuh_config(engagement_id)"
|
|
133
|
+
)
|
|
117
134
|
|
|
118
135
|
conn.commit()
|
|
119
136
|
print("Migration 027: Reverted to single SIEM per engagement")
|
|
@@ -36,32 +36,32 @@ from . import (
|
|
|
36
36
|
|
|
37
37
|
# Migration registry - maps version to module
|
|
38
38
|
MIGRATIONS_REGISTRY = {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
39
|
+
"001": _001_add_credential_enhancements,
|
|
40
|
+
"002": _002_add_status_tracking,
|
|
41
|
+
"003": _003_add_execution_log,
|
|
42
|
+
"005": _005_screenshots,
|
|
43
|
+
"006": _006_deliverables,
|
|
44
|
+
"007": _007_deliverable_templates,
|
|
45
|
+
"008": _008_add_nuclei_table,
|
|
46
|
+
"009": _009_add_cme_tables,
|
|
47
|
+
"010": _010_evidence_linking,
|
|
48
|
+
"011": _011_timeline_tracking,
|
|
49
|
+
"012": _012_team_collaboration,
|
|
50
|
+
"013": _013_add_host_tags,
|
|
51
|
+
"014": _014_exploit_attempts,
|
|
52
|
+
"015": _015_add_mac_os_fields,
|
|
53
|
+
"016": _016_add_domain_field,
|
|
54
|
+
"017": _017_msf_sessions,
|
|
55
|
+
"018": _018_add_osint_target,
|
|
56
|
+
"019": _019_add_engagement_type,
|
|
57
|
+
"020": _020_add_rbac,
|
|
58
|
+
"021": _021_wazuh_integration,
|
|
59
|
+
"022": _022_wazuh_indexer_columns,
|
|
60
|
+
"023": _023_fix_detection_results_fk,
|
|
61
|
+
"024": _024_wazuh_vulnerabilities,
|
|
62
|
+
"025": _025_multi_siem_support,
|
|
63
|
+
"026": _026_add_engagement_scope,
|
|
64
|
+
"027": _027_multi_siem_persistence,
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
|
|
@@ -20,14 +20,16 @@ class MigrationManager:
|
|
|
20
20
|
def _ensure_migrations_table(self):
|
|
21
21
|
"""Create migrations tracking table if it doesn't exist."""
|
|
22
22
|
conn = sqlite3.connect(self.db_path)
|
|
23
|
-
conn.execute(
|
|
23
|
+
conn.execute(
|
|
24
|
+
"""
|
|
24
25
|
CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
25
26
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
26
27
|
version TEXT UNIQUE NOT NULL,
|
|
27
28
|
name TEXT NOT NULL,
|
|
28
29
|
applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
29
30
|
)
|
|
30
|
-
"""
|
|
31
|
+
"""
|
|
32
|
+
)
|
|
31
33
|
conn.commit()
|
|
32
34
|
conn.close()
|
|
33
35
|
|
|
@@ -48,12 +50,8 @@ class MigrationManager:
|
|
|
48
50
|
for version in get_all_versions():
|
|
49
51
|
if version not in applied:
|
|
50
52
|
module = MIGRATIONS_REGISTRY[version]
|
|
51
|
-
name = getattr(module,
|
|
52
|
-
pending.append({
|
|
53
|
-
'version': version,
|
|
54
|
-
'name': name,
|
|
55
|
-
'module': module
|
|
56
|
-
})
|
|
53
|
+
name = getattr(module, "DESCRIPTION", version)
|
|
54
|
+
pending.append({"version": version, "name": name, "module": module})
|
|
57
55
|
|
|
58
56
|
return pending
|
|
59
57
|
|
|
@@ -65,12 +63,13 @@ class MigrationManager:
|
|
|
65
63
|
try:
|
|
66
64
|
# Set environment variable for migration scripts to check
|
|
67
65
|
import os
|
|
68
|
-
|
|
66
|
+
|
|
67
|
+
old_silent = os.environ.get("SOULEYEZ_MIGRATION_SILENT")
|
|
69
68
|
if silent:
|
|
70
|
-
os.environ[
|
|
69
|
+
os.environ["SOULEYEZ_MIGRATION_SILENT"] = "1"
|
|
71
70
|
|
|
72
71
|
# Get migration module from registry (already imported)
|
|
73
|
-
migration_module = migration[
|
|
72
|
+
migration_module = migration["module"]
|
|
74
73
|
|
|
75
74
|
# Execute upgrade function
|
|
76
75
|
conn = sqlite3.connect(self.db_path)
|
|
@@ -79,7 +78,7 @@ class MigrationManager:
|
|
|
79
78
|
# Record migration
|
|
80
79
|
conn.execute(
|
|
81
80
|
"INSERT INTO schema_migrations (version, name) VALUES (?, ?)",
|
|
82
|
-
(migration[
|
|
81
|
+
(migration["version"], migration["name"]),
|
|
83
82
|
)
|
|
84
83
|
conn.commit()
|
|
85
84
|
conn.close()
|
|
@@ -87,9 +86,9 @@ class MigrationManager:
|
|
|
87
86
|
# Restore environment variable
|
|
88
87
|
if silent:
|
|
89
88
|
if old_silent is None:
|
|
90
|
-
os.environ.pop(
|
|
89
|
+
os.environ.pop("SOULEYEZ_MIGRATION_SILENT", None)
|
|
91
90
|
else:
|
|
92
|
-
os.environ[
|
|
91
|
+
os.environ["SOULEYEZ_MIGRATION_SILENT"] = old_silent
|
|
93
92
|
|
|
94
93
|
if not silent:
|
|
95
94
|
print(f"[{migration['version']}] ✅ Successfully applied")
|
|
@@ -157,7 +156,7 @@ class MigrationManager:
|
|
|
157
156
|
continue
|
|
158
157
|
|
|
159
158
|
# Check if downgrade function exists
|
|
160
|
-
if not hasattr(migration_module,
|
|
159
|
+
if not hasattr(migration_module, "downgrade"):
|
|
161
160
|
print(f"[{version}] ❌ No downgrade() function found")
|
|
162
161
|
continue
|
|
163
162
|
|
|
@@ -167,8 +166,7 @@ class MigrationManager:
|
|
|
167
166
|
|
|
168
167
|
# Remove from migrations table
|
|
169
168
|
conn.execute(
|
|
170
|
-
"DELETE FROM schema_migrations WHERE version = ?",
|
|
171
|
-
(version,)
|
|
169
|
+
"DELETE FROM schema_migrations WHERE version = ?", (version,)
|
|
172
170
|
)
|
|
173
171
|
conn.commit()
|
|
174
172
|
conn.close()
|
|
@@ -201,11 +199,13 @@ class MigrationManager:
|
|
|
201
199
|
if applied:
|
|
202
200
|
print("✅ Applied:")
|
|
203
201
|
conn = sqlite3.connect(self.db_path)
|
|
204
|
-
cursor = conn.execute(
|
|
202
|
+
cursor = conn.execute(
|
|
203
|
+
"""
|
|
205
204
|
SELECT version, name, applied_at
|
|
206
205
|
FROM schema_migrations
|
|
207
206
|
ORDER BY version
|
|
208
|
-
"""
|
|
207
|
+
"""
|
|
208
|
+
)
|
|
209
209
|
for row in cursor.fetchall():
|
|
210
210
|
print(f" [{row[0]}] {row[1]} (applied: {row[2]})")
|
|
211
211
|
conn.close()
|
souleyez/storage/msf_sessions.py
CHANGED
|
@@ -25,7 +25,7 @@ def add_msf_session(
|
|
|
25
25
|
port: Optional[int] = None,
|
|
26
26
|
tunnel_peer: Optional[str] = None,
|
|
27
27
|
opened_at: Optional[datetime] = None,
|
|
28
|
-
notes: Optional[str] = None
|
|
28
|
+
notes: Optional[str] = None,
|
|
29
29
|
) -> int:
|
|
30
30
|
"""
|
|
31
31
|
Add or update MSF session record
|
|
@@ -52,16 +52,20 @@ def add_msf_session(
|
|
|
52
52
|
cursor = db.cursor()
|
|
53
53
|
|
|
54
54
|
# Check if session already exists
|
|
55
|
-
cursor.execute(
|
|
55
|
+
cursor.execute(
|
|
56
|
+
"""
|
|
56
57
|
SELECT id FROM msf_sessions
|
|
57
58
|
WHERE engagement_id = ? AND msf_session_id = ?
|
|
58
|
-
""",
|
|
59
|
+
""",
|
|
60
|
+
(engagement_id, msf_session_id),
|
|
61
|
+
)
|
|
59
62
|
|
|
60
63
|
existing = cursor.fetchone()
|
|
61
64
|
|
|
62
65
|
if existing:
|
|
63
66
|
# Update existing session
|
|
64
|
-
cursor.execute(
|
|
67
|
+
cursor.execute(
|
|
68
|
+
"""
|
|
65
69
|
UPDATE msf_sessions
|
|
66
70
|
SET session_type = ?,
|
|
67
71
|
via_exploit = ?,
|
|
@@ -76,34 +80,54 @@ def add_msf_session(
|
|
|
76
80
|
is_active = 1,
|
|
77
81
|
updated_at = CURRENT_TIMESTAMP
|
|
78
82
|
WHERE id = ?
|
|
79
|
-
""",
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
+
""",
|
|
84
|
+
(
|
|
85
|
+
session_type,
|
|
86
|
+
via_exploit,
|
|
87
|
+
via_payload,
|
|
88
|
+
platform,
|
|
89
|
+
arch,
|
|
90
|
+
username,
|
|
91
|
+
port,
|
|
92
|
+
tunnel_peer,
|
|
93
|
+
opened_at,
|
|
94
|
+
notes,
|
|
95
|
+
existing[0],
|
|
96
|
+
),
|
|
97
|
+
)
|
|
83
98
|
return existing[0]
|
|
84
99
|
else:
|
|
85
100
|
# Insert new session
|
|
86
|
-
cursor.execute(
|
|
101
|
+
cursor.execute(
|
|
102
|
+
"""
|
|
87
103
|
INSERT INTO msf_sessions (
|
|
88
104
|
engagement_id, host_id, msf_session_id,
|
|
89
105
|
session_type, via_exploit, via_payload,
|
|
90
106
|
platform, arch, username, port,
|
|
91
107
|
tunnel_peer, opened_at, notes, is_active
|
|
92
108
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1)
|
|
93
|
-
""",
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
109
|
+
""",
|
|
110
|
+
(
|
|
111
|
+
engagement_id,
|
|
112
|
+
host_id,
|
|
113
|
+
msf_session_id,
|
|
114
|
+
session_type,
|
|
115
|
+
via_exploit,
|
|
116
|
+
via_payload,
|
|
117
|
+
platform,
|
|
118
|
+
arch,
|
|
119
|
+
username,
|
|
120
|
+
port,
|
|
121
|
+
tunnel_peer,
|
|
122
|
+
opened_at,
|
|
123
|
+
notes,
|
|
124
|
+
),
|
|
125
|
+
)
|
|
99
126
|
return cursor.lastrowid
|
|
100
127
|
|
|
101
128
|
|
|
102
129
|
def close_msf_session(
|
|
103
|
-
db,
|
|
104
|
-
engagement_id: int,
|
|
105
|
-
msf_session_id: int,
|
|
106
|
-
close_reason: Optional[str] = None
|
|
130
|
+
db, engagement_id: int, msf_session_id: int, close_reason: Optional[str] = None
|
|
107
131
|
) -> bool:
|
|
108
132
|
"""
|
|
109
133
|
Mark MSF session as closed
|
|
@@ -119,23 +143,23 @@ def close_msf_session(
|
|
|
119
143
|
"""
|
|
120
144
|
cursor = db.cursor()
|
|
121
145
|
|
|
122
|
-
cursor.execute(
|
|
146
|
+
cursor.execute(
|
|
147
|
+
"""
|
|
123
148
|
UPDATE msf_sessions
|
|
124
149
|
SET is_active = 0,
|
|
125
150
|
closed_at = CURRENT_TIMESTAMP,
|
|
126
151
|
close_reason = ?,
|
|
127
152
|
updated_at = CURRENT_TIMESTAMP
|
|
128
153
|
WHERE engagement_id = ? AND msf_session_id = ?
|
|
129
|
-
""",
|
|
154
|
+
""",
|
|
155
|
+
(close_reason, engagement_id, msf_session_id),
|
|
156
|
+
)
|
|
130
157
|
|
|
131
158
|
return cursor.rowcount > 0
|
|
132
159
|
|
|
133
160
|
|
|
134
161
|
def get_msf_sessions(
|
|
135
|
-
db,
|
|
136
|
-
engagement_id: int,
|
|
137
|
-
active_only: bool = True,
|
|
138
|
-
host_id: Optional[int] = None
|
|
162
|
+
db, engagement_id: int, active_only: bool = True, host_id: Optional[int] = None
|
|
139
163
|
) -> List[Dict[str, Any]]:
|
|
140
164
|
"""
|
|
141
165
|
Get MSF sessions
|
|
@@ -178,9 +202,7 @@ def get_msf_sessions(
|
|
|
178
202
|
|
|
179
203
|
|
|
180
204
|
def get_msf_session_by_id(
|
|
181
|
-
db,
|
|
182
|
-
engagement_id: int,
|
|
183
|
-
msf_session_id: int
|
|
205
|
+
db, engagement_id: int, msf_session_id: int
|
|
184
206
|
) -> Optional[Dict[str, Any]]:
|
|
185
207
|
"""
|
|
186
208
|
Get MSF session by MSF session ID
|
|
@@ -195,7 +217,8 @@ def get_msf_session_by_id(
|
|
|
195
217
|
"""
|
|
196
218
|
cursor = db.cursor()
|
|
197
219
|
|
|
198
|
-
cursor.execute(
|
|
220
|
+
cursor.execute(
|
|
221
|
+
"""
|
|
199
222
|
SELECT
|
|
200
223
|
s.*,
|
|
201
224
|
h.ip_address as host_ip,
|
|
@@ -203,7 +226,9 @@ def get_msf_session_by_id(
|
|
|
203
226
|
FROM msf_sessions s
|
|
204
227
|
JOIN hosts h ON s.host_id = h.id
|
|
205
228
|
WHERE s.engagement_id = ? AND s.msf_session_id = ?
|
|
206
|
-
""",
|
|
229
|
+
""",
|
|
230
|
+
(engagement_id, msf_session_id),
|
|
231
|
+
)
|
|
207
232
|
|
|
208
233
|
row = cursor.fetchone()
|
|
209
234
|
if row:
|
|
@@ -212,11 +237,7 @@ def get_msf_session_by_id(
|
|
|
212
237
|
return None
|
|
213
238
|
|
|
214
239
|
|
|
215
|
-
def update_session_last_seen(
|
|
216
|
-
db,
|
|
217
|
-
engagement_id: int,
|
|
218
|
-
msf_session_id: int
|
|
219
|
-
) -> bool:
|
|
240
|
+
def update_session_last_seen(db, engagement_id: int, msf_session_id: int) -> bool:
|
|
220
241
|
"""
|
|
221
242
|
Update session last_seen timestamp
|
|
222
243
|
|
|
@@ -230,12 +251,15 @@ def update_session_last_seen(
|
|
|
230
251
|
"""
|
|
231
252
|
cursor = db.cursor()
|
|
232
253
|
|
|
233
|
-
cursor.execute(
|
|
254
|
+
cursor.execute(
|
|
255
|
+
"""
|
|
234
256
|
UPDATE msf_sessions
|
|
235
257
|
SET last_seen = CURRENT_TIMESTAMP,
|
|
236
258
|
updated_at = CURRENT_TIMESTAMP
|
|
237
259
|
WHERE engagement_id = ? AND msf_session_id = ?
|
|
238
|
-
""",
|
|
260
|
+
""",
|
|
261
|
+
(engagement_id, msf_session_id),
|
|
262
|
+
)
|
|
239
263
|
|
|
240
264
|
return cursor.rowcount > 0
|
|
241
265
|
|
|
@@ -254,71 +278,79 @@ def get_session_stats(db, engagement_id: int) -> Dict[str, Any]:
|
|
|
254
278
|
cursor = db.cursor()
|
|
255
279
|
|
|
256
280
|
stats = {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
281
|
+
"total": 0,
|
|
282
|
+
"active": 0,
|
|
283
|
+
"closed": 0,
|
|
284
|
+
"by_type": {},
|
|
285
|
+
"by_exploit": {},
|
|
286
|
+
"compromised_hosts": 0,
|
|
263
287
|
}
|
|
264
288
|
|
|
265
289
|
# Total and active sessions
|
|
266
|
-
cursor.execute(
|
|
290
|
+
cursor.execute(
|
|
291
|
+
"""
|
|
267
292
|
SELECT
|
|
268
293
|
COUNT(*) as total,
|
|
269
294
|
SUM(CASE WHEN is_active = 1 THEN 1 ELSE 0 END) as active
|
|
270
295
|
FROM msf_sessions
|
|
271
296
|
WHERE engagement_id = ?
|
|
272
|
-
""",
|
|
297
|
+
""",
|
|
298
|
+
(engagement_id,),
|
|
299
|
+
)
|
|
273
300
|
|
|
274
301
|
row = cursor.fetchone()
|
|
275
302
|
if row:
|
|
276
|
-
stats[
|
|
277
|
-
stats[
|
|
278
|
-
stats[
|
|
303
|
+
stats["total"] = row[0] or 0
|
|
304
|
+
stats["active"] = row[1] or 0
|
|
305
|
+
stats["closed"] = stats["total"] - stats["active"]
|
|
279
306
|
|
|
280
307
|
# Sessions by type
|
|
281
|
-
cursor.execute(
|
|
308
|
+
cursor.execute(
|
|
309
|
+
"""
|
|
282
310
|
SELECT session_type, COUNT(*) as count
|
|
283
311
|
FROM msf_sessions
|
|
284
312
|
WHERE engagement_id = ?
|
|
285
313
|
GROUP BY session_type
|
|
286
|
-
""",
|
|
314
|
+
""",
|
|
315
|
+
(engagement_id,),
|
|
316
|
+
)
|
|
287
317
|
|
|
288
318
|
for row in cursor.fetchall():
|
|
289
|
-
session_type = row[0] or
|
|
290
|
-
stats[
|
|
319
|
+
session_type = row[0] or "unknown"
|
|
320
|
+
stats["by_type"][session_type] = row[1]
|
|
291
321
|
|
|
292
322
|
# Sessions by exploit
|
|
293
|
-
cursor.execute(
|
|
323
|
+
cursor.execute(
|
|
324
|
+
"""
|
|
294
325
|
SELECT via_exploit, COUNT(*) as count
|
|
295
326
|
FROM msf_sessions
|
|
296
327
|
WHERE engagement_id = ? AND via_exploit IS NOT NULL
|
|
297
328
|
GROUP BY via_exploit
|
|
298
|
-
""",
|
|
329
|
+
""",
|
|
330
|
+
(engagement_id,),
|
|
331
|
+
)
|
|
299
332
|
|
|
300
333
|
for row in cursor.fetchall():
|
|
301
|
-
stats[
|
|
334
|
+
stats["by_exploit"][row[0]] = row[1]
|
|
302
335
|
|
|
303
336
|
# Compromised hosts (hosts with active sessions)
|
|
304
|
-
cursor.execute(
|
|
337
|
+
cursor.execute(
|
|
338
|
+
"""
|
|
305
339
|
SELECT COUNT(DISTINCT host_id)
|
|
306
340
|
FROM msf_sessions
|
|
307
341
|
WHERE engagement_id = ? AND is_active = 1
|
|
308
|
-
""",
|
|
342
|
+
""",
|
|
343
|
+
(engagement_id,),
|
|
344
|
+
)
|
|
309
345
|
|
|
310
346
|
row = cursor.fetchone()
|
|
311
347
|
if row:
|
|
312
|
-
stats[
|
|
348
|
+
stats["compromised_hosts"] = row[0] or 0
|
|
313
349
|
|
|
314
350
|
return stats
|
|
315
351
|
|
|
316
352
|
|
|
317
|
-
def delete_msf_session(
|
|
318
|
-
db,
|
|
319
|
-
engagement_id: int,
|
|
320
|
-
msf_session_id: int
|
|
321
|
-
) -> bool:
|
|
353
|
+
def delete_msf_session(db, engagement_id: int, msf_session_id: int) -> bool:
|
|
322
354
|
"""
|
|
323
355
|
Delete MSF session record
|
|
324
356
|
|
|
@@ -332,9 +364,12 @@ def delete_msf_session(
|
|
|
332
364
|
"""
|
|
333
365
|
cursor = db.cursor()
|
|
334
366
|
|
|
335
|
-
cursor.execute(
|
|
367
|
+
cursor.execute(
|
|
368
|
+
"""
|
|
336
369
|
DELETE FROM msf_sessions
|
|
337
370
|
WHERE engagement_id = ? AND msf_session_id = ?
|
|
338
|
-
""",
|
|
371
|
+
""",
|
|
372
|
+
(engagement_id, msf_session_id),
|
|
373
|
+
)
|
|
339
374
|
|
|
340
375
|
return cursor.rowcount > 0
|