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.
Potentially problematic release.
This version of souleyez might be problematic. Click here for more details.
- 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
|
@@ -22,7 +22,9 @@ class CredentialTester:
|
|
|
22
22
|
self.fm = FindingsManager()
|
|
23
23
|
self.em = EngagementManager()
|
|
24
24
|
|
|
25
|
-
def test_ssh_credential(
|
|
25
|
+
def test_ssh_credential(
|
|
26
|
+
self, host: str, username: str, password: str = None, timeout: int = 10
|
|
27
|
+
) -> Tuple[bool, str]:
|
|
26
28
|
"""
|
|
27
29
|
Test SSH credential against a host.
|
|
28
30
|
|
|
@@ -37,22 +39,26 @@ class CredentialTester:
|
|
|
37
39
|
# Use sshpass to test credentials non-interactively
|
|
38
40
|
# Add legacy crypto support for old SSH servers (like metasploitable)
|
|
39
41
|
cmd = [
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
"sshpass",
|
|
43
|
+
"-p",
|
|
44
|
+
password,
|
|
45
|
+
"ssh",
|
|
46
|
+
"-o",
|
|
47
|
+
"StrictHostKeyChecking=no",
|
|
48
|
+
"-o",
|
|
49
|
+
"ConnectTimeout=5",
|
|
50
|
+
"-o",
|
|
51
|
+
"HostKeyAlgorithms=+ssh-rsa",
|
|
52
|
+
f"{username}@{host}",
|
|
53
|
+
"echo",
|
|
54
|
+
"SUCCESS",
|
|
46
55
|
]
|
|
47
56
|
|
|
48
57
|
result = subprocess.run(
|
|
49
|
-
cmd,
|
|
50
|
-
capture_output=True,
|
|
51
|
-
text=True,
|
|
52
|
-
timeout=timeout
|
|
58
|
+
cmd, capture_output=True, text=True, timeout=timeout
|
|
53
59
|
)
|
|
54
60
|
|
|
55
|
-
if result.returncode == 0 and
|
|
61
|
+
if result.returncode == 0 and "SUCCESS" in result.stdout:
|
|
56
62
|
return (True, "SSH authentication successful")
|
|
57
63
|
else:
|
|
58
64
|
return (False, f"Authentication failed (rc={result.returncode})")
|
|
@@ -64,7 +70,9 @@ class CredentialTester:
|
|
|
64
70
|
except Exception as e:
|
|
65
71
|
return (False, f"Error: {str(e)}")
|
|
66
72
|
|
|
67
|
-
def test_smb_credential(
|
|
73
|
+
def test_smb_credential(
|
|
74
|
+
self, host: str, username: str, password: str = None, timeout: int = 10
|
|
75
|
+
) -> Tuple[bool, str]:
|
|
68
76
|
"""
|
|
69
77
|
Test SMB credential against a host.
|
|
70
78
|
|
|
@@ -77,17 +85,16 @@ class CredentialTester:
|
|
|
77
85
|
try:
|
|
78
86
|
# Use smbclient to test credentials
|
|
79
87
|
cmd = [
|
|
80
|
-
|
|
81
|
-
f
|
|
82
|
-
|
|
83
|
-
|
|
88
|
+
"smbclient",
|
|
89
|
+
f"//{host}/IPC$",
|
|
90
|
+
"-U",
|
|
91
|
+
f"{username}%{password}",
|
|
92
|
+
"-c",
|
|
93
|
+
"exit",
|
|
84
94
|
]
|
|
85
95
|
|
|
86
96
|
result = subprocess.run(
|
|
87
|
-
cmd,
|
|
88
|
-
capture_output=True,
|
|
89
|
-
text=True,
|
|
90
|
-
timeout=timeout
|
|
97
|
+
cmd, capture_output=True, text=True, timeout=timeout
|
|
91
98
|
)
|
|
92
99
|
|
|
93
100
|
# smbclient returns 0 on success
|
|
@@ -96,9 +103,9 @@ class CredentialTester:
|
|
|
96
103
|
else:
|
|
97
104
|
# Check for specific error messages
|
|
98
105
|
stderr = result.stderr.lower()
|
|
99
|
-
if
|
|
106
|
+
if "logon failure" in stderr or "access denied" in stderr:
|
|
100
107
|
return (False, "Invalid credentials")
|
|
101
|
-
elif
|
|
108
|
+
elif "connection refused" in stderr:
|
|
102
109
|
return (False, "SMB service not available")
|
|
103
110
|
else:
|
|
104
111
|
return (False, f"Authentication failed (rc={result.returncode})")
|
|
@@ -124,30 +131,30 @@ class CredentialTester:
|
|
|
124
131
|
'tested_at': str
|
|
125
132
|
}
|
|
126
133
|
"""
|
|
127
|
-
service = cred.get(
|
|
128
|
-
username = cred.get(
|
|
129
|
-
password = cred.get(
|
|
130
|
-
host_ip = host.get(
|
|
134
|
+
service = cred.get("service", "").lower()
|
|
135
|
+
username = cred.get("username")
|
|
136
|
+
password = cred.get("password")
|
|
137
|
+
host_ip = host.get("ip_address")
|
|
131
138
|
|
|
132
139
|
result = {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
140
|
+
"credential_id": cred.get("id"),
|
|
141
|
+
"host_id": host.get("id"),
|
|
142
|
+
"service": service,
|
|
143
|
+
"success": False,
|
|
144
|
+
"message": "Unknown service",
|
|
145
|
+
"tested_at": time.strftime("%Y-%m-%d %H:%M:%S UTC", time.gmtime()),
|
|
139
146
|
}
|
|
140
147
|
|
|
141
|
-
if service ==
|
|
148
|
+
if service == "ssh":
|
|
142
149
|
success, message = self.test_ssh_credential(host_ip, username, password)
|
|
143
|
-
result[
|
|
144
|
-
result[
|
|
145
|
-
elif service ==
|
|
150
|
+
result["success"] = success
|
|
151
|
+
result["message"] = message
|
|
152
|
+
elif service == "smb":
|
|
146
153
|
success, message = self.test_smb_credential(host_ip, username, password)
|
|
147
|
-
result[
|
|
148
|
-
result[
|
|
154
|
+
result["success"] = success
|
|
155
|
+
result["message"] = message
|
|
149
156
|
else:
|
|
150
|
-
result[
|
|
157
|
+
result["message"] = f"Testing not implemented for service: {service}"
|
|
151
158
|
|
|
152
159
|
return result
|
|
153
160
|
|
|
@@ -169,79 +176,78 @@ class CredentialTester:
|
|
|
169
176
|
hosts = self.hm.list_hosts(engagement_id)
|
|
170
177
|
|
|
171
178
|
# Filter to only active hosts
|
|
172
|
-
active_hosts = [h for h in hosts if h.get(
|
|
179
|
+
active_hosts = [h for h in hosts if h.get("status") == "up"]
|
|
173
180
|
|
|
174
181
|
results = {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
182
|
+
"total_tests": 0,
|
|
183
|
+
"successful": 0,
|
|
184
|
+
"failed": 0,
|
|
185
|
+
"findings_created": 0,
|
|
186
|
+
"results": [],
|
|
180
187
|
}
|
|
181
188
|
|
|
182
189
|
# Test each credential against each host
|
|
183
190
|
for cred in credentials:
|
|
184
191
|
# Skip username-only credentials for now (need password to test)
|
|
185
|
-
if not cred.get(
|
|
192
|
+
if not cred.get("password"):
|
|
186
193
|
continue
|
|
187
194
|
|
|
188
|
-
service = cred.get(
|
|
195
|
+
service = cred.get("service", "").lower()
|
|
189
196
|
|
|
190
197
|
for host in active_hosts:
|
|
191
198
|
# Only test if host has the service running
|
|
192
199
|
if not self._host_has_service(host, service, engagement_id):
|
|
193
200
|
continue
|
|
194
201
|
|
|
195
|
-
results[
|
|
202
|
+
results["total_tests"] += 1
|
|
196
203
|
|
|
197
204
|
# Test the credential
|
|
198
205
|
test_result = self.test_credential_against_host(cred, host)
|
|
199
|
-
results[
|
|
206
|
+
results["results"].append(test_result)
|
|
200
207
|
|
|
201
|
-
if test_result[
|
|
202
|
-
results[
|
|
208
|
+
if test_result["success"]:
|
|
209
|
+
results["successful"] += 1
|
|
203
210
|
|
|
204
211
|
# Create a finding for successful authentication
|
|
205
212
|
finding = self._create_finding_for_success(
|
|
206
|
-
engagement_id,
|
|
207
|
-
host,
|
|
208
|
-
cred,
|
|
209
|
-
test_result
|
|
213
|
+
engagement_id, host, cred, test_result
|
|
210
214
|
)
|
|
211
215
|
if finding:
|
|
212
|
-
results[
|
|
216
|
+
results["findings_created"] += 1
|
|
213
217
|
else:
|
|
214
|
-
results[
|
|
218
|
+
results["failed"] += 1
|
|
215
219
|
|
|
216
220
|
return results
|
|
217
221
|
|
|
218
222
|
def _host_has_service(self, host: Dict, service: str, engagement_id: int) -> bool:
|
|
219
223
|
"""Check if a host has a specific service running."""
|
|
220
224
|
# Get services for this host from HostManager
|
|
221
|
-
services = self.hm.get_host_services(host.get(
|
|
225
|
+
services = self.hm.get_host_services(host.get("id"))
|
|
222
226
|
|
|
223
227
|
# Check if service type matches
|
|
224
228
|
service_ports = {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
229
|
+
"ssh": [22],
|
|
230
|
+
"smb": [139, 445],
|
|
231
|
+
"rdp": [3389],
|
|
232
|
+
"ftp": [21],
|
|
233
|
+
"mysql": [3306],
|
|
234
|
+
"postgres": [5432],
|
|
231
235
|
}
|
|
232
236
|
|
|
233
237
|
target_ports = service_ports.get(service, [])
|
|
234
238
|
for svc in services:
|
|
235
|
-
if svc.get(
|
|
239
|
+
if svc.get("port") in target_ports:
|
|
236
240
|
return True
|
|
237
241
|
|
|
238
242
|
return False
|
|
239
243
|
|
|
240
|
-
def _create_finding_for_success(
|
|
244
|
+
def _create_finding_for_success(
|
|
245
|
+
self, engagement_id: int, host: Dict, cred: Dict, test_result: Dict
|
|
246
|
+
) -> Optional[Dict]:
|
|
241
247
|
"""Create a finding for successful credential test."""
|
|
242
|
-
service = cred.get(
|
|
243
|
-
username = cred.get(
|
|
244
|
-
host_ip = host.get(
|
|
248
|
+
service = cred.get("service", "unknown")
|
|
249
|
+
username = cred.get("username", "unknown")
|
|
250
|
+
host_ip = host.get("ip_address", "unknown")
|
|
245
251
|
|
|
246
252
|
title = f"Valid {service.upper()} Credentials - {username}@{host_ip}"
|
|
247
253
|
description = f"""
|
|
@@ -274,11 +280,11 @@ An attacker with these credentials can:
|
|
|
274
280
|
finding = self.fm.add_finding(
|
|
275
281
|
engagement_id,
|
|
276
282
|
title,
|
|
277
|
-
|
|
283
|
+
"vulnerability", # finding_type
|
|
278
284
|
severity=severity,
|
|
279
285
|
description=description.strip(),
|
|
280
|
-
host_id=host.get(
|
|
281
|
-
tool=
|
|
286
|
+
host_id=host.get("id"),
|
|
287
|
+
tool="credential_tester",
|
|
282
288
|
)
|
|
283
289
|
return finding
|
|
284
290
|
except Exception as e:
|
|
@@ -287,22 +293,22 @@ An attacker with these credentials can:
|
|
|
287
293
|
|
|
288
294
|
def _determine_credential_severity(self, cred: Dict, host: Dict) -> str:
|
|
289
295
|
"""Determine severity based on credential and host context."""
|
|
290
|
-
username = cred.get(
|
|
291
|
-
password = cred.get(
|
|
296
|
+
username = cred.get("username", "").lower()
|
|
297
|
+
password = cred.get("password", "")
|
|
292
298
|
|
|
293
299
|
# High severity for privileged accounts
|
|
294
|
-
privileged_users = [
|
|
300
|
+
privileged_users = ["root", "admin", "administrator", "sa", "postgres", "mysql"]
|
|
295
301
|
if username in privileged_users:
|
|
296
|
-
return
|
|
302
|
+
return "high"
|
|
297
303
|
|
|
298
304
|
# High severity for weak/default passwords
|
|
299
|
-
weak_passwords = [
|
|
305
|
+
weak_passwords = ["password", "admin", "123456", "root", "toor", "changeme", ""]
|
|
300
306
|
if password.lower() in weak_passwords:
|
|
301
|
-
return
|
|
307
|
+
return "high"
|
|
302
308
|
|
|
303
309
|
# High severity for short passwords
|
|
304
310
|
if len(password) < 8:
|
|
305
|
-
return
|
|
311
|
+
return "high"
|
|
306
312
|
|
|
307
313
|
# Medium severity for standard users
|
|
308
|
-
return
|
|
314
|
+
return "medium"
|