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
souleyez/core/templates.py
CHANGED
|
@@ -12,6 +12,7 @@ from typing import List, Dict, Any, Optional
|
|
|
12
12
|
@dataclass
|
|
13
13
|
class ScanPhase:
|
|
14
14
|
"""A phase in the recommended scan sequence."""
|
|
15
|
+
|
|
15
16
|
name: str
|
|
16
17
|
description: str
|
|
17
18
|
tools: List[str]
|
|
@@ -21,6 +22,7 @@ class ScanPhase:
|
|
|
21
22
|
@dataclass
|
|
22
23
|
class EngagementTemplate:
|
|
23
24
|
"""Workflow preset for a specific type of penetration test."""
|
|
25
|
+
|
|
24
26
|
id: str
|
|
25
27
|
name: str
|
|
26
28
|
description: str
|
|
@@ -58,170 +60,200 @@ TEMPLATES: Dict[str, EngagementTemplate] = {
|
|
|
58
60
|
description="Test web applications for OWASP Top 10 and common web vulnerabilities",
|
|
59
61
|
icon="[W]",
|
|
60
62
|
recommended_tools=[
|
|
61
|
-
"nmap",
|
|
62
|
-
"
|
|
63
|
+
"nmap",
|
|
64
|
+
"nikto",
|
|
65
|
+
"gobuster",
|
|
66
|
+
"feroxbuster",
|
|
67
|
+
"sqlmap",
|
|
68
|
+
"whatweb",
|
|
69
|
+
"wpscan",
|
|
70
|
+
"nuclei",
|
|
71
|
+
"ffuf",
|
|
72
|
+
"httpx",
|
|
63
73
|
],
|
|
64
74
|
scan_phases=[
|
|
65
75
|
ScanPhase(
|
|
66
76
|
name="Reconnaissance",
|
|
67
77
|
description="Discover services, technologies, and entry points",
|
|
68
|
-
tools=["nmap", "whatweb", "httpx"]
|
|
78
|
+
tools=["nmap", "whatweb", "httpx"],
|
|
69
79
|
),
|
|
70
80
|
ScanPhase(
|
|
71
81
|
name="Content Discovery",
|
|
72
82
|
description="Find hidden directories, files, and endpoints",
|
|
73
|
-
tools=["gobuster", "feroxbuster", "ffuf"]
|
|
83
|
+
tools=["gobuster", "feroxbuster", "ffuf"],
|
|
74
84
|
),
|
|
75
85
|
ScanPhase(
|
|
76
86
|
name="Vulnerability Scanning",
|
|
77
87
|
description="Identify known vulnerabilities and misconfigurations",
|
|
78
|
-
tools=["nikto", "nuclei", "wpscan"]
|
|
88
|
+
tools=["nikto", "nuclei", "wpscan"],
|
|
79
89
|
),
|
|
80
90
|
ScanPhase(
|
|
81
91
|
name="Exploitation Testing",
|
|
82
92
|
description="Test for injectable parameters and weaknesses",
|
|
83
|
-
tools=["sqlmap"]
|
|
84
|
-
)
|
|
93
|
+
tools=["sqlmap"],
|
|
94
|
+
),
|
|
85
95
|
],
|
|
86
96
|
wordlists={
|
|
87
97
|
"directories": "directory-list-2.3-medium.txt",
|
|
88
98
|
"files": "raft-large-files.txt",
|
|
89
|
-
"subdomains": "subdomains-top1million-5000.txt"
|
|
99
|
+
"subdomains": "subdomains-top1million-5000.txt",
|
|
90
100
|
},
|
|
91
101
|
common_findings=[
|
|
92
|
-
"SQL Injection",
|
|
93
|
-
"
|
|
94
|
-
"
|
|
95
|
-
"
|
|
102
|
+
"SQL Injection",
|
|
103
|
+
"Cross-Site Scripting (XSS)",
|
|
104
|
+
"CSRF",
|
|
105
|
+
"Insecure Direct Object Reference",
|
|
106
|
+
"Security Misconfiguration",
|
|
107
|
+
"Sensitive Data Exposure",
|
|
108
|
+
"Broken Authentication",
|
|
109
|
+
"Directory Listing Enabled",
|
|
110
|
+
"Information Disclosure",
|
|
96
111
|
],
|
|
97
112
|
tips=[
|
|
98
113
|
"Start with nmap to identify web ports (80, 443, 8080, 8443)",
|
|
99
114
|
"Use whatweb to fingerprint technologies before deeper scanning",
|
|
100
115
|
"Check robots.txt and sitemap.xml for hidden paths",
|
|
101
116
|
"Test both authenticated and unauthenticated access",
|
|
102
|
-
"Look for API endpoints (/api/, /v1/, /graphql)"
|
|
103
|
-
],
|
|
104
|
-
scope_examples=[
|
|
105
|
-
"https://example.com",
|
|
106
|
-
"app.example.com",
|
|
107
|
-
"192.168.1.100:8080"
|
|
117
|
+
"Look for API endpoints (/api/, /v1/, /graphql)",
|
|
108
118
|
],
|
|
119
|
+
scope_examples=["https://example.com", "app.example.com", "192.168.1.100:8080"],
|
|
109
120
|
initial_scan_tool="nmap",
|
|
110
121
|
initial_scan_args="-sV -sC -p 80,443,8080,8443",
|
|
111
|
-
initial_scan_description="Service scan on common web ports"
|
|
122
|
+
initial_scan_description="Service scan on common web ports",
|
|
112
123
|
),
|
|
113
|
-
|
|
114
124
|
"network": EngagementTemplate(
|
|
115
125
|
id="network",
|
|
116
126
|
name="Network Infrastructure",
|
|
117
127
|
description="Test network devices, services, and infrastructure security",
|
|
118
128
|
icon="[N]",
|
|
119
129
|
recommended_tools=[
|
|
120
|
-
"nmap",
|
|
121
|
-
"
|
|
130
|
+
"nmap",
|
|
131
|
+
"masscan",
|
|
132
|
+
"enum4linux-ng",
|
|
133
|
+
"smbclient",
|
|
134
|
+
"snmpwalk",
|
|
135
|
+
"nbtscan",
|
|
136
|
+
"onesixtyone",
|
|
137
|
+
"hydra",
|
|
138
|
+
"crackmapexec",
|
|
139
|
+
"rpcclient",
|
|
122
140
|
],
|
|
123
141
|
scan_phases=[
|
|
124
142
|
ScanPhase(
|
|
125
143
|
name="Host Discovery",
|
|
126
144
|
description="Identify live hosts on the network",
|
|
127
|
-
tools=["nmap", "masscan", "nbtscan"]
|
|
145
|
+
tools=["nmap", "masscan", "nbtscan"],
|
|
128
146
|
),
|
|
129
147
|
ScanPhase(
|
|
130
148
|
name="Port Scanning",
|
|
131
149
|
description="Enumerate open ports and services",
|
|
132
|
-
tools=["nmap", "masscan"]
|
|
150
|
+
tools=["nmap", "masscan"],
|
|
133
151
|
),
|
|
134
152
|
ScanPhase(
|
|
135
153
|
name="Service Enumeration",
|
|
136
154
|
description="Gather detailed information about services",
|
|
137
|
-
tools=["nmap", "enum4linux-ng", "snmpwalk", "onesixtyone"]
|
|
155
|
+
tools=["nmap", "enum4linux-ng", "snmpwalk", "onesixtyone"],
|
|
138
156
|
),
|
|
139
157
|
ScanPhase(
|
|
140
158
|
name="Vulnerability Assessment",
|
|
141
159
|
description="Identify vulnerabilities in network services",
|
|
142
|
-
tools=["nmap"] # NSE scripts
|
|
160
|
+
tools=["nmap"], # NSE scripts
|
|
143
161
|
),
|
|
144
162
|
ScanPhase(
|
|
145
163
|
name="Credential Testing",
|
|
146
164
|
description="Test for weak or default credentials",
|
|
147
|
-
tools=["hydra", "crackmapexec"]
|
|
148
|
-
)
|
|
165
|
+
tools=["hydra", "crackmapexec"],
|
|
166
|
+
),
|
|
149
167
|
],
|
|
150
168
|
wordlists={
|
|
151
|
-
"passwords": "
|
|
152
|
-
"usernames": "
|
|
153
|
-
"snmp": "snmp-strings.txt"
|
|
169
|
+
"passwords": "passwords_brute.txt",
|
|
170
|
+
"usernames": "usernames_common.txt",
|
|
171
|
+
"snmp": "snmp-strings.txt",
|
|
154
172
|
},
|
|
155
173
|
common_findings=[
|
|
156
|
-
"Default Credentials",
|
|
157
|
-
"
|
|
158
|
-
"
|
|
159
|
-
"
|
|
174
|
+
"Default Credentials",
|
|
175
|
+
"Weak Passwords",
|
|
176
|
+
"SMB Signing Disabled",
|
|
177
|
+
"Anonymous FTP Access",
|
|
178
|
+
"SNMP Community Strings",
|
|
179
|
+
"Unpatched Services",
|
|
180
|
+
"Telnet Enabled",
|
|
181
|
+
"Clear-text Protocols",
|
|
182
|
+
"Unnecessary Services",
|
|
183
|
+
"Network Segmentation Issues",
|
|
160
184
|
],
|
|
161
185
|
tips=[
|
|
162
186
|
"Use masscan for fast initial discovery, nmap for detailed scans",
|
|
163
187
|
"Check for SMB null sessions and anonymous access",
|
|
164
188
|
"Look for SNMP with default community strings (public/private)",
|
|
165
189
|
"Test SSH, FTP, and Telnet for weak/default credentials",
|
|
166
|
-
"Document the network topology as you discover it"
|
|
167
|
-
],
|
|
168
|
-
scope_examples=[
|
|
169
|
-
"192.168.1.0/24",
|
|
170
|
-
"10.0.0.0/8",
|
|
171
|
-
"172.16.0.1-172.16.0.254"
|
|
190
|
+
"Document the network topology as you discover it",
|
|
172
191
|
],
|
|
192
|
+
scope_examples=["192.168.1.0/24", "10.0.0.0/8", "172.16.0.1-172.16.0.254"],
|
|
173
193
|
initial_scan_tool="nmap",
|
|
174
194
|
initial_scan_args="-sn",
|
|
175
|
-
initial_scan_description="Host discovery ping sweep"
|
|
195
|
+
initial_scan_description="Host discovery ping sweep",
|
|
176
196
|
),
|
|
177
|
-
|
|
178
197
|
"activedirectory": EngagementTemplate(
|
|
179
198
|
id="activedirectory",
|
|
180
199
|
name="Active Directory",
|
|
181
200
|
description="Test Windows Active Directory environments for privilege escalation paths",
|
|
182
201
|
icon="[AD]",
|
|
183
202
|
recommended_tools=[
|
|
184
|
-
"nmap",
|
|
185
|
-
"
|
|
203
|
+
"nmap",
|
|
204
|
+
"enum4linux-ng",
|
|
205
|
+
"crackmapexec",
|
|
206
|
+
"smbclient",
|
|
207
|
+
"rpcclient",
|
|
208
|
+
"impacket",
|
|
209
|
+
"bloodhound",
|
|
210
|
+
"ldapsearch",
|
|
211
|
+
"kerbrute",
|
|
212
|
+
"responder",
|
|
186
213
|
],
|
|
187
214
|
scan_phases=[
|
|
188
215
|
ScanPhase(
|
|
189
216
|
name="Domain Enumeration",
|
|
190
217
|
description="Identify domain controllers and domain info",
|
|
191
|
-
tools=["nmap", "crackmapexec"]
|
|
218
|
+
tools=["nmap", "crackmapexec"],
|
|
192
219
|
),
|
|
193
220
|
ScanPhase(
|
|
194
221
|
name="User Enumeration",
|
|
195
222
|
description="Enumerate domain users, groups, and computers",
|
|
196
|
-
tools=["enum4linux-ng", "crackmapexec", "rpcclient"]
|
|
223
|
+
tools=["enum4linux-ng", "crackmapexec", "rpcclient"],
|
|
197
224
|
),
|
|
198
225
|
ScanPhase(
|
|
199
226
|
name="Kerberos Attacks",
|
|
200
227
|
description="Test for Kerberoasting and AS-REP roasting",
|
|
201
|
-
tools=["impacket", "kerbrute"]
|
|
228
|
+
tools=["impacket", "kerbrute"],
|
|
202
229
|
),
|
|
203
230
|
ScanPhase(
|
|
204
231
|
name="SMB/LDAP Enumeration",
|
|
205
232
|
description="Enumerate shares, GPOs, and LDAP objects",
|
|
206
|
-
tools=["smbclient", "crackmapexec", "ldapsearch"]
|
|
233
|
+
tools=["smbclient", "crackmapexec", "ldapsearch"],
|
|
207
234
|
),
|
|
208
235
|
ScanPhase(
|
|
209
236
|
name="Attack Path Analysis",
|
|
210
237
|
description="Identify paths to domain admin",
|
|
211
|
-
tools=["bloodhound"]
|
|
212
|
-
)
|
|
238
|
+
tools=["bloodhound"],
|
|
239
|
+
),
|
|
213
240
|
],
|
|
214
241
|
wordlists={
|
|
215
|
-
"passwords": "
|
|
216
|
-
"usernames": "
|
|
217
|
-
"ad-users": "
|
|
242
|
+
"passwords": "passwords_brute.txt",
|
|
243
|
+
"usernames": "usernames_common.txt",
|
|
244
|
+
"ad-users": "ad_users.txt",
|
|
218
245
|
},
|
|
219
246
|
common_findings=[
|
|
220
|
-
"Kerberoastable Accounts",
|
|
221
|
-
"
|
|
222
|
-
"
|
|
223
|
-
"
|
|
224
|
-
"
|
|
247
|
+
"Kerberoastable Accounts",
|
|
248
|
+
"AS-REP Roastable Accounts",
|
|
249
|
+
"Weak Domain Passwords",
|
|
250
|
+
"LLMNR/NBT-NS Poisoning",
|
|
251
|
+
"Unconstrained Delegation",
|
|
252
|
+
"Password in Description",
|
|
253
|
+
"Service Account Misconfiguration",
|
|
254
|
+
"GPP Passwords",
|
|
255
|
+
"SMB Signing Disabled",
|
|
256
|
+
"Path to Domain Admin",
|
|
225
257
|
],
|
|
226
258
|
tips=[
|
|
227
259
|
"Start by identifying all Domain Controllers",
|
|
@@ -229,18 +261,17 @@ TEMPLATES: Dict[str, EngagementTemplate] = {
|
|
|
229
261
|
"Look for service accounts with SPNs (Kerberoasting)",
|
|
230
262
|
"Use BloodHound to visualize attack paths",
|
|
231
263
|
"Check GPO for stored credentials (GPP)",
|
|
232
|
-
"Test password spray attacks carefully (lockout policies!)"
|
|
264
|
+
"Test password spray attacks carefully (lockout policies!)",
|
|
233
265
|
],
|
|
234
266
|
scope_examples=[
|
|
235
267
|
"CORP.EXAMPLE.COM",
|
|
236
268
|
"10.10.10.0/24 (DC subnet)",
|
|
237
|
-
"dc01.corp.local"
|
|
269
|
+
"dc01.corp.local",
|
|
238
270
|
],
|
|
239
271
|
initial_scan_tool="nmap",
|
|
240
272
|
initial_scan_args="-sV -p 53,88,135,139,389,445,464,636,3268,3269",
|
|
241
|
-
initial_scan_description="AD/DC service discovery"
|
|
273
|
+
initial_scan_description="AD/DC service discovery",
|
|
242
274
|
),
|
|
243
|
-
|
|
244
275
|
"custom": EngagementTemplate(
|
|
245
276
|
id="custom",
|
|
246
277
|
name="Custom / Blank",
|
|
@@ -254,59 +285,69 @@ TEMPLATES: Dict[str, EngagementTemplate] = {
|
|
|
254
285
|
"Define your scope clearly before starting",
|
|
255
286
|
"Enable only the tools you need",
|
|
256
287
|
"Use 'souleyez run <tool>' to queue scans",
|
|
257
|
-
"Check 'souleyez dashboard' to monitor progress"
|
|
288
|
+
"Check 'souleyez dashboard' to monitor progress",
|
|
258
289
|
],
|
|
259
|
-
scope_examples=[
|
|
260
|
-
"any target or range"
|
|
261
|
-
]
|
|
290
|
+
scope_examples=["any target or range"],
|
|
262
291
|
),
|
|
263
|
-
|
|
264
292
|
"ctf": EngagementTemplate(
|
|
265
293
|
id="ctf",
|
|
266
294
|
name="CTF / HackTheBox",
|
|
267
295
|
description="Optimized for CTF challenges and platforms like HackTheBox/TryHackMe",
|
|
268
296
|
icon="[CTF]",
|
|
269
297
|
recommended_tools=[
|
|
270
|
-
"nmap",
|
|
271
|
-
"
|
|
298
|
+
"nmap",
|
|
299
|
+
"gobuster",
|
|
300
|
+
"nikto",
|
|
301
|
+
"ffuf",
|
|
302
|
+
"enum4linux-ng",
|
|
303
|
+
"linpeas",
|
|
304
|
+
"winpeas",
|
|
305
|
+
"pspy",
|
|
306
|
+
"hydra",
|
|
307
|
+
"john",
|
|
308
|
+
"hashcat",
|
|
272
309
|
],
|
|
273
310
|
scan_phases=[
|
|
274
311
|
ScanPhase(
|
|
275
312
|
name="Full Port Scan",
|
|
276
313
|
description="Scan all 65535 ports - CTF boxes often have unusual ports",
|
|
277
|
-
tools=["nmap"]
|
|
314
|
+
tools=["nmap"],
|
|
278
315
|
),
|
|
279
316
|
ScanPhase(
|
|
280
317
|
name="Service Enumeration",
|
|
281
318
|
description="Deep dive into each discovered service",
|
|
282
|
-
tools=["nmap", "enum4linux-ng"]
|
|
319
|
+
tools=["nmap", "enum4linux-ng"],
|
|
283
320
|
),
|
|
284
321
|
ScanPhase(
|
|
285
322
|
name="Web Enumeration",
|
|
286
323
|
description="If web ports found, enumerate thoroughly",
|
|
287
|
-
tools=["gobuster", "ffuf", "nikto"]
|
|
324
|
+
tools=["gobuster", "ffuf", "nikto"],
|
|
288
325
|
),
|
|
289
326
|
ScanPhase(
|
|
290
327
|
name="Exploitation",
|
|
291
328
|
description="Exploit vulnerabilities for initial access",
|
|
292
|
-
tools=[] # Manual + searchsploit
|
|
329
|
+
tools=[], # Manual + searchsploit
|
|
293
330
|
),
|
|
294
331
|
ScanPhase(
|
|
295
332
|
name="Privilege Escalation",
|
|
296
333
|
description="Escalate to root/admin",
|
|
297
|
-
tools=["linpeas", "winpeas"]
|
|
298
|
-
)
|
|
334
|
+
tools=["linpeas", "winpeas"],
|
|
335
|
+
),
|
|
299
336
|
],
|
|
300
337
|
wordlists={
|
|
301
|
-
"directories": "
|
|
302
|
-
"passwords": "
|
|
303
|
-
"extensions": "
|
|
338
|
+
"directories": "web_dirs_large.txt",
|
|
339
|
+
"passwords": "passwords_brute.txt",
|
|
340
|
+
"extensions": "web_extensions.txt",
|
|
304
341
|
},
|
|
305
342
|
common_findings=[
|
|
306
|
-
"Hidden Web Directory",
|
|
307
|
-
"
|
|
308
|
-
"
|
|
309
|
-
"
|
|
343
|
+
"Hidden Web Directory",
|
|
344
|
+
"Default Credentials",
|
|
345
|
+
"Outdated Software Version",
|
|
346
|
+
"SUID Binary",
|
|
347
|
+
"Writable Script in Cron",
|
|
348
|
+
"SSH Key Exposure",
|
|
349
|
+
"Database Credentials in Config",
|
|
350
|
+
"Kernel Exploit",
|
|
310
351
|
],
|
|
311
352
|
tips=[
|
|
312
353
|
"Always do a full port scan (-p-) - CTF boxes hide services",
|
|
@@ -314,17 +355,13 @@ TEMPLATES: Dict[str, EngagementTemplate] = {
|
|
|
314
355
|
"Look for version numbers to searchsploit",
|
|
315
356
|
"After initial access, stabilize your shell first",
|
|
316
357
|
"Run linPEAS/winPEAS immediately after access",
|
|
317
|
-
"Check sudo -l, SUID binaries, and cron jobs"
|
|
318
|
-
],
|
|
319
|
-
scope_examples=[
|
|
320
|
-
"10.10.10.X (HTB)",
|
|
321
|
-
"10.10.X.X (THM)",
|
|
322
|
-
"ctf.example.com"
|
|
358
|
+
"Check sudo -l, SUID binaries, and cron jobs",
|
|
323
359
|
],
|
|
360
|
+
scope_examples=["10.10.10.X (HTB)", "10.10.X.X (THM)", "ctf.example.com"],
|
|
324
361
|
initial_scan_tool="nmap",
|
|
325
362
|
initial_scan_args="-sV -sC -p-",
|
|
326
|
-
initial_scan_description="Full port scan (all 65535 ports)"
|
|
327
|
-
)
|
|
363
|
+
initial_scan_description="Full port scan (all 65535 ports)",
|
|
364
|
+
),
|
|
328
365
|
}
|
|
329
366
|
|
|
330
367
|
|
|
@@ -355,6 +392,7 @@ def apply_template_settings(engagement_id: int, template_id: str) -> Dict[str, A
|
|
|
355
392
|
|
|
356
393
|
# Store template metadata with engagement (for future reference)
|
|
357
394
|
from souleyez.storage.engagements import EngagementManager
|
|
395
|
+
|
|
358
396
|
em = EngagementManager()
|
|
359
397
|
|
|
360
398
|
# Update engagement type
|
|
@@ -365,7 +403,7 @@ def apply_template_settings(engagement_id: int, template_id: str) -> Dict[str, A
|
|
|
365
403
|
"template": template.name,
|
|
366
404
|
"recommended_tools": template.recommended_tools,
|
|
367
405
|
"scan_phases": [p.name for p in template.scan_phases],
|
|
368
|
-
"tips": template.tips[:3] # First 3 tips
|
|
406
|
+
"tips": template.tips[:3], # First 3 tips
|
|
369
407
|
}
|
|
370
408
|
|
|
371
409
|
|
|
@@ -374,33 +412,33 @@ def display_template_info(template: EngagementTemplate) -> None:
|
|
|
374
412
|
import click
|
|
375
413
|
|
|
376
414
|
click.echo()
|
|
377
|
-
click.echo(click.style(f" {template.icon} {template.name}", fg=
|
|
378
|
-
click.echo(click.style(f" {template.description}", fg=
|
|
415
|
+
click.echo(click.style(f" {template.icon} {template.name}", fg="cyan", bold=True))
|
|
416
|
+
click.echo(click.style(f" {template.description}", fg="white"))
|
|
379
417
|
click.echo()
|
|
380
418
|
|
|
381
419
|
if template.recommended_tools:
|
|
382
|
-
click.echo(click.style(" Recommended Tools:", fg=
|
|
420
|
+
click.echo(click.style(" Recommended Tools:", fg="yellow"))
|
|
383
421
|
# Display in rows of 5
|
|
384
422
|
tools = template.recommended_tools
|
|
385
423
|
for i in range(0, len(tools), 5):
|
|
386
|
-
row = tools[i:i+5]
|
|
424
|
+
row = tools[i : i + 5]
|
|
387
425
|
click.echo(" " + ", ".join(row))
|
|
388
426
|
click.echo()
|
|
389
427
|
|
|
390
428
|
if template.scan_phases:
|
|
391
|
-
click.echo(click.style(" Scan Phases:", fg=
|
|
429
|
+
click.echo(click.style(" Scan Phases:", fg="yellow"))
|
|
392
430
|
for i, phase in enumerate(template.scan_phases, 1):
|
|
393
431
|
click.echo(f" {i}. {phase.name} - {phase.description}")
|
|
394
432
|
click.echo()
|
|
395
433
|
|
|
396
434
|
if template.tips:
|
|
397
|
-
click.echo(click.style(" Quick Tips:", fg=
|
|
435
|
+
click.echo(click.style(" Quick Tips:", fg="yellow"))
|
|
398
436
|
for tip in template.tips[:3]:
|
|
399
437
|
click.echo(f" - {tip}")
|
|
400
438
|
click.echo()
|
|
401
439
|
|
|
402
440
|
if template.scope_examples:
|
|
403
|
-
click.echo(click.style(" Scope Examples:", fg=
|
|
441
|
+
click.echo(click.style(" Scope Examples:", fg="yellow"))
|
|
404
442
|
for ex in template.scope_examples:
|
|
405
443
|
click.echo(f" - {ex}")
|
|
406
444
|
|
|
@@ -413,7 +451,9 @@ def get_recommended_tools(engagement_type: str) -> set:
|
|
|
413
451
|
return set(t.lower() for t in template.recommended_tools)
|
|
414
452
|
|
|
415
453
|
|
|
416
|
-
def queue_initial_scan(
|
|
454
|
+
def queue_initial_scan(
|
|
455
|
+
template_id: str, target: str, engagement_id: int
|
|
456
|
+
) -> Optional[int]:
|
|
417
457
|
"""
|
|
418
458
|
Queue the initial scan for a template.
|
|
419
459
|
|
|
@@ -425,13 +465,14 @@ def queue_initial_scan(template_id: str, target: str, engagement_id: int) -> Opt
|
|
|
425
465
|
|
|
426
466
|
try:
|
|
427
467
|
from souleyez.engine.background import enqueue_job
|
|
468
|
+
|
|
428
469
|
job_id = enqueue_job(
|
|
429
470
|
tool=template.initial_scan_tool,
|
|
430
471
|
target=target,
|
|
431
472
|
args=template.initial_scan_args,
|
|
432
473
|
label=f"Initial: {template.initial_scan_description}",
|
|
433
474
|
engagement_id=engagement_id,
|
|
434
|
-
metadata={"auto_queued": True, "template": template_id}
|
|
475
|
+
metadata={"auto_queued": True, "template": template_id},
|
|
435
476
|
)
|
|
436
477
|
return job_id
|
|
437
478
|
except Exception:
|
|
@@ -457,16 +498,26 @@ def display_scan_phases_guide(template_id: str, clear_screen: bool = True) -> No
|
|
|
457
498
|
click.echo("┌" + "─" * (width - 2) + "┐")
|
|
458
499
|
title = f"SCAN PHASES GUIDE: {template.name if template else 'Unknown'}"
|
|
459
500
|
padding = (width - len(title) - 2) // 2
|
|
460
|
-
click.echo(
|
|
501
|
+
click.echo(
|
|
502
|
+
"│"
|
|
503
|
+
+ " " * padding
|
|
504
|
+
+ click.style(title, bold=True, fg="cyan")
|
|
505
|
+
+ " " * (width - len(title) - padding - 2)
|
|
506
|
+
+ "│"
|
|
507
|
+
)
|
|
461
508
|
click.echo("└" + "─" * (width - 2) + "┘")
|
|
462
509
|
click.echo()
|
|
463
510
|
|
|
464
511
|
if not template:
|
|
465
|
-
click.echo(click.style(" No template found.", fg=
|
|
512
|
+
click.echo(click.style(" No template found.", fg="red"))
|
|
466
513
|
return
|
|
467
514
|
|
|
468
515
|
if not template.scan_phases:
|
|
469
|
-
click.echo(
|
|
516
|
+
click.echo(
|
|
517
|
+
click.style(
|
|
518
|
+
" No scan phases defined for this engagement type.", fg="yellow"
|
|
519
|
+
)
|
|
520
|
+
)
|
|
470
521
|
click.echo(" This is a custom engagement - define your own workflow!")
|
|
471
522
|
return
|
|
472
523
|
|
|
@@ -475,11 +526,11 @@ def display_scan_phases_guide(template_id: str, clear_screen: bool = True) -> No
|
|
|
475
526
|
click.echo()
|
|
476
527
|
|
|
477
528
|
for i, phase in enumerate(template.scan_phases, 1):
|
|
478
|
-
click.echo(click.style(f" Phase {i}: {phase.name}", fg=
|
|
529
|
+
click.echo(click.style(f" Phase {i}: {phase.name}", fg="yellow", bold=True))
|
|
479
530
|
click.echo(f" {phase.description}")
|
|
480
531
|
if phase.tools:
|
|
481
532
|
tools_str = ", ".join(phase.tools)
|
|
482
|
-
click.echo(click.style(" Tools: ", fg=
|
|
533
|
+
click.echo(click.style(" Tools: ", fg="green") + tools_str)
|
|
483
534
|
click.echo()
|
|
484
535
|
|
|
485
536
|
if template.tips:
|
|
@@ -493,6 +544,6 @@ def display_scan_phases_guide(template_id: str, clear_screen: bool = True) -> No
|
|
|
493
544
|
|
|
494
545
|
click.echo(" " + "─" * (width - 4))
|
|
495
546
|
click.echo()
|
|
496
|
-
click.echo(click.style(" [q] ← Back", fg=
|
|
547
|
+
click.echo(click.style(" [q] ← Back", fg="bright_black"))
|
|
497
548
|
click.echo()
|
|
498
549
|
click.echo(" " + "─" * (width - 4))
|