souleyez 2.43.29__py3-none-any.whl → 3.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- souleyez/__init__.py +1 -2
- souleyez/ai/__init__.py +21 -15
- souleyez/ai/action_mapper.py +249 -150
- souleyez/ai/chain_advisor.py +116 -100
- souleyez/ai/claude_provider.py +29 -28
- souleyez/ai/context_builder.py +80 -62
- souleyez/ai/executor.py +158 -117
- souleyez/ai/feedback_handler.py +136 -121
- souleyez/ai/llm_factory.py +27 -20
- souleyez/ai/llm_provider.py +4 -2
- souleyez/ai/ollama_provider.py +6 -9
- souleyez/ai/ollama_service.py +44 -37
- souleyez/ai/path_scorer.py +91 -76
- souleyez/ai/recommender.py +176 -144
- souleyez/ai/report_context.py +74 -73
- souleyez/ai/report_service.py +84 -66
- souleyez/ai/result_parser.py +222 -229
- souleyez/ai/safety.py +67 -44
- souleyez/auth/__init__.py +23 -22
- souleyez/auth/audit.py +36 -26
- souleyez/auth/engagement_access.py +65 -48
- souleyez/auth/permissions.py +14 -3
- souleyez/auth/session_manager.py +54 -37
- souleyez/auth/user_manager.py +109 -64
- souleyez/commands/audit.py +40 -43
- souleyez/commands/auth.py +35 -15
- souleyez/commands/deliverables.py +55 -50
- souleyez/commands/engagement.py +47 -28
- souleyez/commands/license.py +32 -23
- souleyez/commands/screenshots.py +36 -32
- souleyez/commands/user.py +82 -36
- souleyez/config.py +52 -44
- souleyez/core/credential_tester.py +87 -81
- souleyez/core/cve_mappings.py +179 -192
- souleyez/core/cve_matcher.py +162 -148
- souleyez/core/msf_auto_mapper.py +100 -83
- souleyez/core/msf_chain_engine.py +294 -256
- souleyez/core/msf_database.py +153 -70
- souleyez/core/msf_integration.py +679 -673
- souleyez/core/msf_rpc_client.py +40 -42
- souleyez/core/msf_rpc_manager.py +77 -79
- souleyez/core/msf_sync_manager.py +241 -181
- souleyez/core/network_utils.py +22 -15
- souleyez/core/parser_handler.py +34 -25
- souleyez/core/pending_chains.py +114 -63
- souleyez/core/templates.py +158 -107
- souleyez/core/tool_chaining.py +9564 -2881
- souleyez/core/version_utils.py +79 -94
- souleyez/core/vuln_correlation.py +136 -89
- souleyez/core/web_utils.py +33 -32
- souleyez/data/wordlists/ad_users.txt +378 -0
- souleyez/data/wordlists/api_endpoints_large.txt +769 -0
- souleyez/data/wordlists/home_dir_sensitive.txt +39 -0
- souleyez/data/wordlists/lfi_payloads.txt +82 -0
- souleyez/data/wordlists/passwords_brute.txt +1548 -0
- souleyez/data/wordlists/passwords_crack.txt +2479 -0
- souleyez/data/wordlists/passwords_spray.txt +386 -0
- souleyez/data/wordlists/subdomains_large.txt +5057 -0
- souleyez/data/wordlists/usernames_common.txt +694 -0
- souleyez/data/wordlists/web_dirs_large.txt +4769 -0
- souleyez/detection/__init__.py +1 -1
- souleyez/detection/attack_signatures.py +12 -17
- souleyez/detection/mitre_mappings.py +61 -55
- souleyez/detection/validator.py +97 -86
- souleyez/devtools.py +23 -10
- souleyez/docs/README.md +4 -4
- souleyez/docs/api-reference/cli-commands.md +2 -2
- souleyez/docs/developer-guide/adding-new-tools.md +562 -0
- souleyez/docs/user-guide/auto-chaining.md +30 -8
- souleyez/docs/user-guide/getting-started.md +1 -1
- souleyez/docs/user-guide/installation.md +26 -3
- souleyez/docs/user-guide/metasploit-integration.md +2 -2
- souleyez/docs/user-guide/rbac.md +1 -1
- souleyez/docs/user-guide/scope-management.md +1 -1
- souleyez/docs/user-guide/siem-integration.md +1 -1
- souleyez/docs/user-guide/tools-reference.md +1 -8
- souleyez/docs/user-guide/worker-management.md +1 -1
- souleyez/engine/background.py +1239 -535
- souleyez/engine/base.py +4 -1
- souleyez/engine/job_status.py +17 -49
- souleyez/engine/log_sanitizer.py +103 -77
- souleyez/engine/manager.py +38 -7
- souleyez/engine/result_handler.py +2200 -1550
- souleyez/engine/worker_manager.py +50 -41
- souleyez/export/evidence_bundle.py +72 -62
- souleyez/feature_flags/features.py +16 -20
- souleyez/feature_flags.py +5 -9
- souleyez/handlers/__init__.py +11 -0
- souleyez/handlers/base.py +188 -0
- souleyez/handlers/bash_handler.py +277 -0
- souleyez/handlers/bloodhound_handler.py +243 -0
- souleyez/handlers/certipy_handler.py +311 -0
- souleyez/handlers/crackmapexec_handler.py +486 -0
- souleyez/handlers/dnsrecon_handler.py +344 -0
- souleyez/handlers/enum4linux_handler.py +400 -0
- souleyez/handlers/evil_winrm_handler.py +493 -0
- souleyez/handlers/ffuf_handler.py +815 -0
- souleyez/handlers/gobuster_handler.py +1114 -0
- souleyez/handlers/gpp_extract_handler.py +334 -0
- souleyez/handlers/hashcat_handler.py +444 -0
- souleyez/handlers/hydra_handler.py +564 -0
- souleyez/handlers/impacket_getuserspns_handler.py +343 -0
- souleyez/handlers/impacket_psexec_handler.py +222 -0
- souleyez/handlers/impacket_secretsdump_handler.py +426 -0
- souleyez/handlers/john_handler.py +286 -0
- souleyez/handlers/katana_handler.py +425 -0
- souleyez/handlers/kerbrute_handler.py +298 -0
- souleyez/handlers/ldapsearch_handler.py +636 -0
- souleyez/handlers/lfi_extract_handler.py +464 -0
- souleyez/handlers/msf_auxiliary_handler.py +409 -0
- souleyez/handlers/msf_exploit_handler.py +380 -0
- souleyez/handlers/nikto_handler.py +413 -0
- souleyez/handlers/nmap_handler.py +821 -0
- souleyez/handlers/nuclei_handler.py +359 -0
- souleyez/handlers/nxc_handler.py +417 -0
- souleyez/handlers/rdp_sec_check_handler.py +353 -0
- souleyez/handlers/registry.py +292 -0
- souleyez/handlers/responder_handler.py +232 -0
- souleyez/handlers/service_explorer_handler.py +434 -0
- souleyez/handlers/smbclient_handler.py +344 -0
- souleyez/handlers/smbmap_handler.py +510 -0
- souleyez/handlers/smbpasswd_handler.py +296 -0
- souleyez/handlers/sqlmap_handler.py +1116 -0
- souleyez/handlers/theharvester_handler.py +601 -0
- souleyez/handlers/web_login_test_handler.py +327 -0
- souleyez/handlers/whois_handler.py +277 -0
- souleyez/handlers/wpscan_handler.py +554 -0
- souleyez/history.py +32 -16
- souleyez/importers/msf_importer.py +106 -75
- souleyez/importers/smart_importer.py +208 -147
- souleyez/integrations/siem/__init__.py +10 -10
- souleyez/integrations/siem/base.py +17 -18
- souleyez/integrations/siem/elastic.py +108 -122
- souleyez/integrations/siem/factory.py +207 -80
- souleyez/integrations/siem/googlesecops.py +146 -154
- souleyez/integrations/siem/rule_mappings/__init__.py +1 -1
- souleyez/integrations/siem/rule_mappings/wazuh_rules.py +8 -5
- souleyez/integrations/siem/sentinel.py +107 -109
- souleyez/integrations/siem/splunk.py +246 -212
- souleyez/integrations/siem/wazuh.py +65 -71
- souleyez/integrations/wazuh/__init__.py +5 -5
- souleyez/integrations/wazuh/client.py +70 -93
- souleyez/integrations/wazuh/config.py +85 -57
- souleyez/integrations/wazuh/host_mapper.py +28 -36
- souleyez/integrations/wazuh/sync.py +78 -68
- souleyez/intelligence/__init__.py +4 -5
- souleyez/intelligence/correlation_analyzer.py +309 -295
- souleyez/intelligence/exploit_knowledge.py +661 -623
- souleyez/intelligence/exploit_suggestions.py +159 -139
- souleyez/intelligence/gap_analyzer.py +132 -97
- souleyez/intelligence/gap_detector.py +251 -214
- souleyez/intelligence/sensitive_tables.py +266 -129
- souleyez/intelligence/service_parser.py +137 -123
- souleyez/intelligence/surface_analyzer.py +407 -268
- souleyez/intelligence/target_parser.py +159 -162
- souleyez/licensing/__init__.py +6 -6
- souleyez/licensing/validator.py +17 -19
- souleyez/log_config.py +79 -54
- souleyez/main.py +1505 -687
- souleyez/migrations/fix_job_counter.py +16 -14
- souleyez/parsers/bloodhound_parser.py +41 -39
- souleyez/parsers/crackmapexec_parser.py +178 -111
- souleyez/parsers/dalfox_parser.py +72 -77
- souleyez/parsers/dnsrecon_parser.py +103 -91
- souleyez/parsers/enum4linux_parser.py +183 -153
- souleyez/parsers/ffuf_parser.py +29 -25
- souleyez/parsers/gobuster_parser.py +301 -41
- souleyez/parsers/hashcat_parser.py +324 -79
- souleyez/parsers/http_fingerprint_parser.py +350 -103
- souleyez/parsers/hydra_parser.py +131 -111
- souleyez/parsers/impacket_parser.py +231 -178
- souleyez/parsers/john_parser.py +98 -86
- souleyez/parsers/katana_parser.py +316 -0
- souleyez/parsers/msf_parser.py +943 -498
- souleyez/parsers/nikto_parser.py +346 -65
- souleyez/parsers/nmap_parser.py +262 -174
- souleyez/parsers/nuclei_parser.py +40 -44
- souleyez/parsers/responder_parser.py +26 -26
- souleyez/parsers/searchsploit_parser.py +74 -74
- souleyez/parsers/service_explorer_parser.py +279 -0
- souleyez/parsers/smbmap_parser.py +180 -124
- souleyez/parsers/sqlmap_parser.py +434 -308
- souleyez/parsers/theharvester_parser.py +75 -57
- souleyez/parsers/whois_parser.py +135 -94
- souleyez/parsers/wpscan_parser.py +278 -190
- souleyez/plugins/afp.py +44 -36
- souleyez/plugins/afp_brute.py +114 -46
- souleyez/plugins/ard.py +48 -37
- souleyez/plugins/bloodhound.py +95 -61
- souleyez/plugins/certipy.py +303 -0
- souleyez/plugins/crackmapexec.py +186 -85
- souleyez/plugins/dalfox.py +120 -59
- souleyez/plugins/dns_hijack.py +146 -41
- souleyez/plugins/dnsrecon.py +97 -61
- souleyez/plugins/enum4linux.py +91 -66
- souleyez/plugins/evil_winrm.py +291 -0
- souleyez/plugins/ffuf.py +166 -90
- souleyez/plugins/firmware_extract.py +133 -29
- souleyez/plugins/gobuster.py +387 -190
- souleyez/plugins/gpp_extract.py +393 -0
- souleyez/plugins/hashcat.py +100 -73
- souleyez/plugins/http_fingerprint.py +913 -267
- souleyez/plugins/hydra.py +566 -200
- souleyez/plugins/impacket_getnpusers.py +117 -69
- souleyez/plugins/impacket_psexec.py +84 -64
- souleyez/plugins/impacket_secretsdump.py +103 -69
- souleyez/plugins/impacket_smbclient.py +89 -75
- souleyez/plugins/john.py +86 -69
- souleyez/plugins/katana.py +313 -0
- souleyez/plugins/kerbrute.py +237 -0
- souleyez/plugins/lfi_extract.py +541 -0
- souleyez/plugins/macos_ssh.py +117 -48
- souleyez/plugins/mdns.py +35 -30
- souleyez/plugins/msf_auxiliary.py +253 -130
- souleyez/plugins/msf_exploit.py +239 -161
- souleyez/plugins/nikto.py +134 -78
- souleyez/plugins/nmap.py +275 -91
- souleyez/plugins/nuclei.py +180 -89
- souleyez/plugins/nxc.py +285 -0
- souleyez/plugins/plugin_base.py +35 -36
- souleyez/plugins/plugin_template.py +13 -5
- souleyez/plugins/rdp_sec_check.py +130 -0
- souleyez/plugins/responder.py +112 -71
- souleyez/plugins/router_http_brute.py +76 -65
- souleyez/plugins/router_ssh_brute.py +118 -41
- souleyez/plugins/router_telnet_brute.py +124 -42
- souleyez/plugins/routersploit.py +91 -59
- souleyez/plugins/routersploit_exploit.py +77 -55
- souleyez/plugins/searchsploit.py +91 -77
- souleyez/plugins/service_explorer.py +1160 -0
- souleyez/plugins/smbmap.py +122 -72
- souleyez/plugins/smbpasswd.py +215 -0
- souleyez/plugins/sqlmap.py +301 -113
- souleyez/plugins/theharvester.py +127 -75
- souleyez/plugins/tr069.py +79 -57
- souleyez/plugins/upnp.py +65 -47
- souleyez/plugins/upnp_abuse.py +73 -55
- souleyez/plugins/vnc_access.py +129 -42
- souleyez/plugins/vnc_brute.py +109 -38
- souleyez/plugins/web_login_test.py +417 -0
- souleyez/plugins/whois.py +77 -58
- souleyez/plugins/wpscan.py +219 -69
- souleyez/reporting/__init__.py +2 -1
- souleyez/reporting/attack_chain.py +411 -346
- souleyez/reporting/charts.py +436 -501
- souleyez/reporting/compliance_mappings.py +334 -201
- souleyez/reporting/detection_report.py +126 -125
- souleyez/reporting/formatters.py +828 -591
- souleyez/reporting/generator.py +386 -302
- souleyez/reporting/metrics.py +72 -75
- souleyez/scanner.py +35 -29
- souleyez/security/__init__.py +37 -11
- souleyez/security/scope_validator.py +175 -106
- souleyez/security/validation.py +237 -149
- souleyez/security.py +22 -6
- souleyez/storage/credentials.py +247 -186
- souleyez/storage/crypto.py +296 -129
- souleyez/storage/database.py +73 -50
- souleyez/storage/db.py +58 -36
- souleyez/storage/deliverable_evidence.py +177 -128
- souleyez/storage/deliverable_exporter.py +282 -246
- souleyez/storage/deliverable_templates.py +134 -116
- souleyez/storage/deliverables.py +135 -130
- souleyez/storage/engagements.py +109 -56
- souleyez/storage/evidence.py +181 -152
- souleyez/storage/execution_log.py +31 -17
- souleyez/storage/exploit_attempts.py +93 -57
- souleyez/storage/exploits.py +67 -36
- souleyez/storage/findings.py +48 -61
- souleyez/storage/hosts.py +176 -144
- souleyez/storage/migrate_to_engagements.py +43 -19
- souleyez/storage/migrations/_001_add_credential_enhancements.py +22 -12
- souleyez/storage/migrations/_002_add_status_tracking.py +10 -7
- souleyez/storage/migrations/_003_add_execution_log.py +14 -8
- souleyez/storage/migrations/_005_screenshots.py +13 -5
- souleyez/storage/migrations/_006_deliverables.py +13 -5
- souleyez/storage/migrations/_007_deliverable_templates.py +12 -7
- souleyez/storage/migrations/_008_add_nuclei_table.py +10 -4
- souleyez/storage/migrations/_010_evidence_linking.py +17 -10
- souleyez/storage/migrations/_011_timeline_tracking.py +20 -13
- souleyez/storage/migrations/_012_team_collaboration.py +34 -21
- souleyez/storage/migrations/_013_add_host_tags.py +12 -6
- souleyez/storage/migrations/_014_exploit_attempts.py +22 -10
- souleyez/storage/migrations/_015_add_mac_os_fields.py +15 -7
- souleyez/storage/migrations/_016_add_domain_field.py +10 -4
- souleyez/storage/migrations/_017_msf_sessions.py +16 -8
- souleyez/storage/migrations/_018_add_osint_target.py +10 -6
- souleyez/storage/migrations/_019_add_engagement_type.py +10 -6
- souleyez/storage/migrations/_020_add_rbac.py +36 -15
- souleyez/storage/migrations/_021_wazuh_integration.py +20 -8
- souleyez/storage/migrations/_022_wazuh_indexer_columns.py +6 -4
- souleyez/storage/migrations/_023_fix_detection_results_fk.py +16 -6
- souleyez/storage/migrations/_024_wazuh_vulnerabilities.py +26 -10
- souleyez/storage/migrations/_025_multi_siem_support.py +3 -5
- souleyez/storage/migrations/_026_add_engagement_scope.py +31 -12
- souleyez/storage/migrations/_027_multi_siem_persistence.py +32 -15
- souleyez/storage/migrations/__init__.py +26 -26
- souleyez/storage/migrations/migration_manager.py +19 -19
- souleyez/storage/msf_sessions.py +100 -65
- souleyez/storage/osint.py +17 -24
- souleyez/storage/recommendation_engine.py +269 -235
- souleyez/storage/screenshots.py +33 -32
- souleyez/storage/smb_shares.py +136 -92
- souleyez/storage/sqlmap_data.py +183 -128
- souleyez/storage/team_collaboration.py +135 -141
- souleyez/storage/timeline_tracker.py +122 -94
- souleyez/storage/wazuh_vulns.py +64 -66
- souleyez/storage/web_paths.py +33 -37
- souleyez/testing/credential_tester.py +221 -205
- souleyez/ui/__init__.py +1 -1
- souleyez/ui/ai_quotes.py +12 -12
- souleyez/ui/attack_surface.py +2439 -1516
- souleyez/ui/chain_rules_view.py +914 -382
- souleyez/ui/correlation_view.py +312 -230
- souleyez/ui/dashboard.py +2382 -1130
- souleyez/ui/deliverables_view.py +148 -62
- souleyez/ui/design_system.py +13 -13
- souleyez/ui/errors.py +49 -49
- souleyez/ui/evidence_linking_view.py +284 -179
- souleyez/ui/evidence_vault.py +393 -285
- souleyez/ui/exploit_suggestions_view.py +555 -349
- souleyez/ui/export_view.py +100 -66
- souleyez/ui/gap_analysis_view.py +315 -171
- souleyez/ui/help_system.py +105 -97
- souleyez/ui/intelligence_view.py +436 -293
- souleyez/ui/interactive.py +23034 -10679
- souleyez/ui/interactive_selector.py +75 -68
- souleyez/ui/log_formatter.py +47 -39
- souleyez/ui/menu_components.py +22 -13
- souleyez/ui/msf_auxiliary_menu.py +184 -133
- souleyez/ui/pending_chains_view.py +336 -172
- souleyez/ui/progress_indicators.py +5 -3
- souleyez/ui/recommendations_view.py +195 -137
- souleyez/ui/rule_builder.py +343 -225
- souleyez/ui/setup_wizard.py +678 -284
- souleyez/ui/shortcuts.py +217 -165
- souleyez/ui/splunk_gap_analysis_view.py +452 -270
- souleyez/ui/splunk_vulns_view.py +139 -86
- souleyez/ui/team_dashboard.py +498 -335
- souleyez/ui/template_selector.py +196 -105
- souleyez/ui/terminal.py +6 -6
- souleyez/ui/timeline_view.py +198 -127
- souleyez/ui/tool_setup.py +264 -164
- souleyez/ui/tutorial.py +202 -72
- souleyez/ui/tutorial_state.py +40 -40
- souleyez/ui/wazuh_vulns_view.py +235 -141
- souleyez/ui/wordlist_browser.py +260 -107
- souleyez/ui.py +464 -312
- souleyez/utils/tool_checker.py +427 -367
- souleyez/utils.py +33 -29
- souleyez/wordlists.py +134 -167
- {souleyez-2.43.29.dist-info → souleyez-3.0.0.dist-info}/METADATA +2 -2
- souleyez-3.0.0.dist-info/RECORD +443 -0
- {souleyez-2.43.29.dist-info → souleyez-3.0.0.dist-info}/WHEEL +1 -1
- souleyez-2.43.29.dist-info/RECORD +0 -379
- {souleyez-2.43.29.dist-info → souleyez-3.0.0.dist-info}/entry_points.txt +0 -0
- {souleyez-2.43.29.dist-info → souleyez-3.0.0.dist-info}/licenses/LICENSE +0 -0
- {souleyez-2.43.29.dist-info → souleyez-3.0.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Metasploit exploit handler.
|
|
4
|
+
|
|
5
|
+
Consolidates parsing and display logic for msf_exploit jobs.
|
|
6
|
+
"""
|
|
7
|
+
import logging
|
|
8
|
+
import os
|
|
9
|
+
import re
|
|
10
|
+
from typing import Any, Dict, Optional
|
|
11
|
+
|
|
12
|
+
import click
|
|
13
|
+
|
|
14
|
+
from souleyez.engine.job_status import STATUS_DONE, STATUS_NO_RESULTS, STATUS_WARNING
|
|
15
|
+
from souleyez.handlers.base import BaseToolHandler
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class MsfExploitHandler(BaseToolHandler):
|
|
21
|
+
"""Handler for Metasploit exploit module jobs."""
|
|
22
|
+
|
|
23
|
+
tool_name = "msf_exploit"
|
|
24
|
+
display_name = "Metasploit Exploit"
|
|
25
|
+
|
|
26
|
+
# All handlers enabled
|
|
27
|
+
has_error_handler = True
|
|
28
|
+
has_warning_handler = True
|
|
29
|
+
has_no_results_handler = True
|
|
30
|
+
has_done_handler = True
|
|
31
|
+
|
|
32
|
+
# Success patterns for exploit output
|
|
33
|
+
SUCCESS_PATTERNS = [
|
|
34
|
+
r"\[\*\]\s+Command shell session \d+ opened",
|
|
35
|
+
r"\[\*\]\s+Meterpreter session \d+ opened",
|
|
36
|
+
r"\[\+\]\s+\d+\.\d+\.\d+\.\d+:\d+\s+-\s+Session \d+ created",
|
|
37
|
+
r"\[\+\].*shell.*opened",
|
|
38
|
+
r"\[\+\].*session.*created",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
# Failure patterns
|
|
42
|
+
FAILURE_PATTERNS = [
|
|
43
|
+
r"Exploit completed, but no session was created",
|
|
44
|
+
r"\[-\].*failed",
|
|
45
|
+
r"\[-\].*Exploit aborted",
|
|
46
|
+
r"\[-\].*not valid",
|
|
47
|
+
r"\[-\].*unreachable",
|
|
48
|
+
r"\[-\].*timed?\s*out",
|
|
49
|
+
r"\[-\].*ConnectionTimeout",
|
|
50
|
+
r"\[-\].*Connection refused",
|
|
51
|
+
r"No session was created",
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
def parse_job(
|
|
55
|
+
self,
|
|
56
|
+
engagement_id: int,
|
|
57
|
+
log_path: str,
|
|
58
|
+
job: Dict[str, Any],
|
|
59
|
+
host_manager: Optional[Any] = None,
|
|
60
|
+
findings_manager: Optional[Any] = None,
|
|
61
|
+
credentials_manager: Optional[Any] = None,
|
|
62
|
+
) -> Dict[str, Any]:
|
|
63
|
+
"""
|
|
64
|
+
Parse MSF exploit job results.
|
|
65
|
+
|
|
66
|
+
Extracts session info, success/failure status, and creates findings.
|
|
67
|
+
"""
|
|
68
|
+
try:
|
|
69
|
+
# Import managers if not provided (for backward compatibility)
|
|
70
|
+
if host_manager is None:
|
|
71
|
+
from souleyez.storage.hosts import HostManager
|
|
72
|
+
|
|
73
|
+
host_manager = HostManager()
|
|
74
|
+
if findings_manager is None:
|
|
75
|
+
from souleyez.storage.findings import FindingsManager
|
|
76
|
+
|
|
77
|
+
findings_manager = FindingsManager()
|
|
78
|
+
|
|
79
|
+
# Read the log file
|
|
80
|
+
with open(log_path, "r", encoding="utf-8", errors="replace") as f:
|
|
81
|
+
content = f.read()
|
|
82
|
+
|
|
83
|
+
target = job.get("target", "")
|
|
84
|
+
findings_added = 0
|
|
85
|
+
exploit_success = False
|
|
86
|
+
|
|
87
|
+
# Get or create host
|
|
88
|
+
host = host_manager.get_host_by_ip(engagement_id, target)
|
|
89
|
+
if not host:
|
|
90
|
+
host_id = host_manager.add_host(engagement_id, target)
|
|
91
|
+
else:
|
|
92
|
+
host_id = host["id"]
|
|
93
|
+
|
|
94
|
+
# Extract exploit name from header or args
|
|
95
|
+
exploit_match = re.search(r"Exploit:\s*(.+)$", content, re.MULTILINE)
|
|
96
|
+
exploit_name = (
|
|
97
|
+
exploit_match.group(1).strip() if exploit_match else "unknown"
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
# Check for successful exploitation
|
|
101
|
+
for pattern in self.SUCCESS_PATTERNS:
|
|
102
|
+
if re.search(pattern, content, re.IGNORECASE):
|
|
103
|
+
exploit_success = True
|
|
104
|
+
break
|
|
105
|
+
|
|
106
|
+
# Check for explicit failure
|
|
107
|
+
explicit_failure = False
|
|
108
|
+
failure_reason = None
|
|
109
|
+
for pattern in self.FAILURE_PATTERNS:
|
|
110
|
+
match = re.search(pattern, content, re.IGNORECASE)
|
|
111
|
+
if match:
|
|
112
|
+
explicit_failure = True
|
|
113
|
+
failure_reason = match.group(0).strip()
|
|
114
|
+
break
|
|
115
|
+
|
|
116
|
+
# Create finding based on result
|
|
117
|
+
if exploit_success:
|
|
118
|
+
session_match = re.search(
|
|
119
|
+
r"session (\d+) (opened|created)", content, re.IGNORECASE
|
|
120
|
+
)
|
|
121
|
+
session_info = (
|
|
122
|
+
f" (Session {session_match.group(1)})" if session_match else ""
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
findings_manager.add_finding(
|
|
126
|
+
engagement_id=engagement_id,
|
|
127
|
+
host_id=host_id,
|
|
128
|
+
title=f'Exploit Successful: {exploit_name.split("/")[-1]}',
|
|
129
|
+
finding_type="vulnerability",
|
|
130
|
+
severity="critical",
|
|
131
|
+
description=f"Successfully exploited {target} using {exploit_name}.{session_info}\n\nThis confirms the vulnerability is exploitable.",
|
|
132
|
+
tool="msf_exploit",
|
|
133
|
+
)
|
|
134
|
+
findings_added += 1
|
|
135
|
+
elif not explicit_failure:
|
|
136
|
+
# Check for [+] lines that might indicate partial success
|
|
137
|
+
plus_lines = re.findall(r"\[\+\]\s+(.+)", content)
|
|
138
|
+
if plus_lines:
|
|
139
|
+
for line in plus_lines[:3]:
|
|
140
|
+
findings_manager.add_finding(
|
|
141
|
+
engagement_id=engagement_id,
|
|
142
|
+
host_id=host_id,
|
|
143
|
+
title=f'{exploit_name.split("/")[-1]}: {line[:60]}',
|
|
144
|
+
finding_type="security_issue",
|
|
145
|
+
severity="medium",
|
|
146
|
+
description=f"Exploit output: {line}",
|
|
147
|
+
tool="msf_exploit",
|
|
148
|
+
)
|
|
149
|
+
findings_added += 1
|
|
150
|
+
|
|
151
|
+
# Determine final status and summary
|
|
152
|
+
if exploit_success:
|
|
153
|
+
final_status = STATUS_DONE
|
|
154
|
+
summary = f"Exploit successful: {exploit_name.split('/')[-1]}"
|
|
155
|
+
elif explicit_failure:
|
|
156
|
+
final_status = STATUS_WARNING
|
|
157
|
+
summary = self._format_failure_summary(failure_reason, exploit_name)
|
|
158
|
+
elif findings_added > 0:
|
|
159
|
+
final_status = STATUS_DONE
|
|
160
|
+
summary = f"Exploit output captured ({findings_added} findings)"
|
|
161
|
+
else:
|
|
162
|
+
final_status = STATUS_NO_RESULTS
|
|
163
|
+
summary = f"Exploit completed: no session or findings"
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
"tool": "msf_exploit",
|
|
167
|
+
"status": final_status,
|
|
168
|
+
"summary": summary,
|
|
169
|
+
"host": target,
|
|
170
|
+
"exploit": exploit_name,
|
|
171
|
+
"success": exploit_success,
|
|
172
|
+
"explicit_failure": explicit_failure,
|
|
173
|
+
"findings_added": findings_added,
|
|
174
|
+
}
|
|
175
|
+
except Exception as e:
|
|
176
|
+
logger.error(f"Error parsing msf_exploit job: {e}")
|
|
177
|
+
return {"error": str(e)}
|
|
178
|
+
|
|
179
|
+
def _format_failure_summary(
|
|
180
|
+
self, failure_reason: Optional[str], exploit_name: str
|
|
181
|
+
) -> str:
|
|
182
|
+
"""Format a human-readable failure summary."""
|
|
183
|
+
if not failure_reason:
|
|
184
|
+
return f"Exploit failed: {exploit_name.split('/')[-1]}"
|
|
185
|
+
|
|
186
|
+
reason_lower = failure_reason.lower()
|
|
187
|
+
if "no session was created" in reason_lower:
|
|
188
|
+
return "Exploit failed: no session created"
|
|
189
|
+
elif "unreachable" in reason_lower or "timed out" in reason_lower:
|
|
190
|
+
return "Exploit failed: target unreachable"
|
|
191
|
+
elif "not valid" in reason_lower:
|
|
192
|
+
return "Exploit failed: invalid configuration"
|
|
193
|
+
elif "connection refused" in reason_lower:
|
|
194
|
+
return "Exploit failed: connection refused"
|
|
195
|
+
else:
|
|
196
|
+
return f"Exploit failed: {failure_reason[:50]}"
|
|
197
|
+
|
|
198
|
+
def display_done(
|
|
199
|
+
self,
|
|
200
|
+
job: Dict[str, Any],
|
|
201
|
+
log_path: str,
|
|
202
|
+
show_all: bool = False,
|
|
203
|
+
show_passwords: bool = False,
|
|
204
|
+
) -> None:
|
|
205
|
+
"""Display successful exploit results."""
|
|
206
|
+
try:
|
|
207
|
+
from souleyez.parsers.msf_parser import parse_msf_log
|
|
208
|
+
|
|
209
|
+
if not log_path or not os.path.exists(log_path):
|
|
210
|
+
return
|
|
211
|
+
|
|
212
|
+
parsed = parse_msf_log(log_path)
|
|
213
|
+
sessions = parsed.get("sessions", [])
|
|
214
|
+
findings = parsed.get("findings", [])
|
|
215
|
+
|
|
216
|
+
if not sessions and not findings:
|
|
217
|
+
# Fall back to parse_result summary
|
|
218
|
+
parse_result = job.get("parse_result", {})
|
|
219
|
+
if isinstance(parse_result, dict) and parse_result.get("success"):
|
|
220
|
+
click.echo(click.style("=" * 70, fg="green"))
|
|
221
|
+
click.echo(
|
|
222
|
+
click.style("METASPLOIT EXPLOIT RESULTS", bold=True, fg="green")
|
|
223
|
+
)
|
|
224
|
+
click.echo(click.style("=" * 70, fg="green"))
|
|
225
|
+
click.echo()
|
|
226
|
+
click.echo(
|
|
227
|
+
click.style(
|
|
228
|
+
f" [SUCCESS] {parse_result.get('summary', 'Exploit successful')}",
|
|
229
|
+
fg="green",
|
|
230
|
+
)
|
|
231
|
+
)
|
|
232
|
+
click.echo()
|
|
233
|
+
click.echo(click.style("=" * 70, fg="green"))
|
|
234
|
+
click.echo()
|
|
235
|
+
return
|
|
236
|
+
|
|
237
|
+
click.echo(click.style("=" * 70, fg="green"))
|
|
238
|
+
click.echo(click.style("METASPLOIT EXPLOIT RESULTS", bold=True, fg="green"))
|
|
239
|
+
click.echo(click.style("=" * 70, fg="green"))
|
|
240
|
+
click.echo()
|
|
241
|
+
|
|
242
|
+
# Show sessions (most important)
|
|
243
|
+
if sessions:
|
|
244
|
+
click.echo(
|
|
245
|
+
click.style(
|
|
246
|
+
f"Sessions Created ({len(sessions)}):", bold=True, fg="green"
|
|
247
|
+
)
|
|
248
|
+
)
|
|
249
|
+
for s in sessions:
|
|
250
|
+
session_type = s.get("type", "unknown").title()
|
|
251
|
+
session_id = s.get("id", "?")
|
|
252
|
+
tunnel = s.get("tunnel", "unknown")
|
|
253
|
+
click.echo(
|
|
254
|
+
click.style(
|
|
255
|
+
f" [{session_id}] {session_type} session", fg="green"
|
|
256
|
+
)
|
|
257
|
+
+ f" - {tunnel}"
|
|
258
|
+
)
|
|
259
|
+
click.echo()
|
|
260
|
+
|
|
261
|
+
# Show findings
|
|
262
|
+
if findings:
|
|
263
|
+
severity_colors = {
|
|
264
|
+
"critical": "green",
|
|
265
|
+
"high": "red",
|
|
266
|
+
"medium": "yellow",
|
|
267
|
+
"low": "blue",
|
|
268
|
+
"info": "cyan",
|
|
269
|
+
}
|
|
270
|
+
for f in findings:
|
|
271
|
+
sev = f.get("severity", "info")
|
|
272
|
+
color = severity_colors.get(sev, "white")
|
|
273
|
+
title = f.get("title", "Unknown")
|
|
274
|
+
if "Successful" in title or "session" in title.lower():
|
|
275
|
+
click.echo(click.style(f" [SUCCESS] {title}", fg="green"))
|
|
276
|
+
elif "Failed" in title:
|
|
277
|
+
click.echo(click.style(f" [FAILED] {title}", fg="yellow"))
|
|
278
|
+
else:
|
|
279
|
+
click.echo(click.style(f" [{sev.upper()}] ", fg=color) + title)
|
|
280
|
+
click.echo()
|
|
281
|
+
|
|
282
|
+
click.echo(click.style("=" * 70, fg="green"))
|
|
283
|
+
click.echo()
|
|
284
|
+
except Exception as e:
|
|
285
|
+
logger.debug(f"Error in display_done: {e}")
|
|
286
|
+
|
|
287
|
+
def display_warning(
|
|
288
|
+
self,
|
|
289
|
+
job: Dict[str, Any],
|
|
290
|
+
log_path: str,
|
|
291
|
+
log_content: Optional[str] = None,
|
|
292
|
+
) -> None:
|
|
293
|
+
"""Display warning/failure status for exploit."""
|
|
294
|
+
parse_result = job.get("parse_result", {})
|
|
295
|
+
summary = "Exploit failed"
|
|
296
|
+
if isinstance(parse_result, dict):
|
|
297
|
+
summary = parse_result.get("summary", "Exploit failed")
|
|
298
|
+
|
|
299
|
+
click.echo(click.style("=" * 70, fg="yellow"))
|
|
300
|
+
click.echo(click.style("[FAILED] METASPLOIT EXPLOIT", bold=True, fg="yellow"))
|
|
301
|
+
click.echo(click.style("=" * 70, fg="yellow"))
|
|
302
|
+
click.echo()
|
|
303
|
+
click.echo(f" {summary}")
|
|
304
|
+
click.echo()
|
|
305
|
+
click.echo(click.style(" Common causes:", fg="bright_black"))
|
|
306
|
+
click.echo(
|
|
307
|
+
click.style(
|
|
308
|
+
" - Target unreachable (firewall, network issue)", fg="bright_black"
|
|
309
|
+
)
|
|
310
|
+
)
|
|
311
|
+
click.echo(
|
|
312
|
+
click.style(" - Service not running on expected port", fg="bright_black")
|
|
313
|
+
)
|
|
314
|
+
click.echo(
|
|
315
|
+
click.style(" - Connection timed out or refused", fg="bright_black")
|
|
316
|
+
)
|
|
317
|
+
click.echo()
|
|
318
|
+
click.echo(click.style("=" * 70, fg="yellow"))
|
|
319
|
+
click.echo()
|
|
320
|
+
|
|
321
|
+
def display_no_results(
|
|
322
|
+
self,
|
|
323
|
+
job: Dict[str, Any],
|
|
324
|
+
log_path: str,
|
|
325
|
+
) -> None:
|
|
326
|
+
"""Display no_results status for exploit."""
|
|
327
|
+
click.echo(click.style("=" * 70, fg="yellow"))
|
|
328
|
+
click.echo(click.style("METASPLOIT EXPLOIT RESULTS", bold=True, fg="yellow"))
|
|
329
|
+
click.echo(click.style("=" * 70, fg="yellow"))
|
|
330
|
+
click.echo()
|
|
331
|
+
click.echo(" No session was created.")
|
|
332
|
+
click.echo()
|
|
333
|
+
click.echo(click.style(" Possible reasons:", fg="bright_black"))
|
|
334
|
+
click.echo(
|
|
335
|
+
click.style(
|
|
336
|
+
" - Target is not vulnerable to this exploit", fg="bright_black"
|
|
337
|
+
)
|
|
338
|
+
)
|
|
339
|
+
click.echo(
|
|
340
|
+
click.style(
|
|
341
|
+
" - Exploit completed but payload failed to execute",
|
|
342
|
+
fg="bright_black",
|
|
343
|
+
)
|
|
344
|
+
)
|
|
345
|
+
click.echo(
|
|
346
|
+
click.style(
|
|
347
|
+
" - Target OS/version mismatch with exploit requirements",
|
|
348
|
+
fg="bright_black",
|
|
349
|
+
)
|
|
350
|
+
)
|
|
351
|
+
click.echo(
|
|
352
|
+
click.style(
|
|
353
|
+
" - Security controls blocked the exploit (AV, DEP, ASLR)",
|
|
354
|
+
fg="bright_black",
|
|
355
|
+
)
|
|
356
|
+
)
|
|
357
|
+
click.echo()
|
|
358
|
+
click.echo(click.style("=" * 70, fg="yellow"))
|
|
359
|
+
click.echo()
|
|
360
|
+
|
|
361
|
+
def display_error(
|
|
362
|
+
self,
|
|
363
|
+
job: Dict[str, Any],
|
|
364
|
+
log_path: str,
|
|
365
|
+
log_content: Optional[str] = None,
|
|
366
|
+
) -> None:
|
|
367
|
+
"""Display error status for exploit."""
|
|
368
|
+
parse_result = job.get("parse_result", {})
|
|
369
|
+
summary = "An error occurred during exploitation"
|
|
370
|
+
if isinstance(parse_result, dict):
|
|
371
|
+
summary = parse_result.get("summary", summary)
|
|
372
|
+
|
|
373
|
+
click.echo(click.style("=" * 70, fg="red"))
|
|
374
|
+
click.echo(click.style("[ERROR] METASPLOIT EXPLOIT", bold=True, fg="red"))
|
|
375
|
+
click.echo(click.style("=" * 70, fg="red"))
|
|
376
|
+
click.echo()
|
|
377
|
+
click.echo(f" {summary}")
|
|
378
|
+
click.echo()
|
|
379
|
+
click.echo(click.style("=" * 70, fg="red"))
|
|
380
|
+
click.echo()
|