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/ui/splunk_vulns_view.py
CHANGED
|
@@ -15,10 +15,10 @@ console = Console()
|
|
|
15
15
|
|
|
16
16
|
# Severity colors
|
|
17
17
|
SEVERITY_COLORS = {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
"Critical": "red",
|
|
19
|
+
"High": "yellow",
|
|
20
|
+
"Medium": "white",
|
|
21
|
+
"Low": "bright_black",
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
|
|
@@ -45,15 +45,29 @@ def show_splunk_vulns_view(engagement_id: int, engagement_name: str = "") -> Non
|
|
|
45
45
|
|
|
46
46
|
# Header
|
|
47
47
|
click.echo("\n┌" + "─" * (width - 2) + "┐")
|
|
48
|
-
click.echo(
|
|
48
|
+
click.echo(
|
|
49
|
+
"│"
|
|
50
|
+
+ click.style(
|
|
51
|
+
" SPLUNK VULNERABILITIES ".center(width - 2), bold=True, fg="cyan"
|
|
52
|
+
)
|
|
53
|
+
+ "│"
|
|
54
|
+
)
|
|
49
55
|
click.echo("└" + "─" * (width - 2) + "┘")
|
|
50
56
|
click.echo()
|
|
51
57
|
|
|
52
58
|
# Check if Splunk is configured
|
|
53
59
|
config = WazuhConfig.get_config(engagement_id)
|
|
54
60
|
|
|
55
|
-
if
|
|
56
|
-
|
|
61
|
+
if (
|
|
62
|
+
not config
|
|
63
|
+
or config.get("siem_type") != "splunk"
|
|
64
|
+
or not config.get("enabled")
|
|
65
|
+
):
|
|
66
|
+
click.echo(
|
|
67
|
+
click.style(
|
|
68
|
+
" Splunk is not configured for this engagement.", fg="yellow"
|
|
69
|
+
)
|
|
70
|
+
)
|
|
57
71
|
click.echo()
|
|
58
72
|
click.echo(" Configure Splunk in Settings -> SIEM Integration")
|
|
59
73
|
click.echo()
|
|
@@ -62,7 +76,7 @@ def show_splunk_vulns_view(engagement_id: int, engagement_name: str = "") -> Non
|
|
|
62
76
|
click.echo(" [q] Back")
|
|
63
77
|
click.echo()
|
|
64
78
|
try:
|
|
65
|
-
if click.getchar().lower() ==
|
|
79
|
+
if click.getchar().lower() == "q":
|
|
66
80
|
return
|
|
67
81
|
except (KeyboardInterrupt, EOFError):
|
|
68
82
|
return
|
|
@@ -71,15 +85,18 @@ def show_splunk_vulns_view(engagement_id: int, engagement_name: str = "") -> Non
|
|
|
71
85
|
# Get Splunk client
|
|
72
86
|
try:
|
|
73
87
|
from souleyez.integrations.siem.splunk import SplunkSIEMClient
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
88
|
+
|
|
89
|
+
client = SplunkSIEMClient.from_config(
|
|
90
|
+
{
|
|
91
|
+
"api_url": config.get("api_url", ""),
|
|
92
|
+
"username": config.get("username", ""),
|
|
93
|
+
"password": config.get("password", ""),
|
|
94
|
+
"verify_ssl": config.get("verify_ssl", False),
|
|
95
|
+
"default_index": config.get("default_index", "main"),
|
|
96
|
+
}
|
|
97
|
+
)
|
|
81
98
|
except Exception as e:
|
|
82
|
-
click.echo(click.style(f" Error connecting to Splunk: {e}", fg=
|
|
99
|
+
click.echo(click.style(f" Error connecting to Splunk: {e}", fg="red"))
|
|
83
100
|
click.echo()
|
|
84
101
|
click.pause(" Press any key to return...")
|
|
85
102
|
return
|
|
@@ -88,23 +105,30 @@ def show_splunk_vulns_view(engagement_id: int, engagement_name: str = "") -> Non
|
|
|
88
105
|
try:
|
|
89
106
|
summary = client.get_vulnerability_summary()
|
|
90
107
|
vulns = client.get_vulnerabilities(
|
|
91
|
-
severity=severity_filter,
|
|
92
|
-
agent_name=host_filter,
|
|
93
|
-
limit=1000
|
|
108
|
+
severity=severity_filter, agent_name=host_filter, limit=1000
|
|
94
109
|
)
|
|
95
110
|
except Exception as e:
|
|
96
|
-
click.echo(click.style(f" Error querying Splunk: {e}", fg=
|
|
111
|
+
click.echo(click.style(f" Error querying Splunk: {e}", fg="red"))
|
|
97
112
|
click.echo()
|
|
98
113
|
click.echo(" Make sure the wazuh_vulns index exists and has data.")
|
|
99
|
-
click.echo(
|
|
114
|
+
click.echo(
|
|
115
|
+
" Run the vuln sync script: python3 scripts/wazuh_vuln_to_splunk.py --all"
|
|
116
|
+
)
|
|
100
117
|
click.echo()
|
|
101
118
|
click.pause(" Press any key to return...")
|
|
102
119
|
return
|
|
103
120
|
|
|
104
121
|
# Display table with summary
|
|
105
122
|
page, total_pages = _display_vulns_table(
|
|
106
|
-
console,
|
|
107
|
-
|
|
123
|
+
console,
|
|
124
|
+
vulns,
|
|
125
|
+
page,
|
|
126
|
+
page_size,
|
|
127
|
+
view_all,
|
|
128
|
+
severity_filter,
|
|
129
|
+
host_filter,
|
|
130
|
+
width,
|
|
131
|
+
summary,
|
|
108
132
|
)
|
|
109
133
|
|
|
110
134
|
# Menu
|
|
@@ -123,27 +147,27 @@ def show_splunk_vulns_view(engagement_id: int, engagement_name: str = "") -> Non
|
|
|
123
147
|
try:
|
|
124
148
|
choice = input(" Select option: ").strip().lower()
|
|
125
149
|
|
|
126
|
-
if choice ==
|
|
150
|
+
if choice == "q":
|
|
127
151
|
return
|
|
128
|
-
elif choice ==
|
|
152
|
+
elif choice == "r":
|
|
129
153
|
continue # Refresh
|
|
130
|
-
elif choice ==
|
|
154
|
+
elif choice == "i":
|
|
131
155
|
_interactive_vulns_mode(vulns)
|
|
132
|
-
elif choice ==
|
|
156
|
+
elif choice == "t":
|
|
133
157
|
view_all = not view_all
|
|
134
158
|
if not view_all:
|
|
135
159
|
page = 0
|
|
136
|
-
elif choice ==
|
|
160
|
+
elif choice == "n" and not view_all and page < total_pages - 1:
|
|
137
161
|
page += 1
|
|
138
|
-
elif choice ==
|
|
162
|
+
elif choice == "p" and not view_all and page > 0:
|
|
139
163
|
page -= 1
|
|
140
|
-
elif choice ==
|
|
164
|
+
elif choice == "f":
|
|
141
165
|
severity_filter = _select_severity_filter()
|
|
142
166
|
page = 0
|
|
143
|
-
elif choice ==
|
|
167
|
+
elif choice == "h":
|
|
144
168
|
host_filter = _select_host_filter()
|
|
145
169
|
page = 0
|
|
146
|
-
elif choice ==
|
|
170
|
+
elif choice == "c":
|
|
147
171
|
severity_filter = None
|
|
148
172
|
host_filter = None
|
|
149
173
|
page = 0
|
|
@@ -152,10 +176,10 @@ def show_splunk_vulns_view(engagement_id: int, engagement_name: str = "") -> Non
|
|
|
152
176
|
if 0 <= vuln_idx < len(vulns):
|
|
153
177
|
_show_vuln_detail(vulns[vuln_idx])
|
|
154
178
|
else:
|
|
155
|
-
click.echo(click.style(" Invalid number", fg=
|
|
179
|
+
click.echo(click.style(" Invalid number", fg="red"))
|
|
156
180
|
click.pause()
|
|
157
181
|
else:
|
|
158
|
-
click.echo(click.style("Invalid option", fg=
|
|
182
|
+
click.echo(click.style("Invalid option", fg="red"))
|
|
159
183
|
click.pause()
|
|
160
184
|
|
|
161
185
|
except (KeyboardInterrupt, EOFError):
|
|
@@ -163,19 +187,31 @@ def show_splunk_vulns_view(engagement_id: int, engagement_name: str = "") -> Non
|
|
|
163
187
|
|
|
164
188
|
|
|
165
189
|
def _display_vulns_table(
|
|
166
|
-
console: Console,
|
|
167
|
-
|
|
168
|
-
|
|
190
|
+
console: Console,
|
|
191
|
+
vulns: List[Dict],
|
|
192
|
+
page: int,
|
|
193
|
+
page_size: int,
|
|
194
|
+
view_all: bool,
|
|
195
|
+
severity_filter: Optional[str],
|
|
196
|
+
host_filter: Optional[str],
|
|
197
|
+
width: int,
|
|
198
|
+
summary: Dict,
|
|
169
199
|
) -> tuple:
|
|
170
200
|
"""Display vulnerabilities table with summary header.
|
|
171
201
|
|
|
172
202
|
Returns: (current_page, total_pages)
|
|
173
203
|
"""
|
|
174
|
-
by_sev = summary.get(
|
|
204
|
+
by_sev = summary.get("by_severity", {})
|
|
175
205
|
|
|
176
206
|
# Summary header
|
|
177
207
|
click.echo("═" * width)
|
|
178
|
-
click.echo(
|
|
208
|
+
click.echo(
|
|
209
|
+
click.style(
|
|
210
|
+
f" SPLUNK VULNERABILITIES ({summary.get('total', 0)} total, {summary.get('unique_cves', 0)} unique CVEs)",
|
|
211
|
+
bold=True,
|
|
212
|
+
fg="yellow",
|
|
213
|
+
)
|
|
214
|
+
)
|
|
179
215
|
|
|
180
216
|
# Severity breakdown
|
|
181
217
|
sev_line = (
|
|
@@ -187,7 +223,11 @@ def _display_vulns_table(
|
|
|
187
223
|
click.echo(sev_line)
|
|
188
224
|
|
|
189
225
|
# Agents line
|
|
190
|
-
click.echo(
|
|
226
|
+
click.echo(
|
|
227
|
+
click.style(
|
|
228
|
+
f" Agents affected: {summary.get('agents_affected', 0)}", fg="bright_black"
|
|
229
|
+
)
|
|
230
|
+
)
|
|
191
231
|
|
|
192
232
|
# Show active filters
|
|
193
233
|
if severity_filter or host_filter:
|
|
@@ -196,13 +236,13 @@ def _display_vulns_table(
|
|
|
196
236
|
filter_parts.append(f"Severity: {severity_filter}")
|
|
197
237
|
if host_filter:
|
|
198
238
|
filter_parts.append(f"Host: {host_filter}")
|
|
199
|
-
click.echo(click.style(f" Filters: {', '.join(filter_parts)}", fg=
|
|
239
|
+
click.echo(click.style(f" Filters: {', '.join(filter_parts)}", fg="cyan"))
|
|
200
240
|
|
|
201
241
|
click.echo("─" * width)
|
|
202
242
|
click.echo()
|
|
203
243
|
|
|
204
244
|
if not vulns:
|
|
205
|
-
click.echo(" " + click.style("No vulnerabilities found!", fg=
|
|
245
|
+
click.echo(" " + click.style("No vulnerabilities found!", fg="green"))
|
|
206
246
|
click.echo(" Make sure Wazuh vuln data is synced to Splunk.")
|
|
207
247
|
click.echo()
|
|
208
248
|
return 0, 1
|
|
@@ -224,7 +264,7 @@ def _display_vulns_table(
|
|
|
224
264
|
header_style="bold cyan",
|
|
225
265
|
box=DesignSystem.TABLE_BOX,
|
|
226
266
|
padding=(0, 1),
|
|
227
|
-
expand=True
|
|
267
|
+
expand=True,
|
|
228
268
|
)
|
|
229
269
|
|
|
230
270
|
table.add_column("○", width=3, justify="center")
|
|
@@ -242,17 +282,17 @@ def _display_vulns_table(
|
|
|
242
282
|
else:
|
|
243
283
|
display_idx = (page * page_size) + idx + 1
|
|
244
284
|
|
|
245
|
-
cve = vuln.get(
|
|
246
|
-
severity = vuln.get(
|
|
247
|
-
sev_color = SEVERITY_COLORS.get(severity,
|
|
285
|
+
cve = vuln.get("cve_id", "-")
|
|
286
|
+
severity = vuln.get("severity", "Medium")
|
|
287
|
+
sev_color = SEVERITY_COLORS.get(severity, "white")
|
|
248
288
|
sev_display = f"[{sev_color}]{severity}[/{sev_color}]"
|
|
249
289
|
|
|
250
|
-
cvss = vuln.get(
|
|
290
|
+
cvss = vuln.get("cvss_score")
|
|
251
291
|
cvss_display = f"{cvss:.1f}" if cvss else "-"
|
|
252
292
|
|
|
253
|
-
host = vuln.get(
|
|
254
|
-
package = vuln.get(
|
|
255
|
-
os_name = vuln.get(
|
|
293
|
+
host = vuln.get("agent_name", "-")[:15]
|
|
294
|
+
package = vuln.get("package_name", "-")[:24]
|
|
295
|
+
os_name = vuln.get("os_name", "-")[:11]
|
|
256
296
|
|
|
257
297
|
table.add_row(
|
|
258
298
|
"○",
|
|
@@ -262,7 +302,7 @@ def _display_vulns_table(
|
|
|
262
302
|
cvss_display,
|
|
263
303
|
host,
|
|
264
304
|
package,
|
|
265
|
-
os_name
|
|
305
|
+
os_name,
|
|
266
306
|
)
|
|
267
307
|
|
|
268
308
|
console.print(" ", table)
|
|
@@ -291,9 +331,9 @@ def _select_severity_filter() -> Optional[str]:
|
|
|
291
331
|
click.echo()
|
|
292
332
|
|
|
293
333
|
key = click.getchar().lower()
|
|
294
|
-
severity_map = {
|
|
334
|
+
severity_map = {"1": "Critical", "2": "High", "3": "Medium", "4": "Low"}
|
|
295
335
|
|
|
296
|
-
if key ==
|
|
336
|
+
if key == "c":
|
|
297
337
|
return None
|
|
298
338
|
return severity_map.get(key)
|
|
299
339
|
|
|
@@ -301,9 +341,11 @@ def _select_severity_filter() -> Optional[str]:
|
|
|
301
341
|
def _select_host_filter() -> Optional[str]:
|
|
302
342
|
"""Show host filter prompt."""
|
|
303
343
|
click.echo()
|
|
304
|
-
ip = click.prompt(
|
|
344
|
+
ip = click.prompt(
|
|
345
|
+
" Enter host/agent name (partial match, or 'c' to clear)", default=""
|
|
346
|
+
)
|
|
305
347
|
|
|
306
|
-
if ip.lower() ==
|
|
348
|
+
if ip.lower() == "c" or not ip:
|
|
307
349
|
return None
|
|
308
350
|
return ip
|
|
309
351
|
|
|
@@ -313,17 +355,22 @@ def _show_vuln_detail(vuln: Dict) -> None:
|
|
|
313
355
|
DesignSystem.clear_screen()
|
|
314
356
|
width = DesignSystem.get_terminal_width()
|
|
315
357
|
|
|
316
|
-
cve = vuln.get(
|
|
317
|
-
severity = vuln.get(
|
|
318
|
-
sev_color = SEVERITY_COLORS.get(severity,
|
|
358
|
+
cve = vuln.get("cve_id", "Unknown")
|
|
359
|
+
severity = vuln.get("severity", "Medium")
|
|
360
|
+
sev_color = SEVERITY_COLORS.get(severity, "white")
|
|
319
361
|
|
|
320
362
|
click.echo("\n" + "─" * (width - 2) + "┐")
|
|
321
|
-
click.echo(
|
|
363
|
+
click.echo(
|
|
364
|
+
"│" + click.style(f" {cve} ".center(width - 2), bold=True, fg="cyan") + "│"
|
|
365
|
+
)
|
|
322
366
|
click.echo("└" + "─" * (width - 2) + "┘")
|
|
323
367
|
click.echo()
|
|
324
368
|
|
|
325
|
-
click.echo(
|
|
326
|
-
|
|
369
|
+
click.echo(
|
|
370
|
+
f" Severity: "
|
|
371
|
+
+ click.style(severity, fg=sev_color, bold=True)
|
|
372
|
+
+ f" | CVSS: {vuln.get('cvss_score', '-')}"
|
|
373
|
+
)
|
|
327
374
|
click.echo()
|
|
328
375
|
|
|
329
376
|
click.echo(click.style(" Host/Agent:", bold=True))
|
|
@@ -342,7 +389,7 @@ def _show_vuln_detail(vuln: Dict) -> None:
|
|
|
342
389
|
click.echo()
|
|
343
390
|
|
|
344
391
|
# Description (truncated)
|
|
345
|
-
desc = vuln.get(
|
|
392
|
+
desc = vuln.get("description", "")
|
|
346
393
|
if desc:
|
|
347
394
|
click.echo(click.style(" Description:", bold=True))
|
|
348
395
|
# Word wrap description
|
|
@@ -366,52 +413,58 @@ def _interactive_vulns_mode(vulns: List[Dict]) -> None:
|
|
|
366
413
|
from souleyez.ui.interactive_selector import interactive_select
|
|
367
414
|
|
|
368
415
|
if not vulns:
|
|
369
|
-
click.echo(click.style(" No vulnerabilities to select.", fg=
|
|
416
|
+
click.echo(click.style(" No vulnerabilities to select.", fg="yellow"))
|
|
370
417
|
click.pause()
|
|
371
418
|
return
|
|
372
419
|
|
|
373
420
|
# Prepare items for interactive selector
|
|
374
421
|
vuln_items = []
|
|
375
422
|
for vuln in vulns:
|
|
376
|
-
vuln_items.append(
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
423
|
+
vuln_items.append(
|
|
424
|
+
{
|
|
425
|
+
"id": id(vuln),
|
|
426
|
+
"cve_id": vuln.get("cve_id", "-"),
|
|
427
|
+
"severity": vuln.get("severity", "Medium"),
|
|
428
|
+
"cvss": (
|
|
429
|
+
f"{vuln.get('cvss_score', 0):.1f}"
|
|
430
|
+
if vuln.get("cvss_score")
|
|
431
|
+
else "-"
|
|
432
|
+
),
|
|
433
|
+
"host": vuln.get("agent_name", "-")[:15],
|
|
434
|
+
"package": vuln.get("package_name", "-")[:20],
|
|
435
|
+
"os": vuln.get("os_name", "-")[:12],
|
|
436
|
+
"raw": vuln,
|
|
437
|
+
}
|
|
438
|
+
)
|
|
386
439
|
|
|
387
440
|
columns = [
|
|
388
|
-
{
|
|
389
|
-
{
|
|
390
|
-
{
|
|
391
|
-
{
|
|
392
|
-
{
|
|
441
|
+
{"name": "CVE", "key": "cve_id", "width": 18},
|
|
442
|
+
{"name": "Severity", "key": "severity", "width": 10},
|
|
443
|
+
{"name": "CVSS", "key": "cvss", "width": 6},
|
|
444
|
+
{"name": "Host", "key": "host", "width": 15},
|
|
445
|
+
{"name": "Package", "key": "package", "width": 20},
|
|
393
446
|
]
|
|
394
447
|
|
|
395
448
|
def format_cell(item: Dict, key: str) -> str:
|
|
396
|
-
if key ==
|
|
397
|
-
sev = item.get(
|
|
398
|
-
color = SEVERITY_COLORS.get(sev,
|
|
449
|
+
if key == "severity":
|
|
450
|
+
sev = item.get("severity", "Medium")
|
|
451
|
+
color = SEVERITY_COLORS.get(sev, "white")
|
|
399
452
|
return f"[{color}]{sev}[/{color}]"
|
|
400
|
-
return str(item.get(key,
|
|
453
|
+
return str(item.get(key, "-"))
|
|
401
454
|
|
|
402
455
|
selected_ids: set = set()
|
|
403
456
|
interactive_select(
|
|
404
457
|
items=vuln_items,
|
|
405
458
|
columns=columns,
|
|
406
459
|
selected_ids=selected_ids,
|
|
407
|
-
get_id=lambda v: v[
|
|
460
|
+
get_id=lambda v: v["id"],
|
|
408
461
|
title="SPLUNK VULNERABILITIES",
|
|
409
|
-
format_cell=format_cell
|
|
462
|
+
format_cell=format_cell,
|
|
410
463
|
)
|
|
411
464
|
|
|
412
465
|
# Show details of first selected
|
|
413
466
|
if selected_ids:
|
|
414
467
|
for item in vuln_items:
|
|
415
|
-
if item[
|
|
416
|
-
_show_vuln_detail(item[
|
|
468
|
+
if item["id"] in selected_ids:
|
|
469
|
+
_show_vuln_detail(item["raw"])
|
|
417
470
|
break
|