souleyez 2.43.26__py3-none-any.whl → 2.43.34__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (358) 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 +9526 -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 +1239 -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 +2200 -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 +292 -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/web_login_test_handler.py +327 -0
  126. souleyez/handlers/whois_handler.py +277 -0
  127. souleyez/handlers/wpscan_handler.py +554 -0
  128. souleyez/history.py +32 -16
  129. souleyez/importers/msf_importer.py +106 -75
  130. souleyez/importers/smart_importer.py +208 -147
  131. souleyez/integrations/siem/__init__.py +10 -10
  132. souleyez/integrations/siem/base.py +17 -18
  133. souleyez/integrations/siem/elastic.py +108 -122
  134. souleyez/integrations/siem/factory.py +207 -80
  135. souleyez/integrations/siem/googlesecops.py +146 -154
  136. souleyez/integrations/siem/rule_mappings/__init__.py +1 -1
  137. souleyez/integrations/siem/rule_mappings/wazuh_rules.py +8 -5
  138. souleyez/integrations/siem/sentinel.py +107 -109
  139. souleyez/integrations/siem/splunk.py +246 -212
  140. souleyez/integrations/siem/wazuh.py +65 -71
  141. souleyez/integrations/wazuh/__init__.py +5 -5
  142. souleyez/integrations/wazuh/client.py +70 -93
  143. souleyez/integrations/wazuh/config.py +85 -57
  144. souleyez/integrations/wazuh/host_mapper.py +28 -36
  145. souleyez/integrations/wazuh/sync.py +78 -68
  146. souleyez/intelligence/__init__.py +4 -5
  147. souleyez/intelligence/correlation_analyzer.py +309 -295
  148. souleyez/intelligence/exploit_knowledge.py +661 -623
  149. souleyez/intelligence/exploit_suggestions.py +159 -139
  150. souleyez/intelligence/gap_analyzer.py +132 -97
  151. souleyez/intelligence/gap_detector.py +251 -214
  152. souleyez/intelligence/sensitive_tables.py +266 -129
  153. souleyez/intelligence/service_parser.py +137 -123
  154. souleyez/intelligence/surface_analyzer.py +407 -268
  155. souleyez/intelligence/target_parser.py +159 -162
  156. souleyez/licensing/__init__.py +6 -6
  157. souleyez/licensing/validator.py +17 -19
  158. souleyez/log_config.py +79 -54
  159. souleyez/main.py +1505 -687
  160. souleyez/migrations/fix_job_counter.py +16 -14
  161. souleyez/parsers/bloodhound_parser.py +41 -39
  162. souleyez/parsers/crackmapexec_parser.py +178 -111
  163. souleyez/parsers/dalfox_parser.py +72 -77
  164. souleyez/parsers/dnsrecon_parser.py +103 -91
  165. souleyez/parsers/enum4linux_parser.py +183 -153
  166. souleyez/parsers/ffuf_parser.py +29 -25
  167. souleyez/parsers/gobuster_parser.py +301 -41
  168. souleyez/parsers/hashcat_parser.py +324 -79
  169. souleyez/parsers/http_fingerprint_parser.py +350 -103
  170. souleyez/parsers/hydra_parser.py +131 -111
  171. souleyez/parsers/impacket_parser.py +231 -178
  172. souleyez/parsers/john_parser.py +98 -86
  173. souleyez/parsers/katana_parser.py +316 -0
  174. souleyez/parsers/msf_parser.py +943 -498
  175. souleyez/parsers/nikto_parser.py +346 -65
  176. souleyez/parsers/nmap_parser.py +262 -174
  177. souleyez/parsers/nuclei_parser.py +40 -44
  178. souleyez/parsers/responder_parser.py +26 -26
  179. souleyez/parsers/searchsploit_parser.py +74 -74
  180. souleyez/parsers/service_explorer_parser.py +279 -0
  181. souleyez/parsers/smbmap_parser.py +180 -124
  182. souleyez/parsers/sqlmap_parser.py +434 -308
  183. souleyez/parsers/theharvester_parser.py +75 -57
  184. souleyez/parsers/whois_parser.py +135 -94
  185. souleyez/parsers/wpscan_parser.py +278 -190
  186. souleyez/plugins/afp.py +44 -36
  187. souleyez/plugins/afp_brute.py +114 -46
  188. souleyez/plugins/ard.py +48 -37
  189. souleyez/plugins/bloodhound.py +95 -61
  190. souleyez/plugins/certipy.py +303 -0
  191. souleyez/plugins/crackmapexec.py +186 -85
  192. souleyez/plugins/dalfox.py +120 -59
  193. souleyez/plugins/dns_hijack.py +146 -41
  194. souleyez/plugins/dnsrecon.py +97 -61
  195. souleyez/plugins/enum4linux.py +91 -66
  196. souleyez/plugins/evil_winrm.py +291 -0
  197. souleyez/plugins/ffuf.py +166 -90
  198. souleyez/plugins/firmware_extract.py +133 -29
  199. souleyez/plugins/gobuster.py +387 -190
  200. souleyez/plugins/gpp_extract.py +393 -0
  201. souleyez/plugins/hashcat.py +100 -73
  202. souleyez/plugins/http_fingerprint.py +854 -267
  203. souleyez/plugins/hydra.py +566 -200
  204. souleyez/plugins/impacket_getnpusers.py +117 -69
  205. souleyez/plugins/impacket_psexec.py +84 -64
  206. souleyez/plugins/impacket_secretsdump.py +103 -69
  207. souleyez/plugins/impacket_smbclient.py +89 -75
  208. souleyez/plugins/john.py +86 -69
  209. souleyez/plugins/katana.py +313 -0
  210. souleyez/plugins/kerbrute.py +237 -0
  211. souleyez/plugins/lfi_extract.py +541 -0
  212. souleyez/plugins/macos_ssh.py +117 -48
  213. souleyez/plugins/mdns.py +35 -30
  214. souleyez/plugins/msf_auxiliary.py +253 -130
  215. souleyez/plugins/msf_exploit.py +239 -161
  216. souleyez/plugins/nikto.py +134 -78
  217. souleyez/plugins/nmap.py +275 -91
  218. souleyez/plugins/nuclei.py +180 -89
  219. souleyez/plugins/nxc.py +285 -0
  220. souleyez/plugins/plugin_base.py +35 -36
  221. souleyez/plugins/plugin_template.py +13 -5
  222. souleyez/plugins/rdp_sec_check.py +130 -0
  223. souleyez/plugins/responder.py +112 -71
  224. souleyez/plugins/router_http_brute.py +76 -65
  225. souleyez/plugins/router_ssh_brute.py +118 -41
  226. souleyez/plugins/router_telnet_brute.py +124 -42
  227. souleyez/plugins/routersploit.py +91 -59
  228. souleyez/plugins/routersploit_exploit.py +77 -55
  229. souleyez/plugins/searchsploit.py +91 -77
  230. souleyez/plugins/service_explorer.py +1160 -0
  231. souleyez/plugins/smbmap.py +122 -72
  232. souleyez/plugins/smbpasswd.py +215 -0
  233. souleyez/plugins/sqlmap.py +301 -113
  234. souleyez/plugins/theharvester.py +127 -75
  235. souleyez/plugins/tr069.py +79 -57
  236. souleyez/plugins/upnp.py +65 -47
  237. souleyez/plugins/upnp_abuse.py +73 -55
  238. souleyez/plugins/vnc_access.py +129 -42
  239. souleyez/plugins/vnc_brute.py +109 -38
  240. souleyez/plugins/web_login_test.py +417 -0
  241. souleyez/plugins/whois.py +77 -58
  242. souleyez/plugins/wpscan.py +173 -69
  243. souleyez/reporting/__init__.py +2 -1
  244. souleyez/reporting/attack_chain.py +411 -346
  245. souleyez/reporting/charts.py +436 -501
  246. souleyez/reporting/compliance_mappings.py +334 -201
  247. souleyez/reporting/detection_report.py +126 -125
  248. souleyez/reporting/formatters.py +828 -591
  249. souleyez/reporting/generator.py +386 -302
  250. souleyez/reporting/metrics.py +72 -75
  251. souleyez/scanner.py +35 -29
  252. souleyez/security/__init__.py +37 -11
  253. souleyez/security/scope_validator.py +175 -106
  254. souleyez/security/validation.py +223 -149
  255. souleyez/security.py +22 -6
  256. souleyez/storage/credentials.py +247 -186
  257. souleyez/storage/crypto.py +296 -129
  258. souleyez/storage/database.py +73 -50
  259. souleyez/storage/db.py +58 -36
  260. souleyez/storage/deliverable_evidence.py +177 -128
  261. souleyez/storage/deliverable_exporter.py +282 -246
  262. souleyez/storage/deliverable_templates.py +134 -116
  263. souleyez/storage/deliverables.py +135 -130
  264. souleyez/storage/engagements.py +109 -56
  265. souleyez/storage/evidence.py +181 -152
  266. souleyez/storage/execution_log.py +31 -17
  267. souleyez/storage/exploit_attempts.py +93 -57
  268. souleyez/storage/exploits.py +67 -36
  269. souleyez/storage/findings.py +48 -61
  270. souleyez/storage/hosts.py +176 -144
  271. souleyez/storage/migrate_to_engagements.py +43 -19
  272. souleyez/storage/migrations/_001_add_credential_enhancements.py +22 -12
  273. souleyez/storage/migrations/_002_add_status_tracking.py +10 -7
  274. souleyez/storage/migrations/_003_add_execution_log.py +14 -8
  275. souleyez/storage/migrations/_005_screenshots.py +13 -5
  276. souleyez/storage/migrations/_006_deliverables.py +13 -5
  277. souleyez/storage/migrations/_007_deliverable_templates.py +12 -7
  278. souleyez/storage/migrations/_008_add_nuclei_table.py +10 -4
  279. souleyez/storage/migrations/_010_evidence_linking.py +17 -10
  280. souleyez/storage/migrations/_011_timeline_tracking.py +20 -13
  281. souleyez/storage/migrations/_012_team_collaboration.py +34 -21
  282. souleyez/storage/migrations/_013_add_host_tags.py +12 -6
  283. souleyez/storage/migrations/_014_exploit_attempts.py +22 -10
  284. souleyez/storage/migrations/_015_add_mac_os_fields.py +15 -7
  285. souleyez/storage/migrations/_016_add_domain_field.py +10 -4
  286. souleyez/storage/migrations/_017_msf_sessions.py +16 -8
  287. souleyez/storage/migrations/_018_add_osint_target.py +10 -6
  288. souleyez/storage/migrations/_019_add_engagement_type.py +10 -6
  289. souleyez/storage/migrations/_020_add_rbac.py +36 -15
  290. souleyez/storage/migrations/_021_wazuh_integration.py +20 -8
  291. souleyez/storage/migrations/_022_wazuh_indexer_columns.py +6 -4
  292. souleyez/storage/migrations/_023_fix_detection_results_fk.py +16 -6
  293. souleyez/storage/migrations/_024_wazuh_vulnerabilities.py +26 -10
  294. souleyez/storage/migrations/_025_multi_siem_support.py +3 -5
  295. souleyez/storage/migrations/_026_add_engagement_scope.py +31 -12
  296. souleyez/storage/migrations/_027_multi_siem_persistence.py +32 -15
  297. souleyez/storage/migrations/__init__.py +26 -26
  298. souleyez/storage/migrations/migration_manager.py +19 -19
  299. souleyez/storage/msf_sessions.py +100 -65
  300. souleyez/storage/osint.py +17 -24
  301. souleyez/storage/recommendation_engine.py +269 -235
  302. souleyez/storage/screenshots.py +33 -32
  303. souleyez/storage/smb_shares.py +136 -92
  304. souleyez/storage/sqlmap_data.py +183 -128
  305. souleyez/storage/team_collaboration.py +135 -141
  306. souleyez/storage/timeline_tracker.py +122 -94
  307. souleyez/storage/wazuh_vulns.py +64 -66
  308. souleyez/storage/web_paths.py +33 -37
  309. souleyez/testing/credential_tester.py +221 -205
  310. souleyez/ui/__init__.py +1 -1
  311. souleyez/ui/ai_quotes.py +12 -12
  312. souleyez/ui/attack_surface.py +2439 -1516
  313. souleyez/ui/chain_rules_view.py +914 -382
  314. souleyez/ui/correlation_view.py +312 -230
  315. souleyez/ui/dashboard.py +2382 -1130
  316. souleyez/ui/deliverables_view.py +148 -62
  317. souleyez/ui/design_system.py +13 -13
  318. souleyez/ui/errors.py +49 -49
  319. souleyez/ui/evidence_linking_view.py +284 -179
  320. souleyez/ui/evidence_vault.py +393 -285
  321. souleyez/ui/exploit_suggestions_view.py +555 -349
  322. souleyez/ui/export_view.py +100 -66
  323. souleyez/ui/gap_analysis_view.py +315 -171
  324. souleyez/ui/help_system.py +105 -97
  325. souleyez/ui/intelligence_view.py +436 -293
  326. souleyez/ui/interactive.py +23434 -10286
  327. souleyez/ui/interactive_selector.py +75 -68
  328. souleyez/ui/log_formatter.py +47 -39
  329. souleyez/ui/menu_components.py +22 -13
  330. souleyez/ui/msf_auxiliary_menu.py +184 -133
  331. souleyez/ui/pending_chains_view.py +336 -172
  332. souleyez/ui/progress_indicators.py +5 -3
  333. souleyez/ui/recommendations_view.py +195 -137
  334. souleyez/ui/rule_builder.py +343 -225
  335. souleyez/ui/setup_wizard.py +678 -284
  336. souleyez/ui/shortcuts.py +217 -165
  337. souleyez/ui/splunk_gap_analysis_view.py +452 -270
  338. souleyez/ui/splunk_vulns_view.py +139 -86
  339. souleyez/ui/team_dashboard.py +498 -335
  340. souleyez/ui/template_selector.py +196 -105
  341. souleyez/ui/terminal.py +6 -6
  342. souleyez/ui/timeline_view.py +198 -127
  343. souleyez/ui/tool_setup.py +264 -164
  344. souleyez/ui/tutorial.py +202 -72
  345. souleyez/ui/tutorial_state.py +40 -40
  346. souleyez/ui/wazuh_vulns_view.py +235 -141
  347. souleyez/ui/wordlist_browser.py +260 -107
  348. souleyez/ui.py +464 -312
  349. souleyez/utils/tool_checker.py +427 -367
  350. souleyez/utils.py +33 -29
  351. souleyez/wordlists.py +134 -167
  352. {souleyez-2.43.26.dist-info → souleyez-2.43.34.dist-info}/METADATA +1 -1
  353. souleyez-2.43.34.dist-info/RECORD +443 -0
  354. {souleyez-2.43.26.dist-info → souleyez-2.43.34.dist-info}/WHEEL +1 -1
  355. souleyez-2.43.26.dist-info/RECORD +0 -379
  356. {souleyez-2.43.26.dist-info → souleyez-2.43.34.dist-info}/entry_points.txt +0 -0
  357. {souleyez-2.43.26.dist-info → souleyez-2.43.34.dist-info}/licenses/LICENSE +0 -0
  358. {souleyez-2.43.26.dist-info → souleyez-2.43.34.dist-info}/top_level.txt +0 -0
@@ -22,7 +22,9 @@ class CredentialTester:
22
22
  self.fm = FindingsManager()
23
23
  self.em = EngagementManager()
24
24
 
25
- def test_ssh_credential(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"