souleyez 2.43.34__py3-none-any.whl → 3.0.7__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.
Files changed (326) hide show
  1. souleyez/__init__.py +1 -1
  2. souleyez/ai/__init__.py +7 -7
  3. souleyez/ai/action_mapper.py +3 -2
  4. souleyez/ai/chain_advisor.py +2 -1
  5. souleyez/ai/claude_provider.py +2 -2
  6. souleyez/ai/context_builder.py +4 -2
  7. souleyez/ai/executor.py +9 -6
  8. souleyez/ai/feedback_handler.py +4 -2
  9. souleyez/ai/llm_provider.py +2 -2
  10. souleyez/ai/ollama_provider.py +2 -2
  11. souleyez/ai/ollama_service.py +10 -26
  12. souleyez/ai/path_scorer.py +2 -1
  13. souleyez/ai/recommender.py +6 -4
  14. souleyez/ai/report_context.py +2 -2
  15. souleyez/ai/report_service.py +5 -5
  16. souleyez/ai/result_parser.py +3 -2
  17. souleyez/ai/safety.py +5 -2
  18. souleyez/auth/__init__.py +6 -6
  19. souleyez/auth/audit.py +2 -2
  20. souleyez/auth/engagement_access.py +5 -7
  21. souleyez/auth/permissions.py +1 -1
  22. souleyez/auth/session_manager.py +5 -5
  23. souleyez/auth/user_manager.py +4 -5
  24. souleyez/commands/audit.py +6 -5
  25. souleyez/commands/auth.py +6 -5
  26. souleyez/commands/deliverables.py +2 -3
  27. souleyez/commands/engagement.py +3 -3
  28. souleyez/commands/license.py +3 -2
  29. souleyez/commands/screenshots.py +5 -4
  30. souleyez/commands/user.py +10 -8
  31. souleyez/config.py +4 -2
  32. souleyez/core/credential_tester.py +4 -2
  33. souleyez/core/cve_mappings.py +2 -1
  34. souleyez/core/cve_matcher.py +2 -1
  35. souleyez/core/msf_auto_mapper.py +2 -0
  36. souleyez/core/msf_chain_engine.py +3 -1
  37. souleyez/core/msf_database.py +7 -13
  38. souleyez/core/msf_integration.py +2 -2
  39. souleyez/core/msf_rpc_client.py +3 -2
  40. souleyez/core/msf_rpc_manager.py +4 -4
  41. souleyez/core/msf_sync_manager.py +7 -7
  42. souleyez/core/network_utils.py +1 -1
  43. souleyez/core/parser_handler.py +2 -1
  44. souleyez/core/pending_chains.py +4 -3
  45. souleyez/core/templates.py +5 -2
  46. souleyez/core/tool_chaining.py +297 -230
  47. souleyez/core/version_utils.py +1 -0
  48. souleyez/core/vuln_correlation.py +3 -2
  49. souleyez/core/web_utils.py +2 -1
  50. souleyez/detection/__init__.py +1 -1
  51. souleyez/detection/attack_signatures.py +1 -1
  52. souleyez/detection/mitre_mappings.py +1 -2
  53. souleyez/detection/validator.py +5 -4
  54. souleyez/devtools.py +4 -2
  55. souleyez/docs/README.md +2 -2
  56. souleyez/engine/background.py +168 -7
  57. souleyez/engine/base.py +2 -1
  58. souleyez/engine/loader.py +4 -2
  59. souleyez/engine/log_sanitizer.py +1 -0
  60. souleyez/engine/manager.py +3 -1
  61. souleyez/engine/result_handler.py +50 -67
  62. souleyez/engine/worker_manager.py +6 -4
  63. souleyez/export/evidence_bundle.py +1 -0
  64. souleyez/handlers/base.py +1 -0
  65. souleyez/handlers/bash_handler.py +1 -0
  66. souleyez/handlers/bloodhound_handler.py +1 -0
  67. souleyez/handlers/certipy_handler.py +1 -0
  68. souleyez/handlers/crackmapexec_handler.py +2 -20
  69. souleyez/handlers/dnsrecon_handler.py +2 -1
  70. souleyez/handlers/enum4linux_handler.py +65 -37
  71. souleyez/handlers/evil_winrm_handler.py +1 -0
  72. souleyez/handlers/ffuf_handler.py +3 -1
  73. souleyez/handlers/gobuster_handler.py +7 -6
  74. souleyez/handlers/gpp_extract_handler.py +1 -0
  75. souleyez/handlers/hashcat_handler.py +1 -0
  76. souleyez/handlers/hydra_handler.py +5 -1
  77. souleyez/handlers/impacket_getuserspns_handler.py +1 -0
  78. souleyez/handlers/impacket_psexec_handler.py +1 -0
  79. souleyez/handlers/impacket_secretsdump_handler.py +1 -0
  80. souleyez/handlers/john_handler.py +1 -0
  81. souleyez/handlers/katana_handler.py +39 -2
  82. souleyez/handlers/kerbrute_handler.py +1 -0
  83. souleyez/handlers/ldapsearch_handler.py +90 -17
  84. souleyez/handlers/lfi_extract_handler.py +1 -0
  85. souleyez/handlers/msf_auxiliary_handler.py +2 -0
  86. souleyez/handlers/msf_exploit_handler.py +1 -0
  87. souleyez/handlers/nikto_handler.py +2 -1
  88. souleyez/handlers/nmap_handler.py +2 -1
  89. souleyez/handlers/nuclei_handler.py +2 -1
  90. souleyez/handlers/nxc_handler.py +50 -19
  91. souleyez/handlers/rdp_sec_check_handler.py +1 -0
  92. souleyez/handlers/registry.py +1 -0
  93. souleyez/handlers/responder_handler.py +1 -0
  94. souleyez/handlers/service_explorer_handler.py +2 -1
  95. souleyez/handlers/smbclient_handler.py +1 -0
  96. souleyez/handlers/smbmap_handler.py +3 -2
  97. souleyez/handlers/sqlmap_handler.py +6 -4
  98. souleyez/handlers/theharvester_handler.py +2 -1
  99. souleyez/handlers/web_login_test_handler.py +1 -0
  100. souleyez/handlers/whois_handler.py +3 -2
  101. souleyez/handlers/wpscan_handler.py +2 -1
  102. souleyez/history.py +4 -3
  103. souleyez/importers/msf_importer.py +5 -3
  104. souleyez/importers/smart_importer.py +6 -4
  105. souleyez/integrations/siem/__init__.py +6 -6
  106. souleyez/integrations/siem/base.py +1 -1
  107. souleyez/integrations/siem/elastic.py +3 -3
  108. souleyez/integrations/siem/factory.py +1 -2
  109. souleyez/integrations/siem/googlesecops.py +4 -4
  110. souleyez/integrations/siem/rule_mappings/wazuh_rules.py +1 -1
  111. souleyez/integrations/siem/sentinel.py +3 -3
  112. souleyez/integrations/siem/splunk.py +3 -3
  113. souleyez/integrations/siem/wazuh.py +4 -4
  114. souleyez/integrations/wazuh/__init__.py +1 -1
  115. souleyez/integrations/wazuh/client.py +3 -2
  116. souleyez/integrations/wazuh/config.py +3 -2
  117. souleyez/integrations/wazuh/host_mapper.py +3 -1
  118. souleyez/integrations/wazuh/sync.py +4 -1
  119. souleyez/intelligence/__init__.py +1 -1
  120. souleyez/intelligence/correlation_analyzer.py +6 -5
  121. souleyez/intelligence/exploit_knowledge.py +4 -4
  122. souleyez/intelligence/exploit_suggestions.py +4 -3
  123. souleyez/intelligence/gap_analyzer.py +5 -3
  124. souleyez/intelligence/gap_detector.py +2 -0
  125. souleyez/intelligence/sensitive_tables.py +1 -1
  126. souleyez/intelligence/service_parser.py +1 -0
  127. souleyez/intelligence/surface_analyzer.py +9 -9
  128. souleyez/intelligence/target_parser.py +1 -0
  129. souleyez/licensing/__init__.py +3 -3
  130. souleyez/main.py +25 -18
  131. souleyez/migrations/fix_job_counter.py +2 -1
  132. souleyez/parsers/bloodhound_parser.py +1 -0
  133. souleyez/parsers/crackmapexec_parser.py +2 -1
  134. souleyez/parsers/dalfox_parser.py +3 -2
  135. souleyez/parsers/dnsrecon_parser.py +2 -1
  136. souleyez/parsers/enum4linux_parser.py +2 -1
  137. souleyez/parsers/ffuf_parser.py +2 -1
  138. souleyez/parsers/gobuster_parser.py +2 -1
  139. souleyez/parsers/hashcat_parser.py +3 -2
  140. souleyez/parsers/http_fingerprint_parser.py +2 -1
  141. souleyez/parsers/hydra_parser.py +2 -1
  142. souleyez/parsers/impacket_parser.py +2 -1
  143. souleyez/parsers/john_parser.py +4 -3
  144. souleyez/parsers/katana_parser.py +134 -2
  145. souleyez/parsers/msf_parser.py +2 -1
  146. souleyez/parsers/nikto_parser.py +2 -1
  147. souleyez/parsers/nmap_parser.py +14 -3
  148. souleyez/parsers/nuclei_parser.py +3 -2
  149. souleyez/parsers/responder_parser.py +1 -0
  150. souleyez/parsers/searchsploit_parser.py +3 -2
  151. souleyez/parsers/service_explorer_parser.py +1 -0
  152. souleyez/parsers/smbmap_parser.py +2 -1
  153. souleyez/parsers/sqlmap_parser.py +36 -2
  154. souleyez/parsers/theharvester_parser.py +2 -1
  155. souleyez/parsers/whois_parser.py +2 -1
  156. souleyez/parsers/wpscan_parser.py +3 -2
  157. souleyez/plugins/afp.py +3 -1
  158. souleyez/plugins/afp_brute.py +3 -1
  159. souleyez/plugins/ard.py +3 -1
  160. souleyez/plugins/bloodhound.py +3 -2
  161. souleyez/plugins/certipy.py +1 -0
  162. souleyez/plugins/crackmapexec.py +11 -7
  163. souleyez/plugins/dalfox.py +5 -2
  164. souleyez/plugins/dns_hijack.py +3 -1
  165. souleyez/plugins/dnsrecon.py +3 -1
  166. souleyez/plugins/enum4linux.py +3 -1
  167. souleyez/plugins/evil_winrm.py +1 -0
  168. souleyez/plugins/ffuf.py +3 -1
  169. souleyez/plugins/firmware_extract.py +3 -2
  170. souleyez/plugins/gobuster.py +6 -3
  171. souleyez/plugins/gpp_extract.py +1 -0
  172. souleyez/plugins/hashcat.py +2 -1
  173. souleyez/plugins/http_fingerprint.py +149 -40
  174. souleyez/plugins/hydra.py +5 -3
  175. souleyez/plugins/impacket_common.py +40 -0
  176. souleyez/plugins/impacket_getnpusers.py +19 -2
  177. souleyez/plugins/impacket_getuserspns.py +158 -0
  178. souleyez/plugins/impacket_psexec.py +19 -2
  179. souleyez/plugins/impacket_secretsdump.py +19 -2
  180. souleyez/plugins/impacket_smbclient.py +19 -2
  181. souleyez/plugins/john.py +2 -1
  182. souleyez/plugins/katana.py +48 -6
  183. souleyez/plugins/kerbrute.py +1 -0
  184. souleyez/plugins/lfi_extract.py +1 -0
  185. souleyez/plugins/macos_ssh.py +3 -1
  186. souleyez/plugins/mdns.py +3 -1
  187. souleyez/plugins/msf_auxiliary.py +3 -2
  188. souleyez/plugins/msf_exploit.py +6 -5
  189. souleyez/plugins/nikto.py +5 -2
  190. souleyez/plugins/nmap.py +6 -4
  191. souleyez/plugins/nuclei.py +3 -1
  192. souleyez/plugins/nxc.py +1 -0
  193. souleyez/plugins/plugin_base.py +3 -2
  194. souleyez/plugins/plugin_template.py +3 -2
  195. souleyez/plugins/rdp_sec_check.py +1 -0
  196. souleyez/plugins/responder.py +2 -1
  197. souleyez/plugins/router_http_brute.py +3 -1
  198. souleyez/plugins/router_ssh_brute.py +3 -1
  199. souleyez/plugins/router_telnet_brute.py +3 -1
  200. souleyez/plugins/routersploit.py +5 -3
  201. souleyez/plugins/routersploit_exploit.py +5 -3
  202. souleyez/plugins/searchsploit.py +1 -0
  203. souleyez/plugins/service_explorer.py +2 -1
  204. souleyez/plugins/smbmap.py +3 -1
  205. souleyez/plugins/smbpasswd.py +1 -0
  206. souleyez/plugins/sqlmap.py +3 -1
  207. souleyez/plugins/theharvester.py +3 -1
  208. souleyez/plugins/tr069.py +3 -1
  209. souleyez/plugins/upnp.py +3 -1
  210. souleyez/plugins/upnp_abuse.py +4 -2
  211. souleyez/plugins/vnc_access.py +4 -2
  212. souleyez/plugins/vnc_brute.py +3 -1
  213. souleyez/plugins/web_login_test.py +1 -0
  214. souleyez/plugins/whois.py +3 -1
  215. souleyez/plugins/wpscan.py +49 -1
  216. souleyez/reporting/attack_chain.py +2 -1
  217. souleyez/reporting/charts.py +1 -0
  218. souleyez/reporting/compliance_mappings.py +1 -0
  219. souleyez/reporting/detection_report.py +10 -10
  220. souleyez/reporting/formatters.py +7 -12
  221. souleyez/reporting/generator.py +34 -46
  222. souleyez/reporting/metrics.py +2 -1
  223. souleyez/scanner.py +6 -3
  224. souleyez/security/__init__.py +7 -5
  225. souleyez/security/scope_validator.py +5 -4
  226. souleyez/security/validation.py +14 -0
  227. souleyez/security.py +5 -2
  228. souleyez/storage/credentials.py +14 -19
  229. souleyez/storage/crypto.py +7 -4
  230. souleyez/storage/database.py +6 -6
  231. souleyez/storage/db.py +8 -8
  232. souleyez/storage/deliverable_evidence.py +2 -1
  233. souleyez/storage/deliverable_exporter.py +3 -2
  234. souleyez/storage/deliverable_templates.py +2 -1
  235. souleyez/storage/deliverables.py +2 -1
  236. souleyez/storage/engagements.py +6 -4
  237. souleyez/storage/evidence.py +5 -4
  238. souleyez/storage/execution_log.py +4 -2
  239. souleyez/storage/exploit_attempts.py +3 -2
  240. souleyez/storage/exploits.py +3 -1
  241. souleyez/storage/findings.py +3 -1
  242. souleyez/storage/hosts.py +5 -2
  243. souleyez/storage/migrate_to_engagements.py +14 -24
  244. souleyez/storage/migrations/_001_add_credential_enhancements.py +12 -21
  245. souleyez/storage/migrations/_003_add_execution_log.py +8 -13
  246. souleyez/storage/migrations/_005_screenshots.py +2 -4
  247. souleyez/storage/migrations/_006_deliverables.py +2 -4
  248. souleyez/storage/migrations/_007_deliverable_templates.py +4 -8
  249. souleyez/storage/migrations/_008_add_nuclei_table.py +2 -4
  250. souleyez/storage/migrations/_010_evidence_linking.py +6 -12
  251. souleyez/storage/migrations/_012_team_collaboration.py +12 -24
  252. souleyez/storage/migrations/_013_add_host_tags.py +2 -4
  253. souleyez/storage/migrations/_014_exploit_attempts.py +10 -20
  254. souleyez/storage/migrations/_015_add_mac_os_fields.py +4 -8
  255. souleyez/storage/migrations/_016_add_domain_field.py +2 -4
  256. souleyez/storage/migrations/_017_msf_sessions.py +8 -16
  257. souleyez/storage/migrations/_018_add_osint_target.py +4 -8
  258. souleyez/storage/migrations/_019_add_engagement_type.py +4 -8
  259. souleyez/storage/migrations/_020_add_rbac.py +9 -17
  260. souleyez/storage/migrations/_021_wazuh_integration.py +4 -8
  261. souleyez/storage/migrations/_023_fix_detection_results_fk.py +2 -4
  262. souleyez/storage/migrations/_024_wazuh_vulnerabilities.py +4 -8
  263. souleyez/storage/migrations/_026_add_engagement_scope.py +4 -8
  264. souleyez/storage/migrations/_027_multi_siem_persistence.py +8 -16
  265. souleyez/storage/migrations/__init__.py +1 -4
  266. souleyez/storage/migrations/migration_manager.py +6 -9
  267. souleyez/storage/msf_sessions.py +1 -1
  268. souleyez/storage/osint.py +3 -1
  269. souleyez/storage/recommendation_engine.py +3 -2
  270. souleyez/storage/screenshots.py +2 -1
  271. souleyez/storage/smb_shares.py +3 -1
  272. souleyez/storage/sqlmap_data.py +6 -4
  273. souleyez/storage/team_collaboration.py +3 -2
  274. souleyez/storage/timeline_tracker.py +2 -1
  275. souleyez/storage/wazuh_vulns.py +3 -1
  276. souleyez/storage/web_paths.py +3 -1
  277. souleyez/testing/credential_tester.py +2 -0
  278. souleyez/ui/__init__.py +2 -1
  279. souleyez/ui/ai_quotes.py +1 -1
  280. souleyez/ui/attack_surface.py +50 -28
  281. souleyez/ui/chain_rules_view.py +6 -3
  282. souleyez/ui/correlation_view.py +3 -2
  283. souleyez/ui/dashboard.py +85 -139
  284. souleyez/ui/deliverables_view.py +1 -1
  285. souleyez/ui/design_system.py +5 -3
  286. souleyez/ui/errors.py +3 -1
  287. souleyez/ui/evidence_linking_view.py +2 -1
  288. souleyez/ui/evidence_vault.py +11 -6
  289. souleyez/ui/exploit_suggestions_view.py +11 -7
  290. souleyez/ui/export_view.py +3 -1
  291. souleyez/ui/gap_analysis_view.py +6 -3
  292. souleyez/ui/help_system.py +4 -1
  293. souleyez/ui/intelligence_view.py +7 -3
  294. souleyez/ui/interactive.py +1512 -584
  295. souleyez/ui/interactive_selector.py +3 -2
  296. souleyez/ui/log_formatter.py +1 -0
  297. souleyez/ui/menu_components.py +3 -1
  298. souleyez/ui/msf_auxiliary_menu.py +4 -1
  299. souleyez/ui/pending_chains_view.py +15 -12
  300. souleyez/ui/progress_indicators.py +5 -2
  301. souleyez/ui/recommendations_view.py +4 -2
  302. souleyez/ui/rule_builder.py +4 -1
  303. souleyez/ui/setup_wizard.py +10 -8
  304. souleyez/ui/shortcuts.py +1 -1
  305. souleyez/ui/splunk_gap_analysis_view.py +7 -4
  306. souleyez/ui/splunk_vulns_view.py +4 -1
  307. souleyez/ui/team_dashboard.py +7 -5
  308. souleyez/ui/template_selector.py +2 -1
  309. souleyez/ui/terminal.py +3 -2
  310. souleyez/ui/timeline_view.py +2 -1
  311. souleyez/ui/tool_setup.py +92 -31
  312. souleyez/ui/tutorial.py +7 -4
  313. souleyez/ui/tutorial_state.py +3 -2
  314. souleyez/ui/wazuh_vulns_view.py +5 -2
  315. souleyez/ui/wordlist_browser.py +4 -3
  316. souleyez/ui.py +13 -7
  317. souleyez/utils/tool_checker.py +61 -12
  318. souleyez/utils.py +4 -4
  319. souleyez/wordlists.py +1 -0
  320. {souleyez-2.43.34.dist-info → souleyez-3.0.7.dist-info}/METADATA +2 -2
  321. souleyez-3.0.7.dist-info/RECORD +445 -0
  322. souleyez-2.43.34.dist-info/RECORD +0 -443
  323. {souleyez-2.43.34.dist-info → souleyez-3.0.7.dist-info}/WHEEL +0 -0
  324. {souleyez-2.43.34.dist-info → souleyez-3.0.7.dist-info}/entry_points.txt +0 -0
  325. {souleyez-2.43.34.dist-info → souleyez-3.0.7.dist-info}/licenses/LICENSE +0 -0
  326. {souleyez-2.43.34.dist-info → souleyez-3.0.7.dist-info}/top_level.txt +0 -0
@@ -2,10 +2,12 @@
2
2
  """
3
3
  souleyez.engine.result_handler - Auto-parse job results
4
4
  """
5
- import os
5
+
6
6
  import logging
7
- from typing import Optional, Dict, Any
8
- from .job_status import STATUS_DONE, STATUS_NO_RESULTS, STATUS_WARNING, STATUS_ERROR
7
+ import os
8
+ from typing import Any, Dict, Optional
9
+
10
+ from .job_status import STATUS_DONE, STATUS_ERROR, STATUS_NO_RESULTS, STATUS_WARNING
9
11
 
10
12
  logger = logging.getLogger(__name__)
11
13
 
@@ -49,7 +51,8 @@ TOOL_ERROR_PATTERNS = {
49
51
  "nuclei": [
50
52
  "could not connect",
51
53
  "context deadline exceeded",
52
- "no address found",
54
+ # Note: "no address found" removed - nuclei reports this as [INF] when
55
+ # templates try alternate ports, not a real error. Exit code 0 = success.
53
56
  ],
54
57
  "ffuf": [
55
58
  "error making request",
@@ -129,36 +132,11 @@ def handle_job_result(job: Dict[str, Any]) -> Optional[Dict[str, Any]]:
129
132
  """
130
133
  tool = job.get("tool", "").lower()
131
134
  log_path = job.get("log")
132
- status = job.get("status")
133
-
134
- # Some tools return non-zero exit codes even on success
135
- # Parse 'done' jobs and 'error' jobs for certain tools
136
- # gobuster: exits 1 for wildcard detection (but we can still parse and retry)
137
- # enum4linux: exits non-zero when some queries fail, even with partial results
138
- # msf_exploit: exits 0 even on failure, but we want to parse either way
139
- # hashcat: exits 1 when exhausted (no passwords cracked) - not an error
140
- # web_login_test: exits 1 when credentials fail - not an error, just invalid creds
141
- tools_with_nonzero_success = [
142
- "gobuster",
143
- "msf_auxiliary",
144
- "msfconsole",
145
- "enum4linux",
146
- "msf_exploit",
147
- "wpscan",
148
- "hashcat",
149
- "web_login_test",
150
- ]
151
-
152
- if status == "done":
153
- # Always parse successful jobs
154
- pass
155
- elif status == "error" and tool in tools_with_nonzero_success:
156
- # Parse error jobs for tools that can succeed with non-zero exit codes
157
- pass
158
- else:
159
- # Skip other error/failed jobs
160
- return None
161
135
 
136
+ # Always try to parse if log file exists
137
+ # Status checks were causing race conditions where jobs showed "done"
138
+ # but get_job() returned stale status, causing parse to be skipped
139
+ # The caller (background.py) only calls us for completed jobs anyway
162
140
  if not log_path or not os.path.exists(log_path):
163
141
  logger.error(
164
142
  f"Job {job.get('id')} parse failed: log file missing or does not exist (path={log_path})"
@@ -193,9 +171,9 @@ def handle_job_result(job: Dict[str, Any]) -> Optional[Dict[str, Any]]:
193
171
 
194
172
  try:
195
173
  from souleyez.handlers.registry import get_handler
196
- from souleyez.storage.hosts import HostManager
197
- from souleyez.storage.findings import FindingsManager
198
174
  from souleyez.storage.credentials import CredentialsManager
175
+ from souleyez.storage.findings import FindingsManager
176
+ from souleyez.storage.hosts import HostManager
199
177
 
200
178
  handler = get_handler(tool)
201
179
  if handler:
@@ -306,7 +284,7 @@ def reparse_job(job_id: int) -> Dict[str, Any]:
306
284
  Returns:
307
285
  Dict with 'success', 'message', and optionally 'parse_result'
308
286
  """
309
- from .background import get_job, _read_jobs, _write_jobs
287
+ from .background import _read_jobs, _write_jobs, get_job
310
288
 
311
289
  # Get the job
312
290
  job = get_job(job_id)
@@ -345,9 +323,9 @@ def reparse_job(job_id: int) -> Dict[str, Any]:
345
323
 
346
324
  try:
347
325
  from souleyez.handlers.registry import get_handler
348
- from souleyez.storage.hosts import HostManager
349
- from souleyez.storage.findings import FindingsManager
350
326
  from souleyez.storage.credentials import CredentialsManager
327
+ from souleyez.storage.findings import FindingsManager
328
+ from souleyez.storage.hosts import HostManager
351
329
 
352
330
  handler = get_handler(tool)
353
331
  if handler:
@@ -527,10 +505,10 @@ def parse_nmap_job(
527
505
  ) -> Dict[str, Any]:
528
506
  """Parse nmap job results."""
529
507
  try:
508
+ from souleyez.core.cve_matcher import CVEMatcher
530
509
  from souleyez.parsers.nmap_parser import parse_nmap_log
531
- from souleyez.storage.hosts import HostManager
532
510
  from souleyez.storage.findings import FindingsManager
533
- from souleyez.core.cve_matcher import CVEMatcher
511
+ from souleyez.storage.hosts import HostManager
534
512
 
535
513
  # Parse the log file
536
514
  parsed = parse_nmap_log(log_path)
@@ -804,11 +782,11 @@ def parse_theharvester_job(
804
782
  """Parse theHarvester job results."""
805
783
  try:
806
784
  from souleyez.parsers.theharvester_parser import (
807
- parse_theharvester_output,
808
785
  get_osint_stats,
786
+ parse_theharvester_output,
809
787
  )
810
- from souleyez.storage.osint import OsintManager
811
788
  from souleyez.storage.hosts import HostManager
789
+ from souleyez.storage.osint import OsintManager
812
790
 
813
791
  # Read the log file
814
792
  with open(log_path, "r", encoding="utf-8", errors="replace") as f:
@@ -1301,14 +1279,15 @@ def parse_gobuster_job(
1301
1279
  ) -> Dict[str, Any]:
1302
1280
  """Parse gobuster job results."""
1303
1281
  try:
1282
+ from urllib.parse import urlparse
1283
+
1304
1284
  from souleyez.parsers.gobuster_parser import (
1305
- parse_gobuster_output,
1306
- get_paths_stats,
1307
1285
  generate_next_steps,
1286
+ get_paths_stats,
1287
+ parse_gobuster_output,
1308
1288
  )
1309
- from souleyez.storage.web_paths import WebPathsManager
1310
1289
  from souleyez.storage.hosts import HostManager
1311
- from urllib.parse import urlparse
1290
+ from souleyez.storage.web_paths import WebPathsManager
1312
1291
 
1313
1292
  # Read the log file
1314
1293
  with open(log_path, "r", encoding="utf-8", errors="replace") as f:
@@ -1532,11 +1511,12 @@ def parse_sqlmap_job(
1532
1511
  ) -> Dict[str, Any]:
1533
1512
  """Parse sqlmap job results."""
1534
1513
  try:
1535
- from souleyez.parsers.sqlmap_parser import parse_sqlmap_output, get_sqli_stats
1514
+ from urllib.parse import urlparse
1515
+
1516
+ from souleyez.parsers.sqlmap_parser import get_sqli_stats, parse_sqlmap_output
1536
1517
  from souleyez.storage.findings import FindingsManager
1537
1518
  from souleyez.storage.hosts import HostManager
1538
1519
  from souleyez.storage.sqlmap_data import SQLMapDataManager
1539
- from urllib.parse import urlparse
1540
1520
 
1541
1521
  # Read the log file
1542
1522
  with open(log_path, "r", encoding="utf-8", errors="replace") as f:
@@ -1973,9 +1953,9 @@ def _extract_credentials_from_dump(
1973
1953
  tuple: (count of credentials added, list of plaintext credential dicts for chaining)
1974
1954
  """
1975
1955
  from souleyez.intelligence.sensitive_tables import is_sensitive_table
1956
+ from souleyez.log_config import get_logger
1976
1957
  from souleyez.storage.credentials import CredentialsManager
1977
1958
  from souleyez.storage.hosts import HostManager
1978
- from souleyez.log_config import get_logger
1979
1959
 
1980
1960
  logger = get_logger(__name__)
1981
1961
  cred_manager = CredentialsManager()
@@ -2189,10 +2169,11 @@ def parse_msf_auxiliary_job(
2189
2169
  """Parse MSF auxiliary module job results."""
2190
2170
  try:
2191
2171
  import re
2172
+
2192
2173
  from souleyez.parsers.msf_parser import parse_msf_log
2193
- from souleyez.storage.hosts import HostManager
2194
- from souleyez.storage.findings import FindingsManager
2195
2174
  from souleyez.storage.credentials import CredentialsManager
2175
+ from souleyez.storage.findings import FindingsManager
2176
+ from souleyez.storage.hosts import HostManager
2196
2177
 
2197
2178
  # Read raw log for connection failure detection
2198
2179
  with open(log_path, "r", encoding="utf-8", errors="replace") as f:
@@ -2348,8 +2329,9 @@ def parse_msf_exploit_job(
2348
2329
  """Parse MSF exploit module job results."""
2349
2330
  try:
2350
2331
  import re
2351
- from souleyez.storage.hosts import HostManager
2332
+
2352
2333
  from souleyez.storage.findings import FindingsManager
2334
+ from souleyez.storage.hosts import HostManager
2353
2335
 
2354
2336
  # Read the log file
2355
2337
  with open(log_path, "r", encoding="utf-8", errors="replace") as f:
@@ -2501,10 +2483,10 @@ def parse_smbmap_job(
2501
2483
  ) -> Dict[str, Any]:
2502
2484
  """Parse smbmap job results."""
2503
2485
  try:
2504
- from souleyez.parsers.smbmap_parser import parse_smbmap_output, extract_findings
2505
- from souleyez.storage.smb_shares import SMBSharesManager
2486
+ from souleyez.parsers.smbmap_parser import extract_findings, parse_smbmap_output
2506
2487
  from souleyez.storage.findings import FindingsManager
2507
2488
  from souleyez.storage.hosts import HostManager
2489
+ from souleyez.storage.smb_shares import SMBSharesManager
2508
2490
 
2509
2491
  # Read the log file
2510
2492
  with open(log_path, "r", encoding="utf-8", errors="replace") as f:
@@ -2604,9 +2586,9 @@ def parse_whois_job(
2604
2586
  """Parse WHOIS job results."""
2605
2587
  try:
2606
2588
  from souleyez.parsers.whois_parser import (
2607
- parse_whois_output,
2608
- map_to_osint_data,
2609
2589
  extract_emails,
2590
+ map_to_osint_data,
2591
+ parse_whois_output,
2610
2592
  )
2611
2593
  from souleyez.storage.osint import OsintManager
2612
2594
 
@@ -2666,8 +2648,8 @@ def parse_dnsrecon_job(
2666
2648
  """Parse dnsrecon job results."""
2667
2649
  try:
2668
2650
  from souleyez.parsers.dnsrecon_parser import parse_dnsrecon_output
2669
- from souleyez.storage.osint import OsintManager
2670
2651
  from souleyez.storage.hosts import HostManager
2652
+ from souleyez.storage.osint import OsintManager
2671
2653
 
2672
2654
  # Read the log file
2673
2655
  with open(log_path, "r", encoding="utf-8", errors="replace") as f:
@@ -2818,8 +2800,8 @@ def parse_hydra_job(
2818
2800
  try:
2819
2801
  from souleyez.parsers.hydra_parser import parse_hydra_output
2820
2802
  from souleyez.storage.credentials import CredentialsManager
2821
- from souleyez.storage.hosts import HostManager
2822
2803
  from souleyez.storage.findings import FindingsManager
2804
+ from souleyez.storage.hosts import HostManager
2823
2805
 
2824
2806
  # Read the log file
2825
2807
  with open(log_path, "r", encoding="utf-8", errors="replace") as f:
@@ -3165,9 +3147,9 @@ def parse_enum4linux_job(
3165
3147
  """Parse enum4linux job results."""
3166
3148
  try:
3167
3149
  from souleyez.parsers.enum4linux_parser import (
3168
- parse_enum4linux_output,
3169
- get_smb_stats,
3170
3150
  categorize_share,
3151
+ get_smb_stats,
3152
+ parse_enum4linux_output,
3171
3153
  )
3172
3154
  from souleyez.storage.findings import FindingsManager
3173
3155
  from souleyez.storage.hosts import HostManager
@@ -3310,8 +3292,8 @@ def parse_crackmapexec_job(
3310
3292
  """Parse CrackMapExec job results."""
3311
3293
  try:
3312
3294
  from souleyez.parsers.crackmapexec_parser import parse_crackmapexec
3313
- from souleyez.storage.hosts import HostManager
3314
3295
  from souleyez.storage.credentials import CredentialsManager
3296
+ from souleyez.storage.hosts import HostManager
3315
3297
 
3316
3298
  target = job.get("target", "")
3317
3299
  parsed = parse_crackmapexec(log_path, target)
@@ -3379,8 +3361,8 @@ def parse_ffuf_job(
3379
3361
  """Parse ffuf job results."""
3380
3362
  try:
3381
3363
  from souleyez.parsers.ffuf_parser import parse_ffuf
3382
- from souleyez.storage.hosts import HostManager
3383
3364
  from souleyez.storage.findings import FindingsManager
3365
+ from souleyez.storage.hosts import HostManager
3384
3366
 
3385
3367
  target = job.get("target", "")
3386
3368
  parsed = parse_ffuf(log_path, target)
@@ -3709,8 +3691,8 @@ def parse_nikto_job(
3709
3691
  """Parse nikto web server scanner results."""
3710
3692
  try:
3711
3693
  from souleyez.parsers.nikto_parser import (
3712
- parse_nikto_output,
3713
3694
  generate_next_steps,
3695
+ parse_nikto_output,
3714
3696
  )
3715
3697
  from souleyez.storage.findings import FindingsManager
3716
3698
  from souleyez.storage.hosts import HostManager
@@ -3834,14 +3816,15 @@ def parse_http_fingerprint_job(
3834
3816
  based on detected WAF, CDN, or managed hosting platform.
3835
3817
  """
3836
3818
  try:
3819
+ from urllib.parse import urlparse
3820
+
3837
3821
  from souleyez.parsers.http_fingerprint_parser import (
3838
- parse_http_fingerprint_output,
3839
3822
  build_fingerprint_context,
3840
- get_tool_recommendations,
3841
3823
  generate_next_steps,
3824
+ get_tool_recommendations,
3825
+ parse_http_fingerprint_output,
3842
3826
  )
3843
3827
  from souleyez.storage.hosts import HostManager
3844
- from urllib.parse import urlparse
3845
3828
 
3846
3829
  target = job.get("target", "")
3847
3830
 
@@ -4084,8 +4067,8 @@ def parse_hashcat_job(
4084
4067
  """Parse hashcat job results and extract cracked passwords."""
4085
4068
  try:
4086
4069
  from souleyez.parsers.hashcat_parser import (
4087
- parse_hashcat_output,
4088
4070
  map_to_credentials,
4071
+ parse_hashcat_output,
4089
4072
  )
4090
4073
  from souleyez.storage.credentials import CredentialsManager
4091
4074
  from souleyez.storage.findings import FindingsManager
@@ -2,9 +2,11 @@
2
2
  """
3
3
  Worker health check and management utilities
4
4
  """
5
- import psutil
5
+
6
6
  import time
7
- from typing import Optional, Tuple, Dict, Any
7
+ from typing import Any, Dict, Optional, Tuple
8
+
9
+ import psutil
8
10
 
9
11
 
10
12
  def is_worker_running() -> Tuple[bool, Optional[int]]:
@@ -49,7 +51,7 @@ def is_worker_healthy() -> Tuple[bool, Optional[int], Optional[str]]:
49
51
  - pid: Worker PID if found, None otherwise
50
52
  - issue: Description of issue if not healthy, None otherwise
51
53
  """
52
- from souleyez.engine.background import get_heartbeat_age, HEARTBEAT_STALE_THRESHOLD
54
+ from souleyez.engine.background import HEARTBEAT_STALE_THRESHOLD, get_heartbeat_age
53
55
 
54
56
  is_running, pid = is_worker_running()
55
57
 
@@ -169,7 +171,7 @@ def get_worker_health() -> Dict[str, Any]:
169
171
  - cpu_percent: CPU usage percentage
170
172
  - memory_mb: Memory usage in MB
171
173
  """
172
- from souleyez.engine.background import get_heartbeat_age, HEARTBEAT_STALE_THRESHOLD
174
+ from souleyez.engine.background import HEARTBEAT_STALE_THRESHOLD, get_heartbeat_age
173
175
 
174
176
  is_running, pid = is_worker_running()
175
177
  heartbeat_age = get_heartbeat_age()
@@ -3,6 +3,7 @@
3
3
  Evidence bundle export to ZIP.
4
4
  Creates organized ZIP archive of all engagement evidence.
5
5
  """
6
+
6
7
  import os
7
8
  import zipfile
8
9
  from datetime import datetime
souleyez/handlers/base.py CHANGED
@@ -5,6 +5,7 @@ Base handler class for tool result parsing and display.
5
5
  All tool handlers inherit from BaseToolHandler and implement
6
6
  the required methods for their specific tool.
7
7
  """
8
+
8
9
  import logging
9
10
  from abc import ABC, abstractmethod
10
11
  from typing import Any, Dict, Optional
@@ -5,6 +5,7 @@ Bash handler.
5
5
  Handles bash script execution results, particularly for auto-generated
6
6
  scripts like web login credential tests.
7
7
  """
8
+
8
9
  import logging
9
10
  import os
10
11
  import re
@@ -3,6 +3,7 @@
3
3
  Handler for BloodHound - Active Directory attack path mapping.
4
4
  Parses bloodhound-python collection results.
5
5
  """
6
+
6
7
  import logging
7
8
  import os
8
9
  import re
@@ -3,6 +3,7 @@
3
3
  Handler for Certipy - Active Directory Certificate Services (ADCS) enumeration.
4
4
  Parses vulnerable certificate templates (ESC1-ESC8).
5
5
  """
6
+
6
7
  import logging
7
8
  import os
8
9
  import re
@@ -105,24 +105,8 @@ class CrackMapExecHandler(BaseToolHandler):
105
105
  vulns_found = len(parsed.get("findings", {}).get("vulnerabilities", []))
106
106
  pw_must_change = parsed.get("password_must_change", [])
107
107
 
108
- # Check for transient errors that should trigger retry
109
- transient_errors = [
110
- "NETBIOS connection with the remote host timed out",
111
- "Connection reset by peer",
112
- "Connection timed out",
113
- "Error enumerating shares",
114
- ]
115
- log_content = ""
116
- try:
117
- with open(log_path, "r", encoding="utf-8", errors="replace") as f:
118
- log_content = f.read()
119
- except Exception:
120
- pass
121
-
122
- has_transient_error = any(
123
- err.lower() in log_content.lower() for err in transient_errors
124
- )
125
-
108
+ # Determine status based on results found
109
+ # Retry logic is handled by background.py before parsing
126
110
  if (
127
111
  hosts_found > 0
128
112
  or shares_found > 0
@@ -132,8 +116,6 @@ class CrackMapExecHandler(BaseToolHandler):
132
116
  or len(pw_must_change) > 0
133
117
  ):
134
118
  status = STATUS_DONE
135
- elif has_transient_error:
136
- status = STATUS_WARNING # Transient error - may be retried
137
119
  else:
138
120
  status = STATUS_NO_RESULTS
139
121
 
@@ -4,6 +4,7 @@ DNSRecon handler.
4
4
 
5
5
  Consolidates parsing and display logic for DNSRecon DNS enumeration jobs.
6
6
  """
7
+
7
8
  import logging
8
9
  import os
9
10
  import re
@@ -44,9 +45,9 @@ class DNSReconHandler(BaseToolHandler):
44
45
  Extracts DNS records and stores them as OSINT data.
45
46
  """
46
47
  try:
48
+ from souleyez.engine.result_handler import detect_tool_error
47
49
  from souleyez.parsers.dnsrecon_parser import parse_dnsrecon_output
48
50
  from souleyez.storage.osint import OsintManager
49
- from souleyez.engine.result_handler import detect_tool_error
50
51
 
51
52
  # Import managers if not provided
52
53
  if host_manager is None:
@@ -4,6 +4,7 @@ enum4linux handler.
4
4
 
5
5
  Consolidates parsing and display logic for enum4linux SMB/Samba enumeration jobs.
6
6
  """
7
+
7
8
  import logging
8
9
  import os
9
10
  import re
@@ -11,7 +12,7 @@ from typing import Any, Dict, Optional
11
12
 
12
13
  import click
13
14
 
14
- from souleyez.engine.job_status import STATUS_DONE, STATUS_WARNING, STATUS_NO_RESULTS
15
+ from souleyez.engine.job_status import STATUS_DONE, STATUS_NO_RESULTS, STATUS_WARNING
15
16
  from souleyez.handlers.base import BaseToolHandler
16
17
 
17
18
  logger = logging.getLogger(__name__)
@@ -44,12 +45,12 @@ class Enum4LinuxHandler(BaseToolHandler):
44
45
  Extracts SMB users, groups, shares and stores them.
45
46
  """
46
47
  try:
48
+ from souleyez.engine.result_handler import detect_tool_error
47
49
  from souleyez.parsers.enum4linux_parser import (
48
- parse_enum4linux_output,
49
- get_smb_stats,
50
50
  categorize_share,
51
+ get_smb_stats,
52
+ parse_enum4linux_output,
51
53
  )
52
- from souleyez.engine.result_handler import detect_tool_error
53
54
 
54
55
  # Import managers if not provided
55
56
  if host_manager is None:
@@ -103,46 +104,71 @@ class Enum4LinuxHandler(BaseToolHandler):
103
104
  )
104
105
  credentials_added += 1
105
106
 
106
- # Store shares as findings
107
+ # Store shares in smb_shares table (proper storage)
108
+ from souleyez.storage.smb_shares import SMBSharesManager
109
+
110
+ smb_mgr = SMBSharesManager()
111
+ shares_added = 0
107
112
  findings_added = 0
113
+
108
114
  for share in parsed.get("shares", []):
109
115
  category = categorize_share(share)
110
- if category == "open":
111
- severity = "high"
112
- elif category == "readable":
113
- severity = "medium"
114
- elif category == "restricted":
115
- severity = "low"
116
- else:
117
- severity = "info"
118
-
119
116
  share_name = share["name"]
120
117
  share_type = share.get("type", "Unknown")
121
118
  mapping = share.get("mapping", "N/A")
122
-
123
- if mapping == "OK":
124
- listing = share.get("listing", "N/A")
125
- writing = share.get("writing", "N/A")
126
- access_desc = (
127
- f"Mapping={mapping}, Listing={listing}, Writing={writing}"
119
+ listing = share.get("listing", "N/A")
120
+ writing = share.get("writing", "N/A")
121
+
122
+ # Determine readable/writable status
123
+ readable = mapping == "OK" and listing in ("OK", "N/A")
124
+ writable = mapping == "OK" and writing == "OK"
125
+
126
+ # Store in smb_shares table
127
+ if host_id:
128
+ try:
129
+ smb_mgr.add_share(
130
+ host_id=host_id,
131
+ share_data={
132
+ "name": share_name,
133
+ "type": share_type,
134
+ "permissions": f"{mapping}/{listing}/{writing}",
135
+ "comment": share.get("comment", ""),
136
+ "readable": readable,
137
+ "writable": writable,
138
+ },
139
+ )
140
+ shares_added += 1
141
+ except Exception as e:
142
+ logger.debug(f"Could not store share in smb_shares: {e}")
143
+
144
+ # Also add a finding for high-risk shares (writable or open)
145
+ if category == "open" or writable:
146
+ if category == "open":
147
+ severity = "high"
148
+ elif writable:
149
+ severity = "medium"
150
+ else:
151
+ severity = "low"
152
+
153
+ title = f"Writable SMB Share: {share_name}"
154
+ description = (
155
+ f"Share: {share_name}\n"
156
+ f"Type: {share_type}\n"
157
+ f"Comment: {share.get('comment', 'N/A')}\n"
158
+ f"Readable: {readable}, Writable: {writable}"
128
159
  )
129
- else:
130
- access_desc = f"Access denied (Mapping={mapping})"
131
160
 
132
- title = f"SMB Share: {share_name} ({share_type})"
133
- description = f"Share: {share_name}\nType: {share_type}\nComment: {share.get('comment', 'N/A')}\nAccess: {access_desc}"
134
-
135
- findings_manager.add_finding(
136
- engagement_id=engagement_id,
137
- host_id=host_id,
138
- title=title,
139
- finding_type="smb_share",
140
- severity=severity,
141
- description=description,
142
- tool="enum4linux",
143
- port=445,
144
- )
145
- findings_added += 1
161
+ findings_manager.add_finding(
162
+ engagement_id=engagement_id,
163
+ host_id=host_id,
164
+ title=title,
165
+ finding_type="smb_share",
166
+ severity=severity,
167
+ description=description,
168
+ tool="enum4linux",
169
+ port=445,
170
+ )
171
+ findings_added += 1
146
172
 
147
173
  stats = get_smb_stats(parsed)
148
174
 
@@ -158,7 +184,8 @@ class Enum4LinuxHandler(BaseToolHandler):
158
184
 
159
185
  # Determine status
160
186
  has_results = (
161
- findings_added > 0
187
+ shares_added > 0
188
+ or findings_added > 0
162
189
  or credentials_added > 0
163
190
  or len(parsed.get("users", [])) > 0
164
191
  or stats["total_shares"] > 0
@@ -177,6 +204,7 @@ class Enum4LinuxHandler(BaseToolHandler):
177
204
  return {
178
205
  "tool": "enum4linux",
179
206
  "status": status,
207
+ "shares_added": shares_added,
180
208
  "findings_added": findings_added,
181
209
  "credentials_added": credentials_added,
182
210
  "users_found": len(parsed.get("users", [])),
@@ -4,6 +4,7 @@ Evil-WinRM handler.
4
4
 
5
5
  Consolidates parsing and display logic for Evil-WinRM jobs.
6
6
  """
7
+
7
8
  import logging
8
9
  import os
9
10
  import re
@@ -4,6 +4,7 @@ Ffuf handler.
4
4
 
5
5
  Consolidates parsing and display logic for ffuf fuzzing jobs.
6
6
  """
7
+
7
8
  import logging
8
9
  import os
9
10
  import re
@@ -186,8 +187,8 @@ class FfufHandler(BaseToolHandler):
186
187
  Extracts discovered paths and stores them in the database.
187
188
  """
188
189
  try:
189
- from souleyez.parsers.ffuf_parser import parse_ffuf
190
190
  from souleyez.engine.result_handler import detect_tool_error
191
+ from souleyez.parsers.ffuf_parser import parse_ffuf
191
192
 
192
193
  # Import managers if not provided
193
194
  if host_manager is None:
@@ -344,6 +345,7 @@ class FfufHandler(BaseToolHandler):
344
345
  decode the base64, and parse for credentials.
345
346
  """
346
347
  import base64
348
+
347
349
  import requests
348
350
 
349
351
  extracted_creds = []
@@ -4,18 +4,19 @@ Gobuster handler.
4
4
 
5
5
  Consolidates parsing and display logic for Gobuster directory enumeration jobs.
6
6
  """
7
+
7
8
  import logging
8
9
  import os
9
10
  import re
10
- import ssl
11
11
  import socket
12
- import urllib.request
12
+ import ssl
13
13
  import urllib.error
14
+ import urllib.request
14
15
  from typing import Any, Dict, List, Optional
15
- from urllib.parse import urlparse, urljoin
16
- import defusedxml.ElementTree as ElementTree # Safe XML parsing
16
+ from urllib.parse import urljoin, urlparse
17
17
 
18
18
  import click
19
+ import defusedxml.ElementTree as ElementTree # Safe XML parsing
19
20
 
20
21
  from souleyez.engine.job_status import (
21
22
  STATUS_DONE,
@@ -201,11 +202,11 @@ class GobusterHandler(BaseToolHandler):
201
202
  Extracts discovered paths and stores them in the database.
202
203
  """
203
204
  try:
205
+ from souleyez.engine.result_handler import detect_tool_error
204
206
  from souleyez.parsers.gobuster_parser import (
205
- parse_gobuster_output,
206
207
  get_paths_stats,
208
+ parse_gobuster_output,
207
209
  )
208
- from souleyez.engine.result_handler import detect_tool_error
209
210
 
210
211
  # Import managers if not provided
211
212
  if host_manager is None:
@@ -4,6 +4,7 @@ GPP Extract handler.
4
4
 
5
5
  Handles parsing and credential storage for GPP (Group Policy Preferences) extraction jobs.
6
6
  """
7
+
7
8
  import logging
8
9
  import os
9
10
  import re