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/screenshots.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Screenshot management for visual evidence collection.
|
|
3
3
|
"""
|
|
4
|
+
|
|
4
5
|
import os
|
|
5
6
|
import shutil
|
|
6
7
|
import time
|
|
@@ -31,7 +32,7 @@ class ScreenshotManager:
|
|
|
31
32
|
description: str = None,
|
|
32
33
|
host_id: int = None,
|
|
33
34
|
finding_id: int = None,
|
|
34
|
-
job_id: int = None
|
|
35
|
+
job_id: int = None,
|
|
35
36
|
) -> int:
|
|
36
37
|
"""
|
|
37
38
|
Add a screenshot to the engagement.
|
|
@@ -63,18 +64,21 @@ class ScreenshotManager:
|
|
|
63
64
|
shutil.copy2(source, dest_path)
|
|
64
65
|
os.chmod(dest_path, 0o600)
|
|
65
66
|
|
|
66
|
-
screenshot_id = self.db.insert(
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
67
|
+
screenshot_id = self.db.insert(
|
|
68
|
+
"screenshots",
|
|
69
|
+
{
|
|
70
|
+
"engagement_id": engagement_id,
|
|
71
|
+
"host_id": host_id,
|
|
72
|
+
"finding_id": finding_id,
|
|
73
|
+
"job_id": job_id,
|
|
74
|
+
"filename": filename,
|
|
75
|
+
"filepath": str(dest_path),
|
|
76
|
+
"title": title or source.name,
|
|
77
|
+
"description": description,
|
|
78
|
+
"file_size": file_size,
|
|
79
|
+
"mime_type": mime_type,
|
|
80
|
+
},
|
|
81
|
+
)
|
|
78
82
|
|
|
79
83
|
return screenshot_id
|
|
80
84
|
|
|
@@ -83,7 +87,7 @@ class ScreenshotManager:
|
|
|
83
87
|
engagement_id: int,
|
|
84
88
|
host_id: int = None,
|
|
85
89
|
finding_id: int = None,
|
|
86
|
-
job_id: int = None
|
|
90
|
+
job_id: int = None,
|
|
87
91
|
) -> List[Dict]:
|
|
88
92
|
"""
|
|
89
93
|
List screenshots for engagement.
|
|
@@ -119,8 +123,7 @@ class ScreenshotManager:
|
|
|
119
123
|
def get_screenshot(self, screenshot_id: int) -> Optional[Dict]:
|
|
120
124
|
"""Get screenshot by ID."""
|
|
121
125
|
return self.db.execute_one(
|
|
122
|
-
"SELECT * FROM screenshots WHERE id = ?",
|
|
123
|
-
(screenshot_id,)
|
|
126
|
+
"SELECT * FROM screenshots WHERE id = ?", (screenshot_id,)
|
|
124
127
|
)
|
|
125
128
|
|
|
126
129
|
def delete_screenshot(self, screenshot_id: int) -> bool:
|
|
@@ -129,7 +132,7 @@ class ScreenshotManager:
|
|
|
129
132
|
if not screenshot:
|
|
130
133
|
return False
|
|
131
134
|
|
|
132
|
-
filepath = Path(screenshot[
|
|
135
|
+
filepath = Path(screenshot["filepath"])
|
|
133
136
|
if filepath.exists():
|
|
134
137
|
filepath.unlink()
|
|
135
138
|
|
|
@@ -140,23 +143,21 @@ class ScreenshotManager:
|
|
|
140
143
|
"""Link screenshot to a finding."""
|
|
141
144
|
self.db.execute(
|
|
142
145
|
"UPDATE screenshots SET finding_id = ? WHERE id = ?",
|
|
143
|
-
(finding_id, screenshot_id)
|
|
146
|
+
(finding_id, screenshot_id),
|
|
144
147
|
)
|
|
145
148
|
return True
|
|
146
149
|
|
|
147
150
|
def link_to_job(self, screenshot_id: int, job_id: int) -> bool:
|
|
148
151
|
"""Link screenshot to a job."""
|
|
149
152
|
self.db.execute(
|
|
150
|
-
"UPDATE screenshots SET job_id = ? WHERE id = ?",
|
|
151
|
-
(job_id, screenshot_id)
|
|
153
|
+
"UPDATE screenshots SET job_id = ? WHERE id = ?", (job_id, screenshot_id)
|
|
152
154
|
)
|
|
153
155
|
return True
|
|
154
156
|
|
|
155
157
|
def link_to_host(self, screenshot_id: int, host_id: int) -> bool:
|
|
156
158
|
"""Link screenshot to a host."""
|
|
157
159
|
self.db.execute(
|
|
158
|
-
"UPDATE screenshots SET host_id = ? WHERE id = ?",
|
|
159
|
-
(host_id, screenshot_id)
|
|
160
|
+
"UPDATE screenshots SET host_id = ? WHERE id = ?", (host_id, screenshot_id)
|
|
160
161
|
)
|
|
161
162
|
return True
|
|
162
163
|
|
|
@@ -164,20 +165,20 @@ class ScreenshotManager:
|
|
|
164
165
|
"""Detect MIME type from file extension."""
|
|
165
166
|
ext = filepath.suffix.lower()
|
|
166
167
|
mime_types = {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
168
|
+
".png": "image/png",
|
|
169
|
+
".jpg": "image/jpeg",
|
|
170
|
+
".jpeg": "image/jpeg",
|
|
171
|
+
".gif": "image/gif",
|
|
172
|
+
".bmp": "image/bmp",
|
|
173
|
+
".webp": "image/webp",
|
|
174
|
+
".svg": "image/svg+xml",
|
|
174
175
|
}
|
|
175
|
-
return mime_types.get(ext,
|
|
176
|
+
return mime_types.get(ext, "application/octet-stream")
|
|
176
177
|
|
|
177
178
|
def get_screenshot_count(self, engagement_id: int) -> int:
|
|
178
179
|
"""Get total screenshot count for engagement."""
|
|
179
180
|
result = self.db.execute_one(
|
|
180
181
|
"SELECT COUNT(*) as count FROM screenshots WHERE engagement_id = ?",
|
|
181
|
-
(engagement_id,)
|
|
182
|
+
(engagement_id,),
|
|
182
183
|
)
|
|
183
|
-
return result[
|
|
184
|
+
return result["count"] if result else 0
|
souleyez/storage/smb_shares.py
CHANGED
|
@@ -27,42 +27,48 @@ class SMBSharesManager:
|
|
|
27
27
|
# Check if share already exists
|
|
28
28
|
cursor.execute(
|
|
29
29
|
"SELECT id FROM smb_shares WHERE host_id = ? AND share_name = ?",
|
|
30
|
-
(host_id, share_data[
|
|
30
|
+
(host_id, share_data["name"]),
|
|
31
31
|
)
|
|
32
32
|
existing = cursor.fetchone()
|
|
33
33
|
|
|
34
34
|
if existing:
|
|
35
35
|
# Update existing
|
|
36
|
-
cursor.execute(
|
|
36
|
+
cursor.execute(
|
|
37
|
+
"""
|
|
37
38
|
UPDATE smb_shares
|
|
38
39
|
SET share_type = ?, permissions = ?, comment = ?,
|
|
39
40
|
readable = ?, writable = ?
|
|
40
41
|
WHERE id = ?
|
|
41
|
-
""",
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
42
|
+
""",
|
|
43
|
+
(
|
|
44
|
+
share_data.get("type", ""),
|
|
45
|
+
share_data.get("permissions", ""),
|
|
46
|
+
share_data.get("comment", ""),
|
|
47
|
+
1 if share_data.get("readable") else 0,
|
|
48
|
+
1 if share_data.get("writable") else 0,
|
|
49
|
+
existing[0],
|
|
50
|
+
),
|
|
51
|
+
)
|
|
49
52
|
conn.commit()
|
|
50
53
|
conn.close()
|
|
51
54
|
return existing[0]
|
|
52
55
|
else:
|
|
53
56
|
# Insert new
|
|
54
|
-
cursor.execute(
|
|
57
|
+
cursor.execute(
|
|
58
|
+
"""
|
|
55
59
|
INSERT INTO smb_shares (host_id, share_name, share_type, permissions, comment, readable, writable)
|
|
56
60
|
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
57
|
-
""",
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
61
|
+
""",
|
|
62
|
+
(
|
|
63
|
+
host_id,
|
|
64
|
+
share_data["name"],
|
|
65
|
+
share_data.get("type", ""),
|
|
66
|
+
share_data.get("permissions", ""),
|
|
67
|
+
share_data.get("comment", ""),
|
|
68
|
+
1 if share_data.get("readable") else 0,
|
|
69
|
+
1 if share_data.get("writable") else 0,
|
|
70
|
+
),
|
|
71
|
+
)
|
|
66
72
|
row_id = cursor.lastrowid
|
|
67
73
|
conn.commit()
|
|
68
74
|
conn.close()
|
|
@@ -86,43 +92,51 @@ class SMBSharesManager:
|
|
|
86
92
|
# Check if file already exists
|
|
87
93
|
cursor.execute(
|
|
88
94
|
"SELECT id FROM smb_files WHERE share_id = ? AND path = ?",
|
|
89
|
-
(share_id, file_data[
|
|
95
|
+
(share_id, file_data["path"]),
|
|
90
96
|
)
|
|
91
97
|
existing = cursor.fetchone()
|
|
92
98
|
|
|
93
99
|
if existing:
|
|
94
100
|
# Update existing
|
|
95
|
-
cursor.execute(
|
|
101
|
+
cursor.execute(
|
|
102
|
+
"""
|
|
96
103
|
UPDATE smb_files
|
|
97
104
|
SET size = ?, timestamp = ?, is_directory = ?
|
|
98
105
|
WHERE id = ?
|
|
99
|
-
""",
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
106
|
+
""",
|
|
107
|
+
(
|
|
108
|
+
file_data.get("size", 0),
|
|
109
|
+
file_data.get("timestamp", ""),
|
|
110
|
+
1 if file_data.get("is_directory") else 0,
|
|
111
|
+
existing[0],
|
|
112
|
+
),
|
|
113
|
+
)
|
|
105
114
|
conn.commit()
|
|
106
115
|
conn.close()
|
|
107
116
|
return existing[0]
|
|
108
117
|
else:
|
|
109
118
|
# Insert new
|
|
110
|
-
cursor.execute(
|
|
119
|
+
cursor.execute(
|
|
120
|
+
"""
|
|
111
121
|
INSERT INTO smb_files (share_id, path, size, timestamp, is_directory)
|
|
112
122
|
VALUES (?, ?, ?, ?, ?)
|
|
113
|
-
""",
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
123
|
+
""",
|
|
124
|
+
(
|
|
125
|
+
share_id,
|
|
126
|
+
file_data["path"],
|
|
127
|
+
file_data.get("size", 0),
|
|
128
|
+
file_data.get("timestamp", ""),
|
|
129
|
+
1 if file_data.get("is_directory") else 0,
|
|
130
|
+
),
|
|
131
|
+
)
|
|
120
132
|
row_id = cursor.lastrowid
|
|
121
133
|
conn.commit()
|
|
122
134
|
conn.close()
|
|
123
135
|
return row_id
|
|
124
136
|
|
|
125
|
-
def list_shares(
|
|
137
|
+
def list_shares(
|
|
138
|
+
self, engagement_id: int, host_id: Optional[int] = None
|
|
139
|
+
) -> List[Dict[str, Any]]:
|
|
126
140
|
"""
|
|
127
141
|
List all SMB shares for an engagement or specific host.
|
|
128
142
|
|
|
@@ -138,37 +152,45 @@ class SMBSharesManager:
|
|
|
138
152
|
cursor = conn.cursor()
|
|
139
153
|
|
|
140
154
|
if host_id:
|
|
141
|
-
cursor.execute(
|
|
155
|
+
cursor.execute(
|
|
156
|
+
"""
|
|
142
157
|
SELECT s.*, h.ip_address, h.hostname
|
|
143
158
|
FROM smb_shares s
|
|
144
159
|
JOIN hosts h ON s.host_id = h.id
|
|
145
160
|
WHERE h.engagement_id = ? AND s.host_id = ?
|
|
146
161
|
ORDER BY h.ip_address, s.share_name
|
|
147
|
-
""",
|
|
162
|
+
""",
|
|
163
|
+
(engagement_id, host_id),
|
|
164
|
+
)
|
|
148
165
|
else:
|
|
149
|
-
cursor.execute(
|
|
166
|
+
cursor.execute(
|
|
167
|
+
"""
|
|
150
168
|
SELECT s.*, h.ip_address, h.hostname
|
|
151
169
|
FROM smb_shares s
|
|
152
170
|
JOIN hosts h ON s.host_id = h.id
|
|
153
171
|
WHERE h.engagement_id = ?
|
|
154
172
|
ORDER BY h.ip_address, s.share_name
|
|
155
|
-
""",
|
|
173
|
+
""",
|
|
174
|
+
(engagement_id,),
|
|
175
|
+
)
|
|
156
176
|
|
|
157
177
|
shares = []
|
|
158
178
|
for row in cursor.fetchall():
|
|
159
|
-
shares.append(
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
179
|
+
shares.append(
|
|
180
|
+
{
|
|
181
|
+
"id": row[0],
|
|
182
|
+
"host_id": row[1],
|
|
183
|
+
"share_name": row[2],
|
|
184
|
+
"share_type": row[3],
|
|
185
|
+
"permissions": row[4],
|
|
186
|
+
"comment": row[5],
|
|
187
|
+
"readable": bool(row[6]),
|
|
188
|
+
"writable": bool(row[7]),
|
|
189
|
+
"created_at": row[8],
|
|
190
|
+
"ip_address": row[9],
|
|
191
|
+
"hostname": row[10],
|
|
192
|
+
}
|
|
193
|
+
)
|
|
172
194
|
|
|
173
195
|
conn.close()
|
|
174
196
|
return shares
|
|
@@ -187,24 +209,29 @@ class SMBSharesManager:
|
|
|
187
209
|
conn = db.get_connection()
|
|
188
210
|
cursor = conn.cursor()
|
|
189
211
|
|
|
190
|
-
cursor.execute(
|
|
212
|
+
cursor.execute(
|
|
213
|
+
"""
|
|
191
214
|
SELECT id, share_id, path, size, timestamp, is_directory, created_at
|
|
192
215
|
FROM smb_files
|
|
193
216
|
WHERE share_id = ?
|
|
194
217
|
ORDER BY is_directory DESC, path
|
|
195
|
-
""",
|
|
218
|
+
""",
|
|
219
|
+
(share_id,),
|
|
220
|
+
)
|
|
196
221
|
|
|
197
222
|
files = []
|
|
198
223
|
for row in cursor.fetchall():
|
|
199
|
-
files.append(
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
224
|
+
files.append(
|
|
225
|
+
{
|
|
226
|
+
"id": row[0],
|
|
227
|
+
"share_id": row[1],
|
|
228
|
+
"path": row[2],
|
|
229
|
+
"size": row[3],
|
|
230
|
+
"timestamp": row[4],
|
|
231
|
+
"is_directory": bool(row[5]),
|
|
232
|
+
"created_at": row[6],
|
|
233
|
+
}
|
|
234
|
+
)
|
|
208
235
|
|
|
209
236
|
conn.close()
|
|
210
237
|
return files
|
|
@@ -215,29 +242,34 @@ class SMBSharesManager:
|
|
|
215
242
|
conn = db.get_connection()
|
|
216
243
|
cursor = conn.cursor()
|
|
217
244
|
|
|
218
|
-
cursor.execute(
|
|
245
|
+
cursor.execute(
|
|
246
|
+
"""
|
|
219
247
|
SELECT s.*, h.ip_address, h.hostname
|
|
220
248
|
FROM smb_shares s
|
|
221
249
|
JOIN hosts h ON s.host_id = h.id
|
|
222
250
|
WHERE h.engagement_id = ? AND s.writable = 1
|
|
223
251
|
ORDER BY h.ip_address, s.share_name
|
|
224
|
-
""",
|
|
252
|
+
""",
|
|
253
|
+
(engagement_id,),
|
|
254
|
+
)
|
|
225
255
|
|
|
226
256
|
shares = []
|
|
227
257
|
for row in cursor.fetchall():
|
|
228
|
-
shares.append(
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
258
|
+
shares.append(
|
|
259
|
+
{
|
|
260
|
+
"id": row[0],
|
|
261
|
+
"host_id": row[1],
|
|
262
|
+
"share_name": row[2],
|
|
263
|
+
"share_type": row[3],
|
|
264
|
+
"permissions": row[4],
|
|
265
|
+
"comment": row[5],
|
|
266
|
+
"readable": bool(row[6]),
|
|
267
|
+
"writable": bool(row[7]),
|
|
268
|
+
"created_at": row[8],
|
|
269
|
+
"ip_address": row[9],
|
|
270
|
+
"hostname": row[10],
|
|
271
|
+
}
|
|
272
|
+
)
|
|
241
273
|
|
|
242
274
|
conn.close()
|
|
243
275
|
return shares
|
|
@@ -249,45 +281,57 @@ class SMBSharesManager:
|
|
|
249
281
|
cursor = conn.cursor()
|
|
250
282
|
|
|
251
283
|
# Count total shares
|
|
252
|
-
cursor.execute(
|
|
284
|
+
cursor.execute(
|
|
285
|
+
"""
|
|
253
286
|
SELECT COUNT(*)
|
|
254
287
|
FROM smb_shares s
|
|
255
288
|
JOIN hosts h ON s.host_id = h.id
|
|
256
289
|
WHERE h.engagement_id = ?
|
|
257
|
-
""",
|
|
290
|
+
""",
|
|
291
|
+
(engagement_id,),
|
|
292
|
+
)
|
|
258
293
|
total = cursor.fetchone()[0]
|
|
259
294
|
|
|
260
295
|
# Count writable shares
|
|
261
|
-
cursor.execute(
|
|
296
|
+
cursor.execute(
|
|
297
|
+
"""
|
|
262
298
|
SELECT COUNT(*)
|
|
263
299
|
FROM smb_shares s
|
|
264
300
|
JOIN hosts h ON s.host_id = h.id
|
|
265
301
|
WHERE h.engagement_id = ? AND s.writable = 1
|
|
266
|
-
""",
|
|
302
|
+
""",
|
|
303
|
+
(engagement_id,),
|
|
304
|
+
)
|
|
267
305
|
writable = cursor.fetchone()[0]
|
|
268
306
|
|
|
269
307
|
# Count readable shares
|
|
270
|
-
cursor.execute(
|
|
308
|
+
cursor.execute(
|
|
309
|
+
"""
|
|
271
310
|
SELECT COUNT(*)
|
|
272
311
|
FROM smb_shares s
|
|
273
312
|
JOIN hosts h ON s.host_id = h.id
|
|
274
313
|
WHERE h.engagement_id = ? AND s.readable = 1
|
|
275
|
-
""",
|
|
314
|
+
""",
|
|
315
|
+
(engagement_id,),
|
|
316
|
+
)
|
|
276
317
|
readable = cursor.fetchone()[0]
|
|
277
318
|
|
|
278
319
|
# Count hosts with SMB
|
|
279
|
-
cursor.execute(
|
|
320
|
+
cursor.execute(
|
|
321
|
+
"""
|
|
280
322
|
SELECT COUNT(DISTINCT s.host_id)
|
|
281
323
|
FROM smb_shares s
|
|
282
324
|
JOIN hosts h ON s.host_id = h.id
|
|
283
325
|
WHERE h.engagement_id = ?
|
|
284
|
-
""",
|
|
326
|
+
""",
|
|
327
|
+
(engagement_id,),
|
|
328
|
+
)
|
|
285
329
|
hosts_with_smb = cursor.fetchone()[0]
|
|
286
330
|
|
|
287
331
|
conn.close()
|
|
288
332
|
return {
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
333
|
+
"total_shares": total,
|
|
334
|
+
"writable": writable,
|
|
335
|
+
"readable": readable,
|
|
336
|
+
"hosts_with_smb": hosts_with_smb,
|
|
293
337
|
}
|