souleyez 2.43.29__py3-none-any.whl → 2.43.34__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 +9526 -2879
- 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 +563 -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 +408 -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 +371 -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 +854 -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 +173 -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 +223 -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 +22827 -10678
- 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-2.43.34.dist-info}/METADATA +1 -1
- souleyez-2.43.34.dist-info/RECORD +443 -0
- {souleyez-2.43.29.dist-info → souleyez-2.43.34.dist-info}/WHEEL +1 -1
- souleyez-2.43.29.dist-info/RECORD +0 -379
- {souleyez-2.43.29.dist-info → souleyez-2.43.34.dist-info}/entry_points.txt +0 -0
- {souleyez-2.43.29.dist-info → souleyez-2.43.34.dist-info}/licenses/LICENSE +0 -0
- {souleyez-2.43.29.dist-info → souleyez-2.43.34.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Deliverable templates management.
|
|
3
3
|
"""
|
|
4
|
+
|
|
4
5
|
from typing import List, Dict, Optional
|
|
5
6
|
import json
|
|
6
7
|
import os
|
|
@@ -9,93 +10,97 @@ from .database import get_db
|
|
|
9
10
|
|
|
10
11
|
class TemplateManager:
|
|
11
12
|
"""Manage deliverable templates."""
|
|
12
|
-
|
|
13
|
+
|
|
13
14
|
def __init__(self):
|
|
14
15
|
self.db = get_db()
|
|
15
16
|
self._ensure_builtin_templates()
|
|
16
|
-
|
|
17
|
+
|
|
17
18
|
def _ensure_builtin_templates(self):
|
|
18
19
|
"""Load built-in templates from JSON files if not already loaded."""
|
|
19
20
|
# Get list of existing builtin template names
|
|
20
21
|
existing = self.db.execute(
|
|
21
22
|
"SELECT name FROM deliverable_templates WHERE is_builtin = 1"
|
|
22
23
|
)
|
|
23
|
-
existing_names = {t[
|
|
24
|
-
|
|
24
|
+
existing_names = {t["name"] for t in existing} if existing else set()
|
|
25
|
+
|
|
25
26
|
# Load built-in templates from data/templates/
|
|
26
27
|
templates_dir = self._get_templates_dir()
|
|
27
|
-
|
|
28
|
+
|
|
28
29
|
builtin_templates = [
|
|
29
30
|
# Original templates
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
"pci_dss_4.0.json",
|
|
32
|
+
"owasp_top10_2021.json",
|
|
33
|
+
"hipaa_security.json",
|
|
34
|
+
"nist_csf.json",
|
|
34
35
|
# Compliance Frameworks
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
"soc2_type2.json",
|
|
37
|
+
"iso27001.json",
|
|
38
|
+
"cis_controls_v8.json",
|
|
39
|
+
"cmmc_2.0.json",
|
|
40
|
+
"gdpr_article32.json",
|
|
41
|
+
"glba_safeguards.json",
|
|
41
42
|
# Pentest Methodologies
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
"ptes_standard.json",
|
|
44
|
+
"internal_network.json",
|
|
45
|
+
"external_network.json",
|
|
46
|
+
"webapp_advanced.json",
|
|
47
|
+
"red_team.json",
|
|
48
|
+
"cloud_security.json",
|
|
49
|
+
"active_directory.json",
|
|
49
50
|
# Industry-Specific
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
"nerc_cip.json",
|
|
52
|
+
"hitrust_csf.json",
|
|
53
|
+
"ffiec_cat.json",
|
|
53
54
|
]
|
|
54
|
-
|
|
55
|
+
|
|
55
56
|
for template_file in builtin_templates:
|
|
56
57
|
template_path = os.path.join(templates_dir, template_file)
|
|
57
58
|
if os.path.exists(template_path):
|
|
58
59
|
try:
|
|
59
|
-
with open(template_path,
|
|
60
|
+
with open(template_path, "r") as f:
|
|
60
61
|
template_data = json.load(f)
|
|
61
62
|
|
|
62
63
|
# Skip if template already exists
|
|
63
|
-
if template_data[
|
|
64
|
+
if template_data["name"] in existing_names:
|
|
64
65
|
continue
|
|
65
66
|
|
|
66
67
|
self.create_template(
|
|
67
|
-
name=template_data[
|
|
68
|
-
description=template_data.get(
|
|
69
|
-
framework=template_data.get(
|
|
70
|
-
engagement_type=template_data.get(
|
|
71
|
-
deliverables=template_data[
|
|
72
|
-
is_builtin=True
|
|
68
|
+
name=template_data["name"],
|
|
69
|
+
description=template_data.get("description"),
|
|
70
|
+
framework=template_data.get("framework"),
|
|
71
|
+
engagement_type=template_data.get("engagement_type"),
|
|
72
|
+
deliverables=template_data["deliverables"],
|
|
73
|
+
is_builtin=True,
|
|
73
74
|
)
|
|
74
75
|
except Exception as e:
|
|
75
76
|
print(f"⚠️ Failed to load template {template_file}: {e}")
|
|
76
|
-
|
|
77
|
+
|
|
77
78
|
def _get_templates_dir(self) -> str:
|
|
78
79
|
"""Get path to templates directory across all installation types."""
|
|
79
80
|
import sys
|
|
80
81
|
from pathlib import Path
|
|
81
82
|
|
|
82
83
|
# Check environment variable first
|
|
83
|
-
env_root = os.environ.get(
|
|
84
|
+
env_root = os.environ.get("SOULEYEZ_ROOT")
|
|
84
85
|
if env_root:
|
|
85
|
-
env_path = os.path.join(env_root,
|
|
86
|
+
env_path = os.path.join(env_root, "data", "templates")
|
|
86
87
|
if os.path.isdir(env_path):
|
|
87
88
|
return env_path
|
|
88
89
|
|
|
89
90
|
# Possible locations in priority order
|
|
90
91
|
possible_paths = [
|
|
91
92
|
# Package bundled: souleyez/data/templates/
|
|
92
|
-
os.path.join(
|
|
93
|
+
os.path.join(
|
|
94
|
+
os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
|
|
95
|
+
"data",
|
|
96
|
+
"templates",
|
|
97
|
+
),
|
|
93
98
|
# Debian package install
|
|
94
|
-
|
|
99
|
+
"/usr/share/souleyez/templates",
|
|
95
100
|
# User local install
|
|
96
|
-
os.path.expanduser(
|
|
101
|
+
os.path.expanduser("~/.local/share/souleyez/templates"),
|
|
97
102
|
# System-wide pip install
|
|
98
|
-
os.path.join(sys.prefix,
|
|
103
|
+
os.path.join(sys.prefix, "share", "souleyez", "templates"),
|
|
99
104
|
]
|
|
100
105
|
|
|
101
106
|
for path in possible_paths:
|
|
@@ -104,7 +109,7 @@ class TemplateManager:
|
|
|
104
109
|
|
|
105
110
|
# Fallback to development path (may not exist)
|
|
106
111
|
return possible_paths[0]
|
|
107
|
-
|
|
112
|
+
|
|
108
113
|
def create_template(
|
|
109
114
|
self,
|
|
110
115
|
name: str,
|
|
@@ -113,66 +118,68 @@ class TemplateManager:
|
|
|
113
118
|
framework: str = None,
|
|
114
119
|
engagement_type: str = None,
|
|
115
120
|
created_by: str = None,
|
|
116
|
-
is_builtin: bool = False
|
|
121
|
+
is_builtin: bool = False,
|
|
117
122
|
) -> int:
|
|
118
123
|
"""Create a new deliverable template."""
|
|
119
124
|
deliverables_json = json.dumps(deliverables)
|
|
120
|
-
|
|
121
|
-
template_id = self.db.insert(
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
125
|
+
|
|
126
|
+
template_id = self.db.insert(
|
|
127
|
+
"deliverable_templates",
|
|
128
|
+
{
|
|
129
|
+
"name": name,
|
|
130
|
+
"description": description,
|
|
131
|
+
"framework": framework,
|
|
132
|
+
"engagement_type": engagement_type,
|
|
133
|
+
"deliverables_json": deliverables_json,
|
|
134
|
+
"created_by": created_by,
|
|
135
|
+
"is_builtin": 1 if is_builtin else 0,
|
|
136
|
+
},
|
|
137
|
+
)
|
|
138
|
+
|
|
131
139
|
return template_id
|
|
132
|
-
|
|
140
|
+
|
|
133
141
|
def get_template(self, template_id: int) -> Optional[Dict]:
|
|
134
142
|
"""Get template by ID."""
|
|
135
143
|
template = self.db.execute_one(
|
|
136
|
-
"SELECT * FROM deliverable_templates WHERE id = ?",
|
|
137
|
-
(template_id,)
|
|
144
|
+
"SELECT * FROM deliverable_templates WHERE id = ?", (template_id,)
|
|
138
145
|
)
|
|
139
|
-
|
|
146
|
+
|
|
140
147
|
if template:
|
|
141
|
-
template[
|
|
142
|
-
|
|
148
|
+
template["deliverables"] = json.loads(template["deliverables_json"])
|
|
149
|
+
|
|
143
150
|
return template
|
|
144
|
-
|
|
151
|
+
|
|
145
152
|
def list_templates(
|
|
146
153
|
self,
|
|
147
154
|
framework: str = None,
|
|
148
155
|
engagement_type: str = None,
|
|
149
|
-
include_custom: bool = True
|
|
156
|
+
include_custom: bool = True,
|
|
150
157
|
) -> List[Dict]:
|
|
151
158
|
"""List available templates."""
|
|
152
159
|
query = "SELECT * FROM deliverable_templates WHERE 1=1"
|
|
153
160
|
params = []
|
|
154
|
-
|
|
161
|
+
|
|
155
162
|
if framework:
|
|
156
163
|
query += " AND framework = ?"
|
|
157
164
|
params.append(framework)
|
|
158
|
-
|
|
165
|
+
|
|
159
166
|
if engagement_type:
|
|
160
167
|
query += " AND engagement_type = ?"
|
|
161
168
|
params.append(engagement_type)
|
|
162
|
-
|
|
169
|
+
|
|
163
170
|
if not include_custom:
|
|
164
171
|
query += " AND is_builtin = 1"
|
|
165
|
-
|
|
172
|
+
|
|
166
173
|
query += " ORDER BY is_builtin DESC, name ASC"
|
|
167
|
-
|
|
174
|
+
|
|
168
175
|
templates = self.db.execute(query, tuple(params))
|
|
169
|
-
|
|
176
|
+
|
|
170
177
|
# Parse deliverables JSON for each
|
|
171
178
|
for template in templates:
|
|
172
|
-
template[
|
|
173
|
-
|
|
179
|
+
template["deliverables"] = json.loads(template["deliverables_json"])
|
|
180
|
+
|
|
174
181
|
return templates
|
|
175
|
-
|
|
182
|
+
|
|
176
183
|
def apply_template(self, template_id: int, engagement_id: int) -> int:
|
|
177
184
|
"""Apply a template to an engagement."""
|
|
178
185
|
template = self.get_template(template_id)
|
|
@@ -180,12 +187,13 @@ class TemplateManager:
|
|
|
180
187
|
raise ValueError(f"Template {template_id} not found")
|
|
181
188
|
|
|
182
189
|
from .deliverables import DeliverableManager
|
|
190
|
+
|
|
183
191
|
dm = DeliverableManager()
|
|
184
192
|
|
|
185
193
|
count = 0
|
|
186
|
-
for deliverable_config in template[
|
|
194
|
+
for deliverable_config in template["deliverables"]:
|
|
187
195
|
# Inject engagement_id into validation queries
|
|
188
|
-
validation_query = deliverable_config.get(
|
|
196
|
+
validation_query = deliverable_config.get("validation_query")
|
|
189
197
|
if validation_query:
|
|
190
198
|
validation_query = self._inject_engagement_filter(
|
|
191
199
|
validation_query, engagement_id
|
|
@@ -193,14 +201,14 @@ class TemplateManager:
|
|
|
193
201
|
|
|
194
202
|
dm.add_deliverable(
|
|
195
203
|
engagement_id=engagement_id,
|
|
196
|
-
category=deliverable_config[
|
|
197
|
-
title=deliverable_config[
|
|
198
|
-
description=deliverable_config.get(
|
|
199
|
-
target_type=deliverable_config.get(
|
|
200
|
-
target_value=deliverable_config.get(
|
|
201
|
-
auto_validate=deliverable_config.get(
|
|
204
|
+
category=deliverable_config["category"],
|
|
205
|
+
title=deliverable_config["title"],
|
|
206
|
+
description=deliverable_config.get("description"),
|
|
207
|
+
target_type=deliverable_config.get("target_type", "manual"),
|
|
208
|
+
target_value=deliverable_config.get("target_value"),
|
|
209
|
+
auto_validate=deliverable_config.get("auto_validate", False),
|
|
202
210
|
validation_query=validation_query,
|
|
203
|
-
priority=deliverable_config.get(
|
|
211
|
+
priority=deliverable_config.get("priority", "medium"),
|
|
204
212
|
)
|
|
205
213
|
count += 1
|
|
206
214
|
|
|
@@ -219,79 +227,89 @@ class TemplateManager:
|
|
|
219
227
|
query_lower = query.lower()
|
|
220
228
|
|
|
221
229
|
# For services table, need to join through hosts
|
|
222
|
-
if
|
|
230
|
+
if "from services" in query_lower and "join" not in query_lower:
|
|
223
231
|
# Replace "FROM services" with a JOIN to hosts
|
|
224
232
|
query = re.sub(
|
|
225
|
-
r
|
|
226
|
-
f
|
|
233
|
+
r"FROM\s+services\b",
|
|
234
|
+
f"FROM services s JOIN hosts h ON s.host_id = h.id",
|
|
227
235
|
query,
|
|
228
|
-
flags=re.IGNORECASE
|
|
236
|
+
flags=re.IGNORECASE,
|
|
229
237
|
)
|
|
230
238
|
# Add WHERE clause with engagement filter
|
|
231
|
-
if
|
|
239
|
+
if "where" in query_lower:
|
|
232
240
|
query = re.sub(
|
|
233
|
-
r
|
|
234
|
-
f
|
|
241
|
+
r"\bWHERE\b",
|
|
242
|
+
f"WHERE h.engagement_id = {engagement_id} AND",
|
|
235
243
|
query,
|
|
236
|
-
flags=re.IGNORECASE
|
|
244
|
+
flags=re.IGNORECASE,
|
|
237
245
|
)
|
|
238
246
|
else:
|
|
239
|
-
query += f
|
|
247
|
+
query += f" WHERE h.engagement_id = {engagement_id}"
|
|
240
248
|
# For tables with direct engagement_id column
|
|
241
|
-
elif any(
|
|
242
|
-
|
|
249
|
+
elif any(
|
|
250
|
+
table in query_lower
|
|
251
|
+
for table in [
|
|
252
|
+
"from hosts",
|
|
253
|
+
"from findings",
|
|
254
|
+
"from credentials",
|
|
255
|
+
"from osint_data",
|
|
256
|
+
]
|
|
257
|
+
):
|
|
258
|
+
if "where" in query_lower:
|
|
243
259
|
query = re.sub(
|
|
244
|
-
r
|
|
245
|
-
f
|
|
260
|
+
r"\bWHERE\b",
|
|
261
|
+
f"WHERE engagement_id = {engagement_id} AND",
|
|
246
262
|
query,
|
|
247
|
-
flags=re.IGNORECASE
|
|
263
|
+
flags=re.IGNORECASE,
|
|
248
264
|
)
|
|
249
265
|
else:
|
|
250
|
-
query += f
|
|
266
|
+
query += f" WHERE engagement_id = {engagement_id}"
|
|
251
267
|
|
|
252
268
|
return query
|
|
253
|
-
|
|
269
|
+
|
|
254
270
|
def delete_template(self, template_id: int) -> bool:
|
|
255
271
|
"""Delete a custom template (cannot delete built-in)."""
|
|
256
272
|
template = self.get_template(template_id)
|
|
257
273
|
if not template:
|
|
258
274
|
return False
|
|
259
|
-
|
|
260
|
-
if template[
|
|
275
|
+
|
|
276
|
+
if template["is_builtin"]:
|
|
261
277
|
raise ValueError("Cannot delete built-in templates")
|
|
262
|
-
|
|
263
|
-
self.db.execute(
|
|
278
|
+
|
|
279
|
+
self.db.execute(
|
|
280
|
+
"DELETE FROM deliverable_templates WHERE id = ?", (template_id,)
|
|
281
|
+
)
|
|
264
282
|
return True
|
|
265
|
-
|
|
283
|
+
|
|
266
284
|
def export_template(self, template_id: int) -> str:
|
|
267
285
|
"""Export template as JSON string."""
|
|
268
286
|
template = self.get_template(template_id)
|
|
269
287
|
if not template:
|
|
270
288
|
raise ValueError(f"Template {template_id} not found")
|
|
271
|
-
|
|
289
|
+
|
|
272
290
|
export_data = {
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
291
|
+
"name": template["name"],
|
|
292
|
+
"description": template["description"],
|
|
293
|
+
"framework": template["framework"],
|
|
294
|
+
"engagement_type": template["engagement_type"],
|
|
295
|
+
"deliverables": template["deliverables"],
|
|
278
296
|
}
|
|
279
|
-
|
|
297
|
+
|
|
280
298
|
return json.dumps(export_data, indent=2)
|
|
281
|
-
|
|
299
|
+
|
|
282
300
|
def import_template(self, json_data: str, created_by: str = None) -> int:
|
|
283
301
|
"""Import template from JSON string."""
|
|
284
302
|
try:
|
|
285
303
|
template_data = json.loads(json_data)
|
|
286
|
-
|
|
304
|
+
|
|
287
305
|
return self.create_template(
|
|
288
|
-
name=template_data[
|
|
289
|
-
description=template_data.get(
|
|
290
|
-
framework=template_data.get(
|
|
291
|
-
engagement_type=template_data.get(
|
|
292
|
-
deliverables=template_data[
|
|
306
|
+
name=template_data["name"],
|
|
307
|
+
description=template_data.get("description"),
|
|
308
|
+
framework=template_data.get("framework"),
|
|
309
|
+
engagement_type=template_data.get("engagement_type"),
|
|
310
|
+
deliverables=template_data["deliverables"],
|
|
293
311
|
created_by=created_by,
|
|
294
|
-
is_builtin=False
|
|
312
|
+
is_builtin=False,
|
|
295
313
|
)
|
|
296
314
|
except Exception as e:
|
|
297
315
|
raise ValueError(f"Failed to import template: {e}")
|