souleyez 2.43.28__py3-none-any.whl → 2.43.32__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 (356) hide show
  1. souleyez/__init__.py +1 -2
  2. souleyez/ai/__init__.py +21 -15
  3. souleyez/ai/action_mapper.py +249 -150
  4. souleyez/ai/chain_advisor.py +116 -100
  5. souleyez/ai/claude_provider.py +29 -28
  6. souleyez/ai/context_builder.py +80 -62
  7. souleyez/ai/executor.py +158 -117
  8. souleyez/ai/feedback_handler.py +136 -121
  9. souleyez/ai/llm_factory.py +27 -20
  10. souleyez/ai/llm_provider.py +4 -2
  11. souleyez/ai/ollama_provider.py +6 -9
  12. souleyez/ai/ollama_service.py +44 -37
  13. souleyez/ai/path_scorer.py +91 -76
  14. souleyez/ai/recommender.py +176 -144
  15. souleyez/ai/report_context.py +74 -73
  16. souleyez/ai/report_service.py +84 -66
  17. souleyez/ai/result_parser.py +222 -229
  18. souleyez/ai/safety.py +67 -44
  19. souleyez/auth/__init__.py +23 -22
  20. souleyez/auth/audit.py +36 -26
  21. souleyez/auth/engagement_access.py +65 -48
  22. souleyez/auth/permissions.py +14 -3
  23. souleyez/auth/session_manager.py +54 -37
  24. souleyez/auth/user_manager.py +109 -64
  25. souleyez/commands/audit.py +40 -43
  26. souleyez/commands/auth.py +35 -15
  27. souleyez/commands/deliverables.py +55 -50
  28. souleyez/commands/engagement.py +47 -28
  29. souleyez/commands/license.py +32 -23
  30. souleyez/commands/screenshots.py +36 -32
  31. souleyez/commands/user.py +82 -36
  32. souleyez/config.py +52 -44
  33. souleyez/core/credential_tester.py +87 -81
  34. souleyez/core/cve_mappings.py +179 -192
  35. souleyez/core/cve_matcher.py +162 -148
  36. souleyez/core/msf_auto_mapper.py +100 -83
  37. souleyez/core/msf_chain_engine.py +294 -256
  38. souleyez/core/msf_database.py +153 -70
  39. souleyez/core/msf_integration.py +679 -673
  40. souleyez/core/msf_rpc_client.py +40 -42
  41. souleyez/core/msf_rpc_manager.py +77 -79
  42. souleyez/core/msf_sync_manager.py +241 -181
  43. souleyez/core/network_utils.py +22 -15
  44. souleyez/core/parser_handler.py +34 -25
  45. souleyez/core/pending_chains.py +114 -63
  46. souleyez/core/templates.py +158 -107
  47. souleyez/core/tool_chaining.py +9592 -2879
  48. souleyez/core/version_utils.py +79 -94
  49. souleyez/core/vuln_correlation.py +136 -89
  50. souleyez/core/web_utils.py +33 -32
  51. souleyez/data/wordlists/ad_users.txt +378 -0
  52. souleyez/data/wordlists/api_endpoints_large.txt +769 -0
  53. souleyez/data/wordlists/home_dir_sensitive.txt +39 -0
  54. souleyez/data/wordlists/lfi_payloads.txt +82 -0
  55. souleyez/data/wordlists/passwords_brute.txt +1548 -0
  56. souleyez/data/wordlists/passwords_crack.txt +2479 -0
  57. souleyez/data/wordlists/passwords_spray.txt +386 -0
  58. souleyez/data/wordlists/subdomains_large.txt +5057 -0
  59. souleyez/data/wordlists/usernames_common.txt +694 -0
  60. souleyez/data/wordlists/web_dirs_large.txt +4769 -0
  61. souleyez/detection/__init__.py +1 -1
  62. souleyez/detection/attack_signatures.py +12 -17
  63. souleyez/detection/mitre_mappings.py +61 -55
  64. souleyez/detection/validator.py +97 -86
  65. souleyez/devtools.py +23 -10
  66. souleyez/docs/README.md +4 -4
  67. souleyez/docs/api-reference/cli-commands.md +2 -2
  68. souleyez/docs/developer-guide/adding-new-tools.md +562 -0
  69. souleyez/docs/user-guide/auto-chaining.md +30 -8
  70. souleyez/docs/user-guide/getting-started.md +1 -1
  71. souleyez/docs/user-guide/installation.md +26 -3
  72. souleyez/docs/user-guide/metasploit-integration.md +2 -2
  73. souleyez/docs/user-guide/rbac.md +1 -1
  74. souleyez/docs/user-guide/scope-management.md +1 -1
  75. souleyez/docs/user-guide/siem-integration.md +1 -1
  76. souleyez/docs/user-guide/tools-reference.md +1 -8
  77. souleyez/docs/user-guide/worker-management.md +1 -1
  78. souleyez/engine/background.py +1238 -535
  79. souleyez/engine/base.py +4 -1
  80. souleyez/engine/job_status.py +17 -49
  81. souleyez/engine/log_sanitizer.py +103 -77
  82. souleyez/engine/manager.py +38 -7
  83. souleyez/engine/result_handler.py +2198 -1550
  84. souleyez/engine/worker_manager.py +50 -41
  85. souleyez/export/evidence_bundle.py +72 -62
  86. souleyez/feature_flags/features.py +16 -20
  87. souleyez/feature_flags.py +5 -9
  88. souleyez/handlers/__init__.py +11 -0
  89. souleyez/handlers/base.py +188 -0
  90. souleyez/handlers/bash_handler.py +277 -0
  91. souleyez/handlers/bloodhound_handler.py +243 -0
  92. souleyez/handlers/certipy_handler.py +311 -0
  93. souleyez/handlers/crackmapexec_handler.py +486 -0
  94. souleyez/handlers/dnsrecon_handler.py +344 -0
  95. souleyez/handlers/enum4linux_handler.py +400 -0
  96. souleyez/handlers/evil_winrm_handler.py +493 -0
  97. souleyez/handlers/ffuf_handler.py +815 -0
  98. souleyez/handlers/gobuster_handler.py +1114 -0
  99. souleyez/handlers/gpp_extract_handler.py +334 -0
  100. souleyez/handlers/hashcat_handler.py +444 -0
  101. souleyez/handlers/hydra_handler.py +563 -0
  102. souleyez/handlers/impacket_getuserspns_handler.py +343 -0
  103. souleyez/handlers/impacket_psexec_handler.py +222 -0
  104. souleyez/handlers/impacket_secretsdump_handler.py +426 -0
  105. souleyez/handlers/john_handler.py +286 -0
  106. souleyez/handlers/katana_handler.py +425 -0
  107. souleyez/handlers/kerbrute_handler.py +298 -0
  108. souleyez/handlers/ldapsearch_handler.py +636 -0
  109. souleyez/handlers/lfi_extract_handler.py +464 -0
  110. souleyez/handlers/msf_auxiliary_handler.py +408 -0
  111. souleyez/handlers/msf_exploit_handler.py +380 -0
  112. souleyez/handlers/nikto_handler.py +413 -0
  113. souleyez/handlers/nmap_handler.py +821 -0
  114. souleyez/handlers/nuclei_handler.py +359 -0
  115. souleyez/handlers/nxc_handler.py +371 -0
  116. souleyez/handlers/rdp_sec_check_handler.py +353 -0
  117. souleyez/handlers/registry.py +288 -0
  118. souleyez/handlers/responder_handler.py +232 -0
  119. souleyez/handlers/service_explorer_handler.py +434 -0
  120. souleyez/handlers/smbclient_handler.py +344 -0
  121. souleyez/handlers/smbmap_handler.py +510 -0
  122. souleyez/handlers/smbpasswd_handler.py +296 -0
  123. souleyez/handlers/sqlmap_handler.py +1116 -0
  124. souleyez/handlers/theharvester_handler.py +601 -0
  125. souleyez/handlers/whois_handler.py +277 -0
  126. souleyez/handlers/wpscan_handler.py +554 -0
  127. souleyez/history.py +32 -16
  128. souleyez/importers/msf_importer.py +106 -75
  129. souleyez/importers/smart_importer.py +208 -147
  130. souleyez/integrations/siem/__init__.py +10 -10
  131. souleyez/integrations/siem/base.py +17 -18
  132. souleyez/integrations/siem/elastic.py +108 -122
  133. souleyez/integrations/siem/factory.py +207 -80
  134. souleyez/integrations/siem/googlesecops.py +146 -154
  135. souleyez/integrations/siem/rule_mappings/__init__.py +1 -1
  136. souleyez/integrations/siem/rule_mappings/wazuh_rules.py +8 -5
  137. souleyez/integrations/siem/sentinel.py +107 -109
  138. souleyez/integrations/siem/splunk.py +246 -212
  139. souleyez/integrations/siem/wazuh.py +65 -71
  140. souleyez/integrations/wazuh/__init__.py +5 -5
  141. souleyez/integrations/wazuh/client.py +70 -93
  142. souleyez/integrations/wazuh/config.py +85 -57
  143. souleyez/integrations/wazuh/host_mapper.py +28 -36
  144. souleyez/integrations/wazuh/sync.py +78 -68
  145. souleyez/intelligence/__init__.py +4 -5
  146. souleyez/intelligence/correlation_analyzer.py +309 -295
  147. souleyez/intelligence/exploit_knowledge.py +661 -623
  148. souleyez/intelligence/exploit_suggestions.py +159 -139
  149. souleyez/intelligence/gap_analyzer.py +132 -97
  150. souleyez/intelligence/gap_detector.py +251 -214
  151. souleyez/intelligence/sensitive_tables.py +266 -129
  152. souleyez/intelligence/service_parser.py +137 -123
  153. souleyez/intelligence/surface_analyzer.py +407 -268
  154. souleyez/intelligence/target_parser.py +159 -162
  155. souleyez/licensing/__init__.py +6 -6
  156. souleyez/licensing/validator.py +17 -19
  157. souleyez/log_config.py +79 -54
  158. souleyez/main.py +1505 -687
  159. souleyez/migrations/fix_job_counter.py +16 -14
  160. souleyez/parsers/bloodhound_parser.py +41 -39
  161. souleyez/parsers/crackmapexec_parser.py +178 -111
  162. souleyez/parsers/dalfox_parser.py +72 -77
  163. souleyez/parsers/dnsrecon_parser.py +103 -91
  164. souleyez/parsers/enum4linux_parser.py +183 -153
  165. souleyez/parsers/ffuf_parser.py +29 -25
  166. souleyez/parsers/gobuster_parser.py +301 -41
  167. souleyez/parsers/hashcat_parser.py +324 -79
  168. souleyez/parsers/http_fingerprint_parser.py +350 -103
  169. souleyez/parsers/hydra_parser.py +131 -111
  170. souleyez/parsers/impacket_parser.py +231 -178
  171. souleyez/parsers/john_parser.py +98 -86
  172. souleyez/parsers/katana_parser.py +316 -0
  173. souleyez/parsers/msf_parser.py +943 -498
  174. souleyez/parsers/nikto_parser.py +346 -65
  175. souleyez/parsers/nmap_parser.py +262 -174
  176. souleyez/parsers/nuclei_parser.py +40 -44
  177. souleyez/parsers/responder_parser.py +26 -26
  178. souleyez/parsers/searchsploit_parser.py +74 -74
  179. souleyez/parsers/service_explorer_parser.py +279 -0
  180. souleyez/parsers/smbmap_parser.py +180 -124
  181. souleyez/parsers/sqlmap_parser.py +434 -308
  182. souleyez/parsers/theharvester_parser.py +75 -57
  183. souleyez/parsers/whois_parser.py +135 -94
  184. souleyez/parsers/wpscan_parser.py +278 -190
  185. souleyez/plugins/afp.py +44 -36
  186. souleyez/plugins/afp_brute.py +114 -46
  187. souleyez/plugins/ard.py +48 -37
  188. souleyez/plugins/bloodhound.py +95 -61
  189. souleyez/plugins/certipy.py +303 -0
  190. souleyez/plugins/crackmapexec.py +186 -85
  191. souleyez/plugins/dalfox.py +120 -59
  192. souleyez/plugins/dns_hijack.py +146 -41
  193. souleyez/plugins/dnsrecon.py +97 -61
  194. souleyez/plugins/enum4linux.py +91 -66
  195. souleyez/plugins/evil_winrm.py +291 -0
  196. souleyez/plugins/ffuf.py +166 -90
  197. souleyez/plugins/firmware_extract.py +133 -29
  198. souleyez/plugins/gobuster.py +387 -190
  199. souleyez/plugins/gpp_extract.py +393 -0
  200. souleyez/plugins/hashcat.py +100 -73
  201. souleyez/plugins/http_fingerprint.py +854 -267
  202. souleyez/plugins/hydra.py +566 -200
  203. souleyez/plugins/impacket_getnpusers.py +117 -69
  204. souleyez/plugins/impacket_psexec.py +84 -64
  205. souleyez/plugins/impacket_secretsdump.py +103 -69
  206. souleyez/plugins/impacket_smbclient.py +89 -75
  207. souleyez/plugins/john.py +86 -69
  208. souleyez/plugins/katana.py +313 -0
  209. souleyez/plugins/kerbrute.py +237 -0
  210. souleyez/plugins/lfi_extract.py +541 -0
  211. souleyez/plugins/macos_ssh.py +117 -48
  212. souleyez/plugins/mdns.py +35 -30
  213. souleyez/plugins/msf_auxiliary.py +253 -130
  214. souleyez/plugins/msf_exploit.py +239 -161
  215. souleyez/plugins/nikto.py +134 -78
  216. souleyez/plugins/nmap.py +275 -91
  217. souleyez/plugins/nuclei.py +180 -89
  218. souleyez/plugins/nxc.py +285 -0
  219. souleyez/plugins/plugin_base.py +35 -36
  220. souleyez/plugins/plugin_template.py +13 -5
  221. souleyez/plugins/rdp_sec_check.py +130 -0
  222. souleyez/plugins/responder.py +112 -71
  223. souleyez/plugins/router_http_brute.py +76 -65
  224. souleyez/plugins/router_ssh_brute.py +118 -41
  225. souleyez/plugins/router_telnet_brute.py +124 -42
  226. souleyez/plugins/routersploit.py +91 -59
  227. souleyez/plugins/routersploit_exploit.py +77 -55
  228. souleyez/plugins/searchsploit.py +91 -77
  229. souleyez/plugins/service_explorer.py +1160 -0
  230. souleyez/plugins/smbmap.py +122 -72
  231. souleyez/plugins/smbpasswd.py +215 -0
  232. souleyez/plugins/sqlmap.py +301 -113
  233. souleyez/plugins/theharvester.py +127 -75
  234. souleyez/plugins/tr069.py +79 -57
  235. souleyez/plugins/upnp.py +65 -47
  236. souleyez/plugins/upnp_abuse.py +73 -55
  237. souleyez/plugins/vnc_access.py +129 -42
  238. souleyez/plugins/vnc_brute.py +109 -38
  239. souleyez/plugins/whois.py +77 -58
  240. souleyez/plugins/wpscan.py +173 -69
  241. souleyez/reporting/__init__.py +2 -1
  242. souleyez/reporting/attack_chain.py +411 -346
  243. souleyez/reporting/charts.py +436 -501
  244. souleyez/reporting/compliance_mappings.py +334 -201
  245. souleyez/reporting/detection_report.py +126 -125
  246. souleyez/reporting/formatters.py +828 -591
  247. souleyez/reporting/generator.py +386 -302
  248. souleyez/reporting/metrics.py +72 -75
  249. souleyez/scanner.py +35 -29
  250. souleyez/security/__init__.py +37 -11
  251. souleyez/security/scope_validator.py +175 -106
  252. souleyez/security/validation.py +223 -149
  253. souleyez/security.py +22 -6
  254. souleyez/storage/credentials.py +247 -186
  255. souleyez/storage/crypto.py +296 -129
  256. souleyez/storage/database.py +73 -50
  257. souleyez/storage/db.py +58 -36
  258. souleyez/storage/deliverable_evidence.py +177 -128
  259. souleyez/storage/deliverable_exporter.py +282 -246
  260. souleyez/storage/deliverable_templates.py +134 -116
  261. souleyez/storage/deliverables.py +135 -130
  262. souleyez/storage/engagements.py +109 -56
  263. souleyez/storage/evidence.py +181 -152
  264. souleyez/storage/execution_log.py +31 -17
  265. souleyez/storage/exploit_attempts.py +93 -57
  266. souleyez/storage/exploits.py +67 -36
  267. souleyez/storage/findings.py +48 -61
  268. souleyez/storage/hosts.py +176 -144
  269. souleyez/storage/migrate_to_engagements.py +43 -19
  270. souleyez/storage/migrations/_001_add_credential_enhancements.py +22 -12
  271. souleyez/storage/migrations/_002_add_status_tracking.py +10 -7
  272. souleyez/storage/migrations/_003_add_execution_log.py +14 -8
  273. souleyez/storage/migrations/_005_screenshots.py +13 -5
  274. souleyez/storage/migrations/_006_deliverables.py +13 -5
  275. souleyez/storage/migrations/_007_deliverable_templates.py +12 -7
  276. souleyez/storage/migrations/_008_add_nuclei_table.py +10 -4
  277. souleyez/storage/migrations/_010_evidence_linking.py +17 -10
  278. souleyez/storage/migrations/_011_timeline_tracking.py +20 -13
  279. souleyez/storage/migrations/_012_team_collaboration.py +34 -21
  280. souleyez/storage/migrations/_013_add_host_tags.py +12 -6
  281. souleyez/storage/migrations/_014_exploit_attempts.py +22 -10
  282. souleyez/storage/migrations/_015_add_mac_os_fields.py +15 -7
  283. souleyez/storage/migrations/_016_add_domain_field.py +10 -4
  284. souleyez/storage/migrations/_017_msf_sessions.py +16 -8
  285. souleyez/storage/migrations/_018_add_osint_target.py +10 -6
  286. souleyez/storage/migrations/_019_add_engagement_type.py +10 -6
  287. souleyez/storage/migrations/_020_add_rbac.py +36 -15
  288. souleyez/storage/migrations/_021_wazuh_integration.py +20 -8
  289. souleyez/storage/migrations/_022_wazuh_indexer_columns.py +6 -4
  290. souleyez/storage/migrations/_023_fix_detection_results_fk.py +16 -6
  291. souleyez/storage/migrations/_024_wazuh_vulnerabilities.py +26 -10
  292. souleyez/storage/migrations/_025_multi_siem_support.py +3 -5
  293. souleyez/storage/migrations/_026_add_engagement_scope.py +31 -12
  294. souleyez/storage/migrations/_027_multi_siem_persistence.py +32 -15
  295. souleyez/storage/migrations/__init__.py +26 -26
  296. souleyez/storage/migrations/migration_manager.py +19 -19
  297. souleyez/storage/msf_sessions.py +100 -65
  298. souleyez/storage/osint.py +17 -24
  299. souleyez/storage/recommendation_engine.py +269 -235
  300. souleyez/storage/screenshots.py +33 -32
  301. souleyez/storage/smb_shares.py +136 -92
  302. souleyez/storage/sqlmap_data.py +183 -128
  303. souleyez/storage/team_collaboration.py +135 -141
  304. souleyez/storage/timeline_tracker.py +122 -94
  305. souleyez/storage/wazuh_vulns.py +64 -66
  306. souleyez/storage/web_paths.py +33 -37
  307. souleyez/testing/credential_tester.py +221 -205
  308. souleyez/ui/__init__.py +1 -1
  309. souleyez/ui/ai_quotes.py +12 -12
  310. souleyez/ui/attack_surface.py +2439 -1516
  311. souleyez/ui/chain_rules_view.py +914 -382
  312. souleyez/ui/correlation_view.py +312 -230
  313. souleyez/ui/dashboard.py +2382 -1130
  314. souleyez/ui/deliverables_view.py +148 -62
  315. souleyez/ui/design_system.py +13 -13
  316. souleyez/ui/errors.py +49 -49
  317. souleyez/ui/evidence_linking_view.py +284 -179
  318. souleyez/ui/evidence_vault.py +393 -285
  319. souleyez/ui/exploit_suggestions_view.py +555 -349
  320. souleyez/ui/export_view.py +100 -66
  321. souleyez/ui/gap_analysis_view.py +315 -171
  322. souleyez/ui/help_system.py +105 -97
  323. souleyez/ui/intelligence_view.py +436 -293
  324. souleyez/ui/interactive.py +23142 -10430
  325. souleyez/ui/interactive_selector.py +75 -68
  326. souleyez/ui/log_formatter.py +47 -39
  327. souleyez/ui/menu_components.py +22 -13
  328. souleyez/ui/msf_auxiliary_menu.py +184 -133
  329. souleyez/ui/pending_chains_view.py +336 -172
  330. souleyez/ui/progress_indicators.py +5 -3
  331. souleyez/ui/recommendations_view.py +195 -137
  332. souleyez/ui/rule_builder.py +343 -225
  333. souleyez/ui/setup_wizard.py +678 -284
  334. souleyez/ui/shortcuts.py +217 -165
  335. souleyez/ui/splunk_gap_analysis_view.py +452 -270
  336. souleyez/ui/splunk_vulns_view.py +139 -86
  337. souleyez/ui/team_dashboard.py +498 -335
  338. souleyez/ui/template_selector.py +196 -105
  339. souleyez/ui/terminal.py +6 -6
  340. souleyez/ui/timeline_view.py +198 -127
  341. souleyez/ui/tool_setup.py +264 -164
  342. souleyez/ui/tutorial.py +202 -72
  343. souleyez/ui/tutorial_state.py +40 -40
  344. souleyez/ui/wazuh_vulns_view.py +235 -141
  345. souleyez/ui/wordlist_browser.py +260 -107
  346. souleyez/ui.py +464 -312
  347. souleyez/utils/tool_checker.py +427 -367
  348. souleyez/utils.py +33 -29
  349. souleyez/wordlists.py +134 -167
  350. {souleyez-2.43.28.dist-info → souleyez-2.43.32.dist-info}/METADATA +1 -1
  351. souleyez-2.43.32.dist-info/RECORD +441 -0
  352. {souleyez-2.43.28.dist-info → souleyez-2.43.32.dist-info}/WHEEL +1 -1
  353. souleyez-2.43.28.dist-info/RECORD +0 -379
  354. {souleyez-2.43.28.dist-info → souleyez-2.43.32.dist-info}/entry_points.txt +0 -0
  355. {souleyez-2.43.28.dist-info → souleyez-2.43.32.dist-info}/licenses/LICENSE +0 -0
  356. {souleyez-2.43.28.dist-info → souleyez-2.43.32.dist-info}/top_level.txt +0 -0
@@ -22,7 +22,9 @@ class CredentialTester:
22
22
  self.fm = FindingsManager()
23
23
  self.em = EngagementManager()
24
24
 
25
- def test_ssh_credential(self, host: str, username: str, password: str = None, timeout: int = 10) -> Tuple[bool, str]:
25
+ def test_ssh_credential(
26
+ self, host: str, username: str, password: str = None, timeout: int = 10
27
+ ) -> Tuple[bool, str]:
26
28
  """
27
29
  Test SSH credential against a host.
28
30
 
@@ -37,22 +39,26 @@ class CredentialTester:
37
39
  # Use sshpass to test credentials non-interactively
38
40
  # Add legacy crypto support for old SSH servers (like metasploitable)
39
41
  cmd = [
40
- 'sshpass', '-p', password,
41
- 'ssh', '-o', 'StrictHostKeyChecking=no',
42
- '-o', 'ConnectTimeout=5',
43
- '-o', 'HostKeyAlgorithms=+ssh-rsa',
44
- f'{username}@{host}',
45
- 'echo', 'SUCCESS'
42
+ "sshpass",
43
+ "-p",
44
+ password,
45
+ "ssh",
46
+ "-o",
47
+ "StrictHostKeyChecking=no",
48
+ "-o",
49
+ "ConnectTimeout=5",
50
+ "-o",
51
+ "HostKeyAlgorithms=+ssh-rsa",
52
+ f"{username}@{host}",
53
+ "echo",
54
+ "SUCCESS",
46
55
  ]
47
56
 
48
57
  result = subprocess.run(
49
- cmd,
50
- capture_output=True,
51
- text=True,
52
- timeout=timeout
58
+ cmd, capture_output=True, text=True, timeout=timeout
53
59
  )
54
60
 
55
- if result.returncode == 0 and 'SUCCESS' in result.stdout:
61
+ if result.returncode == 0 and "SUCCESS" in result.stdout:
56
62
  return (True, "SSH authentication successful")
57
63
  else:
58
64
  return (False, f"Authentication failed (rc={result.returncode})")
@@ -64,7 +70,9 @@ class CredentialTester:
64
70
  except Exception as e:
65
71
  return (False, f"Error: {str(e)}")
66
72
 
67
- def test_smb_credential(self, host: str, username: str, password: str = None, timeout: int = 10) -> Tuple[bool, str]:
73
+ def test_smb_credential(
74
+ self, host: str, username: str, password: str = None, timeout: int = 10
75
+ ) -> Tuple[bool, str]:
68
76
  """
69
77
  Test SMB credential against a host.
70
78
 
@@ -77,17 +85,16 @@ class CredentialTester:
77
85
  try:
78
86
  # Use smbclient to test credentials
79
87
  cmd = [
80
- 'smbclient',
81
- f'//{host}/IPC$',
82
- '-U', f'{username}%{password}',
83
- '-c', 'exit'
88
+ "smbclient",
89
+ f"//{host}/IPC$",
90
+ "-U",
91
+ f"{username}%{password}",
92
+ "-c",
93
+ "exit",
84
94
  ]
85
95
 
86
96
  result = subprocess.run(
87
- cmd,
88
- capture_output=True,
89
- text=True,
90
- timeout=timeout
97
+ cmd, capture_output=True, text=True, timeout=timeout
91
98
  )
92
99
 
93
100
  # smbclient returns 0 on success
@@ -96,9 +103,9 @@ class CredentialTester:
96
103
  else:
97
104
  # Check for specific error messages
98
105
  stderr = result.stderr.lower()
99
- if 'logon failure' in stderr or 'access denied' in stderr:
106
+ if "logon failure" in stderr or "access denied" in stderr:
100
107
  return (False, "Invalid credentials")
101
- elif 'connection refused' in stderr:
108
+ elif "connection refused" in stderr:
102
109
  return (False, "SMB service not available")
103
110
  else:
104
111
  return (False, f"Authentication failed (rc={result.returncode})")
@@ -124,30 +131,30 @@ class CredentialTester:
124
131
  'tested_at': str
125
132
  }
126
133
  """
127
- service = cred.get('service', '').lower()
128
- username = cred.get('username')
129
- password = cred.get('password')
130
- host_ip = host.get('ip_address')
134
+ service = cred.get("service", "").lower()
135
+ username = cred.get("username")
136
+ password = cred.get("password")
137
+ host_ip = host.get("ip_address")
131
138
 
132
139
  result = {
133
- 'credential_id': cred.get('id'),
134
- 'host_id': host.get('id'),
135
- 'service': service,
136
- 'success': False,
137
- 'message': 'Unknown service',
138
- 'tested_at': time.strftime('%Y-%m-%d %H:%M:%S UTC', time.gmtime())
140
+ "credential_id": cred.get("id"),
141
+ "host_id": host.get("id"),
142
+ "service": service,
143
+ "success": False,
144
+ "message": "Unknown service",
145
+ "tested_at": time.strftime("%Y-%m-%d %H:%M:%S UTC", time.gmtime()),
139
146
  }
140
147
 
141
- if service == 'ssh':
148
+ if service == "ssh":
142
149
  success, message = self.test_ssh_credential(host_ip, username, password)
143
- result['success'] = success
144
- result['message'] = message
145
- elif service == 'smb':
150
+ result["success"] = success
151
+ result["message"] = message
152
+ elif service == "smb":
146
153
  success, message = self.test_smb_credential(host_ip, username, password)
147
- result['success'] = success
148
- result['message'] = message
154
+ result["success"] = success
155
+ result["message"] = message
149
156
  else:
150
- result['message'] = f"Testing not implemented for service: {service}"
157
+ result["message"] = f"Testing not implemented for service: {service}"
151
158
 
152
159
  return result
153
160
 
@@ -169,79 +176,78 @@ class CredentialTester:
169
176
  hosts = self.hm.list_hosts(engagement_id)
170
177
 
171
178
  # Filter to only active hosts
172
- active_hosts = [h for h in hosts if h.get('status') == 'up']
179
+ active_hosts = [h for h in hosts if h.get("status") == "up"]
173
180
 
174
181
  results = {
175
- 'total_tests': 0,
176
- 'successful': 0,
177
- 'failed': 0,
178
- 'findings_created': 0,
179
- 'results': []
182
+ "total_tests": 0,
183
+ "successful": 0,
184
+ "failed": 0,
185
+ "findings_created": 0,
186
+ "results": [],
180
187
  }
181
188
 
182
189
  # Test each credential against each host
183
190
  for cred in credentials:
184
191
  # Skip username-only credentials for now (need password to test)
185
- if not cred.get('password'):
192
+ if not cred.get("password"):
186
193
  continue
187
194
 
188
- service = cred.get('service', '').lower()
195
+ service = cred.get("service", "").lower()
189
196
 
190
197
  for host in active_hosts:
191
198
  # Only test if host has the service running
192
199
  if not self._host_has_service(host, service, engagement_id):
193
200
  continue
194
201
 
195
- results['total_tests'] += 1
202
+ results["total_tests"] += 1
196
203
 
197
204
  # Test the credential
198
205
  test_result = self.test_credential_against_host(cred, host)
199
- results['results'].append(test_result)
206
+ results["results"].append(test_result)
200
207
 
201
- if test_result['success']:
202
- results['successful'] += 1
208
+ if test_result["success"]:
209
+ results["successful"] += 1
203
210
 
204
211
  # Create a finding for successful authentication
205
212
  finding = self._create_finding_for_success(
206
- engagement_id,
207
- host,
208
- cred,
209
- test_result
213
+ engagement_id, host, cred, test_result
210
214
  )
211
215
  if finding:
212
- results['findings_created'] += 1
216
+ results["findings_created"] += 1
213
217
  else:
214
- results['failed'] += 1
218
+ results["failed"] += 1
215
219
 
216
220
  return results
217
221
 
218
222
  def _host_has_service(self, host: Dict, service: str, engagement_id: int) -> bool:
219
223
  """Check if a host has a specific service running."""
220
224
  # Get services for this host from HostManager
221
- services = self.hm.get_host_services(host.get('id'))
225
+ services = self.hm.get_host_services(host.get("id"))
222
226
 
223
227
  # Check if service type matches
224
228
  service_ports = {
225
- 'ssh': [22],
226
- 'smb': [139, 445],
227
- 'rdp': [3389],
228
- 'ftp': [21],
229
- 'mysql': [3306],
230
- 'postgres': [5432]
229
+ "ssh": [22],
230
+ "smb": [139, 445],
231
+ "rdp": [3389],
232
+ "ftp": [21],
233
+ "mysql": [3306],
234
+ "postgres": [5432],
231
235
  }
232
236
 
233
237
  target_ports = service_ports.get(service, [])
234
238
  for svc in services:
235
- if svc.get('port') in target_ports:
239
+ if svc.get("port") in target_ports:
236
240
  return True
237
241
 
238
242
  return False
239
243
 
240
- def _create_finding_for_success(self, engagement_id: int, host: Dict, cred: Dict, test_result: Dict) -> Optional[Dict]:
244
+ def _create_finding_for_success(
245
+ self, engagement_id: int, host: Dict, cred: Dict, test_result: Dict
246
+ ) -> Optional[Dict]:
241
247
  """Create a finding for successful credential test."""
242
- service = cred.get('service', 'unknown')
243
- username = cred.get('username', 'unknown')
244
- host_ip = host.get('ip_address', 'unknown')
248
+ service = cred.get("service", "unknown")
249
+ username = cred.get("username", "unknown")
250
+ host_ip = host.get("ip_address", "unknown")
245
251
 
246
252
  title = f"Valid {service.upper()} Credentials - {username}@{host_ip}"
247
253
  description = f"""
@@ -274,11 +280,11 @@ An attacker with these credentials can:
274
280
  finding = self.fm.add_finding(
275
281
  engagement_id,
276
282
  title,
277
- 'vulnerability', # finding_type
283
+ "vulnerability", # finding_type
278
284
  severity=severity,
279
285
  description=description.strip(),
280
- host_id=host.get('id'),
281
- tool='credential_tester'
286
+ host_id=host.get("id"),
287
+ tool="credential_tester",
282
288
  )
283
289
  return finding
284
290
  except Exception as e:
@@ -287,22 +293,22 @@ An attacker with these credentials can:
287
293
 
288
294
  def _determine_credential_severity(self, cred: Dict, host: Dict) -> str:
289
295
  """Determine severity based on credential and host context."""
290
- username = cred.get('username', '').lower()
291
- password = cred.get('password', '')
296
+ username = cred.get("username", "").lower()
297
+ password = cred.get("password", "")
292
298
 
293
299
  # High severity for privileged accounts
294
- privileged_users = ['root', 'admin', 'administrator', 'sa', 'postgres', 'mysql']
300
+ privileged_users = ["root", "admin", "administrator", "sa", "postgres", "mysql"]
295
301
  if username in privileged_users:
296
- return 'high'
302
+ return "high"
297
303
 
298
304
  # High severity for weak/default passwords
299
- weak_passwords = ['password', 'admin', '123456', 'root', 'toor', 'changeme', '']
305
+ weak_passwords = ["password", "admin", "123456", "root", "toor", "changeme", ""]
300
306
  if password.lower() in weak_passwords:
301
- return 'high'
307
+ return "high"
302
308
 
303
309
  # High severity for short passwords
304
310
  if len(password) < 8:
305
- return 'high'
311
+ return "high"
306
312
 
307
313
  # Medium severity for standard users
308
- return 'medium'
314
+ return "medium"