souleyez 2.43.26__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 +23434 -10286
- 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.26.dist-info → souleyez-2.43.34.dist-info}/METADATA +1 -1
- souleyez-2.43.34.dist-info/RECORD +443 -0
- {souleyez-2.43.26.dist-info → souleyez-2.43.34.dist-info}/WHEEL +1 -1
- souleyez-2.43.26.dist-info/RECORD +0 -379
- {souleyez-2.43.26.dist-info → souleyez-2.43.34.dist-info}/entry_points.txt +0 -0
- {souleyez-2.43.26.dist-info → souleyez-2.43.34.dist-info}/licenses/LICENSE +0 -0
- {souleyez-2.43.26.dist-info → souleyez-2.43.34.dist-info}/top_level.txt +0 -0
|
@@ -28,11 +28,11 @@ class MSFImporter:
|
|
|
28
28
|
self.fm = FindingsManager()
|
|
29
29
|
|
|
30
30
|
self.stats = {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
"hosts": 0,
|
|
32
|
+
"services": 0,
|
|
33
|
+
"credentials": 0,
|
|
34
|
+
"vulnerabilities": 0,
|
|
35
|
+
"skipped": 0,
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
def import_xml(self, xml_file: str, verbose: bool = False) -> Dict:
|
|
@@ -61,7 +61,7 @@ class MSFImporter:
|
|
|
61
61
|
click.echo("XML parsed successfully")
|
|
62
62
|
|
|
63
63
|
# Import hosts first
|
|
64
|
-
hosts = root.findall(
|
|
64
|
+
hosts = root.findall(".//host")
|
|
65
65
|
if verbose:
|
|
66
66
|
click.echo(f"\nFound {len(hosts)} hosts")
|
|
67
67
|
|
|
@@ -70,7 +70,11 @@ class MSFImporter:
|
|
|
70
70
|
for host_elem in hosts:
|
|
71
71
|
host_id = self._import_host(host_elem, verbose)
|
|
72
72
|
if host_id:
|
|
73
|
-
address =
|
|
73
|
+
address = (
|
|
74
|
+
host_elem.find("address").text
|
|
75
|
+
if host_elem.find("address") is not None
|
|
76
|
+
else None
|
|
77
|
+
)
|
|
74
78
|
if address:
|
|
75
79
|
host_mapping[address] = host_id
|
|
76
80
|
|
|
@@ -79,14 +83,18 @@ class MSFImporter:
|
|
|
79
83
|
click.echo("\nImporting services...")
|
|
80
84
|
|
|
81
85
|
for host_elem in hosts:
|
|
82
|
-
address =
|
|
86
|
+
address = (
|
|
87
|
+
host_elem.find("address").text
|
|
88
|
+
if host_elem.find("address") is not None
|
|
89
|
+
else None
|
|
90
|
+
)
|
|
83
91
|
if address and address in host_mapping:
|
|
84
|
-
services = host_elem.findall(
|
|
92
|
+
services = host_elem.findall(".//service")
|
|
85
93
|
for svc_elem in services:
|
|
86
94
|
self._import_service(svc_elem, host_mapping[address], verbose)
|
|
87
95
|
|
|
88
96
|
# Import credentials
|
|
89
|
-
creds = root.findall(
|
|
97
|
+
creds = root.findall(".//cred")
|
|
90
98
|
if verbose and creds:
|
|
91
99
|
click.echo(f"\nFound {len(creds)} credentials")
|
|
92
100
|
|
|
@@ -94,8 +102,8 @@ class MSFImporter:
|
|
|
94
102
|
self._import_credential(cred_elem, host_mapping, verbose)
|
|
95
103
|
|
|
96
104
|
# Import vulnerabilities/notes as findings
|
|
97
|
-
vulns = root.findall(
|
|
98
|
-
notes = root.findall(
|
|
105
|
+
vulns = root.findall(".//vuln")
|
|
106
|
+
notes = root.findall(".//note")
|
|
99
107
|
|
|
100
108
|
if verbose and (vulns or notes):
|
|
101
109
|
click.echo(f"\nFound {len(vulns)} vulnerabilities and {len(notes)} notes")
|
|
@@ -105,20 +113,22 @@ class MSFImporter:
|
|
|
105
113
|
|
|
106
114
|
return self.stats
|
|
107
115
|
|
|
108
|
-
def _import_host(
|
|
116
|
+
def _import_host(
|
|
117
|
+
self, host_elem: "Element", verbose: bool = False
|
|
118
|
+
) -> Optional[int]:
|
|
109
119
|
"""Import a single host."""
|
|
110
|
-
address = host_elem.find(
|
|
120
|
+
address = host_elem.find("address")
|
|
111
121
|
if address is None or not address.text:
|
|
112
|
-
self.stats[
|
|
122
|
+
self.stats["skipped"] += 1
|
|
113
123
|
return None
|
|
114
124
|
|
|
115
125
|
ip_address = address.text
|
|
116
126
|
# mac = host_elem.find('mac') # not used currently
|
|
117
127
|
|
|
118
128
|
# Get OS info
|
|
119
|
-
os_name_elem = host_elem.find(
|
|
120
|
-
os_flavor_elem = host_elem.find(
|
|
121
|
-
os_sp_elem = host_elem.find(
|
|
129
|
+
os_name_elem = host_elem.find("os-name")
|
|
130
|
+
os_flavor_elem = host_elem.find("os-flavor")
|
|
131
|
+
os_sp_elem = host_elem.find("os-sp")
|
|
122
132
|
|
|
123
133
|
os_parts = []
|
|
124
134
|
if os_name_elem is not None and os_name_elem.text:
|
|
@@ -128,35 +138,37 @@ class MSFImporter:
|
|
|
128
138
|
if os_sp_elem is not None and os_sp_elem.text:
|
|
129
139
|
os_parts.append(os_sp_elem.text)
|
|
130
140
|
|
|
131
|
-
os_name =
|
|
141
|
+
os_name = " ".join(os_parts) if os_parts else None
|
|
132
142
|
|
|
133
143
|
# Get hostname
|
|
134
|
-
name_elem = host_elem.find(
|
|
144
|
+
name_elem = host_elem.find("name")
|
|
135
145
|
hostname = name_elem.text if name_elem is not None and name_elem.text else None
|
|
136
146
|
|
|
137
147
|
# Check host state
|
|
138
|
-
state_elem = host_elem.find(
|
|
139
|
-
state = state_elem.text if state_elem is not None else
|
|
148
|
+
state_elem = host_elem.find("state")
|
|
149
|
+
state = state_elem.text if state_elem is not None else "up"
|
|
140
150
|
|
|
141
151
|
if verbose:
|
|
142
152
|
click.echo(f" Importing host: {ip_address} ({hostname or 'no hostname'})")
|
|
143
153
|
|
|
144
154
|
# Add or update host
|
|
145
155
|
host_data = {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
156
|
+
"ip": ip_address,
|
|
157
|
+
"hostname": hostname,
|
|
158
|
+
"os": os_name,
|
|
159
|
+
"status": state,
|
|
150
160
|
}
|
|
151
161
|
|
|
152
162
|
host_id = self.hm.add_or_update_host(self.engagement_id, host_data)
|
|
153
163
|
|
|
154
|
-
self.stats[
|
|
164
|
+
self.stats["hosts"] += 1
|
|
155
165
|
return host_id
|
|
156
166
|
|
|
157
|
-
def _import_service(
|
|
167
|
+
def _import_service(
|
|
168
|
+
self, svc_elem: "Element", host_id: int, verbose: bool = False
|
|
169
|
+
) -> Optional[int]:
|
|
158
170
|
"""Import a single service."""
|
|
159
|
-
port_elem = svc_elem.find(
|
|
171
|
+
port_elem = svc_elem.find("port")
|
|
160
172
|
if port_elem is None or not port_elem.text:
|
|
161
173
|
return None
|
|
162
174
|
|
|
@@ -165,41 +177,49 @@ class MSFImporter:
|
|
|
165
177
|
except ValueError:
|
|
166
178
|
return None
|
|
167
179
|
|
|
168
|
-
proto_elem = svc_elem.find(
|
|
169
|
-
protocol =
|
|
180
|
+
proto_elem = svc_elem.find("proto")
|
|
181
|
+
protocol = (
|
|
182
|
+
proto_elem.text if proto_elem is not None and proto_elem.text else "tcp"
|
|
183
|
+
)
|
|
170
184
|
|
|
171
|
-
name_elem = svc_elem.find(
|
|
172
|
-
service_name =
|
|
185
|
+
name_elem = svc_elem.find("name")
|
|
186
|
+
service_name = (
|
|
187
|
+
name_elem.text if name_elem is not None and name_elem.text else "unknown"
|
|
188
|
+
)
|
|
173
189
|
|
|
174
190
|
# Get service info/version
|
|
175
|
-
info_elem = svc_elem.find(
|
|
176
|
-
service_version =
|
|
191
|
+
info_elem = svc_elem.find("info")
|
|
192
|
+
service_version = (
|
|
193
|
+
info_elem.text if info_elem is not None and info_elem.text else None
|
|
194
|
+
)
|
|
177
195
|
|
|
178
|
-
state_elem = svc_elem.find(
|
|
179
|
-
state = state_elem.text if state_elem is not None else
|
|
196
|
+
state_elem = svc_elem.find("state")
|
|
197
|
+
state = state_elem.text if state_elem is not None else "open"
|
|
180
198
|
|
|
181
199
|
if verbose:
|
|
182
200
|
click.echo(f" Service: {port}/{protocol} ({service_name})")
|
|
183
201
|
|
|
184
202
|
# Add service
|
|
185
203
|
service_data = {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
204
|
+
"port": port,
|
|
205
|
+
"protocol": protocol,
|
|
206
|
+
"state": state,
|
|
207
|
+
"service": service_name,
|
|
208
|
+
"version": service_version,
|
|
191
209
|
}
|
|
192
210
|
|
|
193
211
|
self.hm.add_service(host_id, service_data)
|
|
194
212
|
|
|
195
|
-
self.stats[
|
|
213
|
+
self.stats["services"] += 1
|
|
196
214
|
return port
|
|
197
215
|
|
|
198
|
-
def _import_credential(
|
|
216
|
+
def _import_credential(
|
|
217
|
+
self, cred_elem: "Element", host_mapping: Dict, verbose: bool = False
|
|
218
|
+
):
|
|
199
219
|
"""Import a single credential."""
|
|
200
220
|
# Get credential details
|
|
201
|
-
user_elem = cred_elem.find(
|
|
202
|
-
pass_elem = cred_elem.find(
|
|
221
|
+
user_elem = cred_elem.find(".//username")
|
|
222
|
+
pass_elem = cred_elem.find(".//password")
|
|
203
223
|
# type_elem = cred_elem.find('.//type') # not used currently
|
|
204
224
|
|
|
205
225
|
username = user_elem.text if user_elem is not None and user_elem.text else None
|
|
@@ -210,21 +230,21 @@ class MSFImporter:
|
|
|
210
230
|
return
|
|
211
231
|
|
|
212
232
|
# Try to get associated service info
|
|
213
|
-
service_elem = cred_elem.find(
|
|
214
|
-
host_elem = cred_elem.find(
|
|
233
|
+
service_elem = cred_elem.find(".//service")
|
|
234
|
+
host_elem = cred_elem.find(".//host")
|
|
215
235
|
|
|
216
236
|
ip_address = None
|
|
217
237
|
service_name = None
|
|
218
238
|
port = None
|
|
219
239
|
|
|
220
240
|
if host_elem is not None:
|
|
221
|
-
address_elem = host_elem.find(
|
|
241
|
+
address_elem = host_elem.find("address")
|
|
222
242
|
if address_elem is not None:
|
|
223
243
|
ip_address = address_elem.text
|
|
224
244
|
|
|
225
245
|
if service_elem is not None:
|
|
226
|
-
name_elem = service_elem.find(
|
|
227
|
-
port_elem = service_elem.find(
|
|
246
|
+
name_elem = service_elem.find("name")
|
|
247
|
+
port_elem = service_elem.find("port")
|
|
228
248
|
|
|
229
249
|
if name_elem is not None:
|
|
230
250
|
service_name = name_elem.text
|
|
@@ -235,7 +255,7 @@ class MSFImporter:
|
|
|
235
255
|
pass
|
|
236
256
|
|
|
237
257
|
# Determine status - if we have a password, assume it's valid
|
|
238
|
-
status =
|
|
258
|
+
status = "valid" if password else "discovered"
|
|
239
259
|
|
|
240
260
|
# Get host_id from IP
|
|
241
261
|
host_id = None
|
|
@@ -263,26 +283,28 @@ class MSFImporter:
|
|
|
263
283
|
service=service_name,
|
|
264
284
|
port=port,
|
|
265
285
|
status=status,
|
|
266
|
-
tool=
|
|
286
|
+
tool="msf_import",
|
|
267
287
|
)
|
|
268
288
|
|
|
269
|
-
self.stats[
|
|
289
|
+
self.stats["credentials"] += 1
|
|
270
290
|
|
|
271
|
-
def _import_vulnerability(
|
|
291
|
+
def _import_vulnerability(
|
|
292
|
+
self, vuln_elem: "Element", host_mapping: Dict, verbose: bool = False
|
|
293
|
+
):
|
|
272
294
|
"""Import a vulnerability as a finding."""
|
|
273
|
-
name_elem = vuln_elem.find(
|
|
295
|
+
name_elem = vuln_elem.find("name")
|
|
274
296
|
if name_elem is None or not name_elem.text:
|
|
275
297
|
return
|
|
276
298
|
|
|
277
299
|
title = name_elem.text
|
|
278
300
|
|
|
279
301
|
# Get host
|
|
280
|
-
host_elem = vuln_elem.find(
|
|
302
|
+
host_elem = vuln_elem.find("host")
|
|
281
303
|
ip_address = None
|
|
282
304
|
host_id = None
|
|
283
305
|
|
|
284
306
|
if host_elem is not None:
|
|
285
|
-
address_elem = host_elem.find(
|
|
307
|
+
address_elem = host_elem.find("address")
|
|
286
308
|
if address_elem is not None and address_elem.text:
|
|
287
309
|
ip_address = address_elem.text
|
|
288
310
|
host_id = host_mapping.get(ip_address)
|
|
@@ -291,7 +313,7 @@ class MSFImporter:
|
|
|
291
313
|
return
|
|
292
314
|
|
|
293
315
|
# Get port
|
|
294
|
-
port_elem = vuln_elem.find(
|
|
316
|
+
port_elem = vuln_elem.find("port")
|
|
295
317
|
port = None
|
|
296
318
|
if port_elem is not None and port_elem.text:
|
|
297
319
|
try:
|
|
@@ -300,18 +322,22 @@ class MSFImporter:
|
|
|
300
322
|
pass
|
|
301
323
|
|
|
302
324
|
# Get refs
|
|
303
|
-
refs_elem = vuln_elem.find(
|
|
325
|
+
refs_elem = vuln_elem.find("refs")
|
|
304
326
|
refs = []
|
|
305
327
|
if refs_elem is not None:
|
|
306
|
-
for ref_elem in refs_elem.findall(
|
|
328
|
+
for ref_elem in refs_elem.findall("ref"):
|
|
307
329
|
if ref_elem.text:
|
|
308
330
|
refs.append(ref_elem.text)
|
|
309
331
|
|
|
310
|
-
refs_text =
|
|
332
|
+
refs_text = "\n".join(refs) if refs else None
|
|
311
333
|
|
|
312
334
|
# Get info/description
|
|
313
|
-
info_elem = vuln_elem.find(
|
|
314
|
-
description =
|
|
335
|
+
info_elem = vuln_elem.find("info")
|
|
336
|
+
description = (
|
|
337
|
+
info_elem.text
|
|
338
|
+
if info_elem is not None and info_elem.text
|
|
339
|
+
else f"Vulnerability: {title}"
|
|
340
|
+
)
|
|
315
341
|
|
|
316
342
|
# Try to determine severity from name/refs
|
|
317
343
|
severity = self._determine_severity(title, refs_text)
|
|
@@ -323,38 +349,43 @@ class MSFImporter:
|
|
|
323
349
|
self.fm.add_finding(
|
|
324
350
|
engagement_id=self.engagement_id,
|
|
325
351
|
title=title,
|
|
326
|
-
finding_type=
|
|
352
|
+
finding_type="vulnerability",
|
|
327
353
|
severity=severity,
|
|
328
354
|
description=description,
|
|
329
355
|
host_id=host_id,
|
|
330
356
|
port=port,
|
|
331
|
-
tool=
|
|
332
|
-
refs=refs_text
|
|
357
|
+
tool="msf_import",
|
|
358
|
+
refs=refs_text,
|
|
333
359
|
)
|
|
334
360
|
|
|
335
|
-
self.stats[
|
|
361
|
+
self.stats["vulnerabilities"] += 1
|
|
336
362
|
|
|
337
363
|
def _determine_severity(self, title: str, refs: Optional[str]) -> str:
|
|
338
364
|
"""Try to determine severity from vulnerability title and references."""
|
|
339
365
|
title_lower = title.lower()
|
|
340
|
-
refs_lower = refs.lower() if refs else
|
|
366
|
+
refs_lower = refs.lower() if refs else ""
|
|
341
367
|
|
|
342
368
|
# Critical indicators
|
|
343
|
-
critical_keywords = [
|
|
369
|
+
critical_keywords = [
|
|
370
|
+
"rce",
|
|
371
|
+
"remote code execution",
|
|
372
|
+
"unauthenticated",
|
|
373
|
+
"critical",
|
|
374
|
+
]
|
|
344
375
|
for keyword in critical_keywords:
|
|
345
376
|
if keyword in title_lower:
|
|
346
|
-
return
|
|
377
|
+
return "critical"
|
|
347
378
|
|
|
348
379
|
# High indicators
|
|
349
|
-
high_keywords = [
|
|
380
|
+
high_keywords = ["exploit", "overflow", "injection", "authentication bypass"]
|
|
350
381
|
for keyword in high_keywords:
|
|
351
382
|
if keyword in title_lower:
|
|
352
|
-
return
|
|
383
|
+
return "high"
|
|
353
384
|
|
|
354
385
|
# Check CVE scores (if available in refs)
|
|
355
|
-
if
|
|
386
|
+
if "cvss" in refs_lower:
|
|
356
387
|
# Could parse CVSS scores here
|
|
357
388
|
pass
|
|
358
389
|
|
|
359
390
|
# Default to medium for vulnerabilities
|
|
360
|
-
return
|
|
391
|
+
return "medium"
|