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/engine/base.py
CHANGED
|
@@ -17,9 +17,12 @@ class ScannerPlugin:
|
|
|
17
17
|
- prepare(target, args, label) -> dict (optional)
|
|
18
18
|
- run(prepared) -> ScanResult
|
|
19
19
|
"""
|
|
20
|
+
|
|
20
21
|
name = "base"
|
|
21
22
|
|
|
22
|
-
def prepare(
|
|
23
|
+
def prepare(
|
|
24
|
+
self, target: str, args: list, label: Optional[str] = None
|
|
25
|
+
) -> Dict[str, Any]:
|
|
23
26
|
return {"target": target, "args": args, "label": label}
|
|
24
27
|
|
|
25
28
|
def run(self, prepared: Dict[str, Any]) -> ScanResult:
|
souleyez/engine/job_status.py
CHANGED
|
@@ -6,13 +6,13 @@ Defines the status lifecycle for jobs in the system.
|
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
# Job status constants
|
|
9
|
-
STATUS_QUEUED =
|
|
10
|
-
STATUS_RUNNING =
|
|
11
|
-
STATUS_DONE =
|
|
12
|
-
STATUS_NO_RESULTS =
|
|
13
|
-
STATUS_WARNING =
|
|
14
|
-
STATUS_ERROR =
|
|
15
|
-
STATUS_KILLED =
|
|
9
|
+
STATUS_QUEUED = "queued" # Job waiting to execute
|
|
10
|
+
STATUS_RUNNING = "running" # Job actively executing
|
|
11
|
+
STATUS_DONE = "done" # Completed successfully WITH results
|
|
12
|
+
STATUS_NO_RESULTS = "no_results" # Completed successfully but found NOTHING
|
|
13
|
+
STATUS_WARNING = "warning" # Partial success or non-critical issues
|
|
14
|
+
STATUS_ERROR = "error" # TRUE failures (crashes, timeouts, invalid args)
|
|
15
|
+
STATUS_KILLED = "killed" # User terminated
|
|
16
16
|
|
|
17
17
|
# Valid status values
|
|
18
18
|
VALID_STATUSES = {
|
|
@@ -36,9 +36,9 @@ TERMINAL_STATUSES = {
|
|
|
36
36
|
|
|
37
37
|
# Statuses that should trigger auto-chaining
|
|
38
38
|
CHAINABLE_STATUSES = {
|
|
39
|
-
STATUS_DONE,
|
|
39
|
+
STATUS_DONE, # Always chain - results found
|
|
40
40
|
STATUS_NO_RESULTS, # May chain if intelligence-driven
|
|
41
|
-
STATUS_WARNING,
|
|
41
|
+
STATUS_WARNING, # May chain with special handling
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
|
|
@@ -60,45 +60,13 @@ def get_status_display_info(status: str) -> dict:
|
|
|
60
60
|
dict with 'color', 'icon', and 'label' keys
|
|
61
61
|
"""
|
|
62
62
|
status_info = {
|
|
63
|
-
STATUS_QUEUED: {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
},
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
'icon': '▶',
|
|
71
|
-
'label': 'running'
|
|
72
|
-
},
|
|
73
|
-
STATUS_DONE: {
|
|
74
|
-
'color': 'green',
|
|
75
|
-
'icon': '✓',
|
|
76
|
-
'label': 'done'
|
|
77
|
-
},
|
|
78
|
-
STATUS_NO_RESULTS: {
|
|
79
|
-
'color': 'white',
|
|
80
|
-
'icon': '⊘',
|
|
81
|
-
'label': 'no results'
|
|
82
|
-
},
|
|
83
|
-
STATUS_WARNING: {
|
|
84
|
-
'color': 'yellow',
|
|
85
|
-
'icon': '⚠',
|
|
86
|
-
'label': 'warning'
|
|
87
|
-
},
|
|
88
|
-
STATUS_ERROR: {
|
|
89
|
-
'color': 'red',
|
|
90
|
-
'icon': '✗',
|
|
91
|
-
'label': 'error'
|
|
92
|
-
},
|
|
93
|
-
STATUS_KILLED: {
|
|
94
|
-
'color': 'magenta',
|
|
95
|
-
'icon': '●',
|
|
96
|
-
'label': 'killed'
|
|
97
|
-
},
|
|
63
|
+
STATUS_QUEUED: {"color": "cyan", "icon": "◷", "label": "queued"},
|
|
64
|
+
STATUS_RUNNING: {"color": "yellow", "icon": "▶", "label": "running"},
|
|
65
|
+
STATUS_DONE: {"color": "green", "icon": "✓", "label": "done"},
|
|
66
|
+
STATUS_NO_RESULTS: {"color": "white", "icon": "⊘", "label": "no results"},
|
|
67
|
+
STATUS_WARNING: {"color": "yellow", "icon": "⚠", "label": "warning"},
|
|
68
|
+
STATUS_ERROR: {"color": "red", "icon": "✗", "label": "error"},
|
|
69
|
+
STATUS_KILLED: {"color": "magenta", "icon": "●", "label": "killed"},
|
|
98
70
|
}
|
|
99
71
|
|
|
100
|
-
return status_info.get(status, {
|
|
101
|
-
'color': 'white',
|
|
102
|
-
'icon': '?',
|
|
103
|
-
'label': status
|
|
104
|
-
})
|
|
72
|
+
return status_info.get(status, {"color": "white", "icon": "?", "label": status})
|
souleyez/engine/log_sanitizer.py
CHANGED
|
@@ -12,86 +12,112 @@ from typing import Optional
|
|
|
12
12
|
class LogSanitizer:
|
|
13
13
|
"""
|
|
14
14
|
Sanitizes logs by redacting credentials and sensitive information.
|
|
15
|
-
|
|
15
|
+
|
|
16
16
|
Patterns detected:
|
|
17
17
|
- Login successful messages with credentials
|
|
18
18
|
- Username:password combinations
|
|
19
19
|
- SSH/FTP/MySQL/PostgreSQL credentials
|
|
20
20
|
- API keys and tokens
|
|
21
21
|
"""
|
|
22
|
-
|
|
22
|
+
|
|
23
23
|
# Common credential patterns
|
|
24
24
|
PATTERNS = [
|
|
25
25
|
# Metasploit successful login: [+] 10.0.0.82:5432 - Login Successful: postgres:postgres@template1
|
|
26
|
-
(r
|
|
27
|
-
|
|
26
|
+
(r"(Login Successful:?\s+)([^:]+):([^@\s]+)(@\S+)?", r"\1\2:[REDACTED]\4"),
|
|
28
27
|
# MSF telnet_login format: msfadmin:msfadmin login: Login OK
|
|
29
|
-
(r
|
|
30
|
-
|
|
28
|
+
(r"(\s)([^:\s]+):([^:\s]+)(\s+login:\s+Login OK)", r"\1\2:[REDACTED]\4"),
|
|
31
29
|
# Hydra output format: login: username password: secretpass
|
|
32
|
-
(r
|
|
33
|
-
|
|
30
|
+
(r"(login:\s+)(\S+)(\s+password:\s+)(\S+)", r"\1\2\3[REDACTED]"),
|
|
34
31
|
# Hydra colon format in output: [port][service] host: X login: Y password: Z
|
|
35
|
-
(
|
|
36
|
-
|
|
32
|
+
(
|
|
33
|
+
r"(host:\s+\S+\s+login:\s+)(\S+)(\s+password:\s+)(.+?)(\s|$)",
|
|
34
|
+
r"\1\2\3[REDACTED]\5",
|
|
35
|
+
),
|
|
37
36
|
# SSH/FTP success: Successfully authenticated as 'root' with password 'toor'
|
|
38
|
-
(
|
|
39
|
-
|
|
37
|
+
(
|
|
38
|
+
r"(authenticated as ['\"]?\w+['\"]? with password ['\"]?)([^'\"]+)(['\"]?)",
|
|
39
|
+
r"\1[REDACTED]\3",
|
|
40
|
+
),
|
|
40
41
|
# MySQL/PostgreSQL connection strings - capture everything between : and last @
|
|
41
42
|
# This handles passwords with @ symbols by matching the last @ before a hostname
|
|
42
|
-
(
|
|
43
|
-
|
|
43
|
+
(
|
|
44
|
+
r"((?:mysql|postgres|postgresql)://[^:]+:)(.+)(@(?:(?:\d{1,3}\.){3}\d{1,3}(?::\d+)?|[a-zA-Z0-9.-]+(?::\d+)?)(?:/|$))",
|
|
45
|
+
r"\1[REDACTED]\3",
|
|
46
|
+
),
|
|
44
47
|
# Direct credentials: username:password format (but not URLs)
|
|
45
|
-
(r
|
|
46
|
-
|
|
48
|
+
(r"(?<!://)\b(\w+):([^\s:@]{4,})@", r"\1:[REDACTED]@"),
|
|
47
49
|
# Common password indicators (stop at & to preserve form parameters)
|
|
48
|
-
(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
(
|
|
51
|
+
r'(password[=:\s]+["\']?)([^"\'\s&]{4,})(["\']?)',
|
|
52
|
+
r"\1[REDACTED]\3",
|
|
53
|
+
re.IGNORECASE,
|
|
54
|
+
),
|
|
55
|
+
(
|
|
56
|
+
r'(pass[=:\s]+["\']?)([^"\'\s&]{4,})(["\']?)',
|
|
57
|
+
r"\1[REDACTED]\3",
|
|
58
|
+
re.IGNORECASE,
|
|
59
|
+
),
|
|
60
|
+
(
|
|
61
|
+
r'(pwd[=:\s]+["\']?)([^"\'\s&]{4,})(["\']?)',
|
|
62
|
+
r"\1[REDACTED]\3",
|
|
63
|
+
re.IGNORECASE,
|
|
64
|
+
),
|
|
52
65
|
# API keys and tokens (long alphanumeric strings)
|
|
53
|
-
(
|
|
54
|
-
|
|
55
|
-
|
|
66
|
+
(
|
|
67
|
+
r'(["\']?api[_-]?key["\']?\s*[=:]\s*["\']?)([A-Za-z0-9_-]{20,})(["\']?)',
|
|
68
|
+
r"\1[REDACTED]\3",
|
|
69
|
+
re.IGNORECASE,
|
|
70
|
+
),
|
|
71
|
+
(
|
|
72
|
+
r'(["\']?token["\']?\s*[=:]\s*["\']?)([A-Za-z0-9_.-]{20,})(["\']?)',
|
|
73
|
+
r"\1[REDACTED]\3",
|
|
74
|
+
re.IGNORECASE,
|
|
75
|
+
),
|
|
56
76
|
# SSH private keys
|
|
57
|
-
(
|
|
58
|
-
|
|
77
|
+
(
|
|
78
|
+
r"(-----BEGIN[A-Z\s]+PRIVATE KEY-----)(.*?)(-----END[A-Z\s]+PRIVATE KEY-----)",
|
|
79
|
+
r"\1\n[REDACTED]\n\3",
|
|
80
|
+
re.DOTALL,
|
|
81
|
+
),
|
|
59
82
|
# Hashes (common hash formats: MD5, SHA1, SHA256)
|
|
60
|
-
(r
|
|
61
|
-
(r
|
|
62
|
-
(r
|
|
63
|
-
|
|
83
|
+
(r"\b([a-f0-9]{32})\b", r"[HASH_REDACTED]"), # MD5
|
|
84
|
+
(r"\b([a-f0-9]{40})\b", r"[HASH_REDACTED]"), # SHA1
|
|
85
|
+
(r"\b([a-f0-9]{64})\b", r"[HASH_REDACTED]"), # SHA256
|
|
64
86
|
# Generic secret patterns
|
|
65
|
-
(
|
|
87
|
+
(
|
|
88
|
+
r'(secret[=:\s]+["\']?)([^"\'\s]{4,})(["\']?)',
|
|
89
|
+
r"\1[REDACTED]\3",
|
|
90
|
+
re.IGNORECASE,
|
|
91
|
+
),
|
|
66
92
|
]
|
|
67
|
-
|
|
93
|
+
|
|
68
94
|
# Whitelist patterns (don't redact these even if they match)
|
|
69
95
|
WHITELIST_PATTERNS = [
|
|
70
|
-
r
|
|
71
|
-
r
|
|
72
|
-
r
|
|
73
|
-
r
|
|
74
|
-
r
|
|
75
|
-
r
|
|
96
|
+
r"http://",
|
|
97
|
+
r"https://",
|
|
98
|
+
r"localhost",
|
|
99
|
+
r"127\.0\.0\.1",
|
|
100
|
+
r"0\.0\.0\.0",
|
|
101
|
+
r"example\.com",
|
|
76
102
|
]
|
|
77
|
-
|
|
103
|
+
|
|
78
104
|
@classmethod
|
|
79
105
|
def sanitize(cls, log_content: str, aggressive: bool = False) -> str:
|
|
80
106
|
"""
|
|
81
107
|
Sanitize log content by redacting credentials.
|
|
82
|
-
|
|
108
|
+
|
|
83
109
|
Args:
|
|
84
110
|
log_content: Raw log content
|
|
85
111
|
aggressive: If True, use more aggressive redaction (may over-redact)
|
|
86
|
-
|
|
112
|
+
|
|
87
113
|
Returns:
|
|
88
114
|
Sanitized log content with credentials redacted
|
|
89
115
|
"""
|
|
90
116
|
if not log_content:
|
|
91
117
|
return log_content
|
|
92
|
-
|
|
118
|
+
|
|
93
119
|
sanitized = log_content
|
|
94
|
-
|
|
120
|
+
|
|
95
121
|
# Apply all patterns
|
|
96
122
|
for pattern_tuple in cls.PATTERNS:
|
|
97
123
|
if len(pattern_tuple) == 2:
|
|
@@ -99,100 +125,100 @@ class LogSanitizer:
|
|
|
99
125
|
flags = 0
|
|
100
126
|
else:
|
|
101
127
|
pattern, replacement, flags = pattern_tuple
|
|
102
|
-
|
|
128
|
+
|
|
103
129
|
try:
|
|
104
130
|
sanitized = re.sub(pattern, replacement, sanitized, flags=flags)
|
|
105
131
|
except Exception:
|
|
106
132
|
# If regex fails, continue with next pattern
|
|
107
133
|
continue
|
|
108
|
-
|
|
134
|
+
|
|
109
135
|
return sanitized
|
|
110
|
-
|
|
136
|
+
|
|
111
137
|
@classmethod
|
|
112
138
|
def contains_credentials(cls, log_content: str) -> bool:
|
|
113
139
|
"""
|
|
114
140
|
Check if log content appears to contain credentials.
|
|
115
|
-
|
|
141
|
+
|
|
116
142
|
Args:
|
|
117
143
|
log_content: Log content to check
|
|
118
|
-
|
|
144
|
+
|
|
119
145
|
Returns:
|
|
120
146
|
True if credentials detected, False otherwise
|
|
121
147
|
"""
|
|
122
148
|
if not log_content:
|
|
123
149
|
return False
|
|
124
|
-
|
|
150
|
+
|
|
125
151
|
# Quick checks for common credential indicators
|
|
126
152
|
indicators = [
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
153
|
+
"login successful",
|
|
154
|
+
"login ok", # MSF telnet_login
|
|
155
|
+
"authenticated",
|
|
156
|
+
"password:",
|
|
157
|
+
"credentials",
|
|
158
|
+
"api_key",
|
|
159
|
+
"api-key",
|
|
160
|
+
"token:",
|
|
161
|
+
"secret:",
|
|
162
|
+
"BEGIN PRIVATE KEY",
|
|
163
|
+
"login:", # Hydra output
|
|
164
|
+
"valid pair found", # Hydra success
|
|
139
165
|
]
|
|
140
|
-
|
|
166
|
+
|
|
141
167
|
log_lower = log_content.lower()
|
|
142
168
|
return any(indicator in log_lower for indicator in indicators)
|
|
143
|
-
|
|
169
|
+
|
|
144
170
|
@classmethod
|
|
145
171
|
def get_redaction_summary(cls, original: str, sanitized: str) -> Optional[str]:
|
|
146
172
|
"""
|
|
147
173
|
Generate a summary of what was redacted.
|
|
148
|
-
|
|
174
|
+
|
|
149
175
|
Args:
|
|
150
176
|
original: Original log content
|
|
151
177
|
sanitized: Sanitized log content
|
|
152
|
-
|
|
178
|
+
|
|
153
179
|
Returns:
|
|
154
180
|
Summary message or None if nothing redacted
|
|
155
181
|
"""
|
|
156
182
|
if original == sanitized:
|
|
157
183
|
return None
|
|
158
|
-
|
|
184
|
+
|
|
159
185
|
# Count how many times [REDACTED] appears in sanitized version
|
|
160
|
-
redaction_count = sanitized.count(
|
|
161
|
-
hash_count = sanitized.count(
|
|
162
|
-
|
|
186
|
+
redaction_count = sanitized.count("[REDACTED]")
|
|
187
|
+
hash_count = sanitized.count("[HASH_REDACTED]")
|
|
188
|
+
|
|
163
189
|
parts = []
|
|
164
190
|
if redaction_count > 0:
|
|
165
191
|
parts.append(f"{redaction_count} credential(s)")
|
|
166
192
|
if hash_count > 0:
|
|
167
193
|
parts.append(f"{hash_count} hash(es)")
|
|
168
|
-
|
|
194
|
+
|
|
169
195
|
if parts:
|
|
170
196
|
return f"Redacted: {', '.join(parts)}"
|
|
171
|
-
|
|
197
|
+
|
|
172
198
|
return "Some sensitive data redacted"
|
|
173
199
|
|
|
174
200
|
|
|
175
201
|
def sanitize_log_file(log_path: str, output_path: Optional[str] = None) -> bool:
|
|
176
202
|
"""
|
|
177
203
|
Sanitize a log file in place or write to new file.
|
|
178
|
-
|
|
204
|
+
|
|
179
205
|
Args:
|
|
180
206
|
log_path: Path to log file to sanitize
|
|
181
207
|
output_path: Optional output path (if None, modifies in place)
|
|
182
|
-
|
|
208
|
+
|
|
183
209
|
Returns:
|
|
184
210
|
True if successful, False otherwise
|
|
185
211
|
"""
|
|
186
212
|
try:
|
|
187
|
-
with open(log_path,
|
|
213
|
+
with open(log_path, "r", encoding="utf-8", errors="replace") as f:
|
|
188
214
|
original = f.read()
|
|
189
|
-
|
|
215
|
+
|
|
190
216
|
sanitized = LogSanitizer.sanitize(original)
|
|
191
|
-
|
|
217
|
+
|
|
192
218
|
target_path = output_path or log_path
|
|
193
|
-
with open(target_path,
|
|
219
|
+
with open(target_path, "w", encoding="utf-8") as f:
|
|
194
220
|
f.write(sanitized)
|
|
195
|
-
|
|
221
|
+
|
|
196
222
|
return True
|
|
197
223
|
except Exception:
|
|
198
224
|
return False
|
souleyez/engine/manager.py
CHANGED
|
@@ -17,11 +17,18 @@ import importlib
|
|
|
17
17
|
|
|
18
18
|
def _run_nmap_adapter(target, args, label, save_xml=False):
|
|
19
19
|
from .. import scanner as scanner_module
|
|
20
|
+
|
|
20
21
|
# scanner.run_nmap should return (logpath, rc, xmlpath, summary)
|
|
21
22
|
return scanner_module.run_nmap(target, args, label, save_xml=save_xml)
|
|
22
23
|
|
|
23
24
|
|
|
24
|
-
def run_scan_sync(
|
|
25
|
+
def run_scan_sync(
|
|
26
|
+
tool: str,
|
|
27
|
+
target: str,
|
|
28
|
+
args: list,
|
|
29
|
+
label: Optional[str] = None,
|
|
30
|
+
save_xml: bool = False,
|
|
31
|
+
) -> int:
|
|
25
32
|
"""
|
|
26
33
|
Run a scan synchronously and return the DB scan id.
|
|
27
34
|
Currently supports 'nmap' as a built-in. Creates a DB record, runs, updates DB.
|
|
@@ -39,16 +46,26 @@ def run_scan_sync(tool: str, target: str, args: list, label: Optional[str] = Non
|
|
|
39
46
|
"summary": {},
|
|
40
47
|
"per_host": [],
|
|
41
48
|
"status": "pending",
|
|
42
|
-
"rc": None
|
|
49
|
+
"rc": None,
|
|
43
50
|
}
|
|
44
51
|
scan_id = insert_scan(entry)
|
|
45
52
|
|
|
46
53
|
try:
|
|
47
54
|
if tool.lower() == "nmap":
|
|
48
|
-
logpath, rc, xmlpath, summary = _run_nmap_adapter(
|
|
55
|
+
logpath, rc, xmlpath, summary = _run_nmap_adapter(
|
|
56
|
+
target, args, label, save_xml=save_xml
|
|
57
|
+
)
|
|
49
58
|
# ensure per_host in summary (some parsers provide it)
|
|
50
59
|
per_host = summary.get("per_host") if isinstance(summary, dict) else []
|
|
51
|
-
update_scan(
|
|
60
|
+
update_scan(
|
|
61
|
+
scan_id,
|
|
62
|
+
status="done",
|
|
63
|
+
rc=rc,
|
|
64
|
+
log=logpath,
|
|
65
|
+
xml=xmlpath,
|
|
66
|
+
summary=summary,
|
|
67
|
+
per_host=per_host,
|
|
68
|
+
)
|
|
52
69
|
else:
|
|
53
70
|
# try to import a plugin module by convention souleyez.plugins.<tool>
|
|
54
71
|
try:
|
|
@@ -58,7 +75,15 @@ def run_scan_sync(tool: str, target: str, args: list, label: Optional[str] = Non
|
|
|
58
75
|
plugin = PluginClass()
|
|
59
76
|
prepared = plugin.prepare(target, args, label)
|
|
60
77
|
result = plugin.run(prepared)
|
|
61
|
-
update_scan(
|
|
78
|
+
update_scan(
|
|
79
|
+
scan_id,
|
|
80
|
+
status=result.get("status", "done"),
|
|
81
|
+
rc=result.get("rc"),
|
|
82
|
+
log=result.get("log"),
|
|
83
|
+
xml=result.get("xml"),
|
|
84
|
+
summary=result.get("summary"),
|
|
85
|
+
per_host=result.get("per_host"),
|
|
86
|
+
)
|
|
62
87
|
else:
|
|
63
88
|
update_scan(scan_id, status="failed")
|
|
64
89
|
except Exception:
|
|
@@ -68,7 +93,13 @@ def run_scan_sync(tool: str, target: str, args: list, label: Optional[str] = Non
|
|
|
68
93
|
return scan_id
|
|
69
94
|
|
|
70
95
|
|
|
71
|
-
def run_scan_background(
|
|
96
|
+
def run_scan_background(
|
|
97
|
+
tool: str,
|
|
98
|
+
target: str,
|
|
99
|
+
args: list,
|
|
100
|
+
label: Optional[str] = None,
|
|
101
|
+
save_xml: bool = False,
|
|
102
|
+
) -> int:
|
|
72
103
|
"""
|
|
73
104
|
Run the scan in a background thread and return the DB id immediately.
|
|
74
105
|
"""
|
|
@@ -85,7 +116,7 @@ def run_scan_background(tool: str, target: str, args: list, label: Optional[str]
|
|
|
85
116
|
"summary": {},
|
|
86
117
|
"per_host": [],
|
|
87
118
|
"status": "pending",
|
|
88
|
-
"rc": None
|
|
119
|
+
"rc": None,
|
|
89
120
|
}
|
|
90
121
|
scan_id = insert_scan(entry)
|
|
91
122
|
|