souleyez 2.43.29__py3-none-any.whl → 3.0.0__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 +9564 -2881
  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 +564 -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 +409 -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 +417 -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 +913 -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 +219 -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 +237 -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 +23034 -10679
  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.29.dist-info → souleyez-3.0.0.dist-info}/METADATA +2 -2
  353. souleyez-3.0.0.dist-info/RECORD +443 -0
  354. {souleyez-2.43.29.dist-info → souleyez-3.0.0.dist-info}/WHEEL +1 -1
  355. souleyez-2.43.29.dist-info/RECORD +0 -379
  356. {souleyez-2.43.29.dist-info → souleyez-3.0.0.dist-info}/entry_points.txt +0 -0
  357. {souleyez-2.43.29.dist-info → souleyez-3.0.0.dist-info}/licenses/LICENSE +0 -0
  358. {souleyez-2.43.29.dist-info → souleyez-3.0.0.dist-info}/top_level.txt +0 -0
@@ -50,20 +50,15 @@ def parse_dalfox_output(output: str, target: str = "") -> Dict[str, Any]:
50
50
  }
51
51
  """
52
52
  result = {
53
- 'target': target,
54
- 'vulnerabilities': [],
55
- 'parameters': [],
56
- 'warnings': [],
57
- 'info': [],
58
- 'stats': {
59
- 'total_vulns': 0,
60
- 'reflected': 0,
61
- 'dom': 0,
62
- 'parameters_found': 0
63
- }
53
+ "target": target,
54
+ "vulnerabilities": [],
55
+ "parameters": [],
56
+ "warnings": [],
57
+ "info": [],
58
+ "stats": {"total_vulns": 0, "reflected": 0, "dom": 0, "parameters_found": 0},
64
59
  }
65
60
 
66
- lines = output.split('\n')
61
+ lines = output.split("\n")
67
62
 
68
63
  for line in lines:
69
64
  line = line.strip()
@@ -71,7 +66,7 @@ def parse_dalfox_output(output: str, target: str = "") -> Dict[str, Any]:
71
66
  continue
72
67
 
73
68
  # Try JSON parsing first
74
- if line.startswith('{'):
69
+ if line.startswith("{"):
75
70
  try:
76
71
  data = json.loads(line)
77
72
  _process_json_line(data, result)
@@ -83,139 +78,139 @@ def parse_dalfox_output(output: str, target: str = "") -> Dict[str, Any]:
83
78
  _process_text_line(line, result)
84
79
 
85
80
  # Update stats
86
- result['stats']['total_vulns'] = len(result['vulnerabilities'])
87
- result['stats']['parameters_found'] = len(result['parameters'])
81
+ result["stats"]["total_vulns"] = len(result["vulnerabilities"])
82
+ result["stats"]["parameters_found"] = len(result["parameters"])
88
83
 
89
84
  return result
90
85
 
91
86
 
92
87
  def _process_json_line(data: Dict, result: Dict):
93
88
  """Process a JSON-formatted line from Dalfox."""
94
- msg_type = data.get('type', '')
95
- msg_data = data.get('data', '')
96
- poc = data.get('poc', '')
97
- cwe = data.get('cwe', '')
89
+ msg_type = data.get("type", "")
90
+ msg_data = data.get("data", "")
91
+ poc = data.get("poc", "")
92
+ cwe = data.get("cwe", "")
98
93
 
99
- if msg_type == 'V':
94
+ if msg_type == "V":
100
95
  # Vulnerability found
101
96
  vuln = {
102
- 'type': _detect_xss_type(msg_data),
103
- 'parameter': _extract_parameter(poc or msg_data),
104
- 'payload': _extract_payload(poc or msg_data),
105
- 'poc': poc,
106
- 'cwe': cwe,
107
- 'raw': msg_data
97
+ "type": _detect_xss_type(msg_data),
98
+ "parameter": _extract_parameter(poc or msg_data),
99
+ "payload": _extract_payload(poc or msg_data),
100
+ "poc": poc,
101
+ "cwe": cwe,
102
+ "raw": msg_data,
108
103
  }
109
- result['vulnerabilities'].append(vuln)
104
+ result["vulnerabilities"].append(vuln)
110
105
 
111
- if 'dom' in msg_data.lower():
112
- result['stats']['dom'] += 1
106
+ if "dom" in msg_data.lower():
107
+ result["stats"]["dom"] += 1
113
108
  else:
114
- result['stats']['reflected'] += 1
109
+ result["stats"]["reflected"] += 1
115
110
 
116
- elif msg_type == 'I':
117
- result['info'].append(msg_data)
111
+ elif msg_type == "I":
112
+ result["info"].append(msg_data)
118
113
  # Check for parameter discovery
119
114
  param = _extract_discovered_param(msg_data)
120
- if param and param not in result['parameters']:
121
- result['parameters'].append(param)
115
+ if param and param not in result["parameters"]:
116
+ result["parameters"].append(param)
122
117
 
123
- elif msg_type == 'W':
124
- result['warnings'].append(msg_data)
118
+ elif msg_type == "W":
119
+ result["warnings"].append(msg_data)
125
120
 
126
121
 
127
122
  def _process_text_line(line: str, result: Dict):
128
123
  """Process a text-formatted line from Dalfox."""
129
124
 
130
125
  # Vulnerability line: [V] or [POC]
131
- if line.startswith('[V]') or 'Vulnerable' in line:
126
+ if line.startswith("[V]") or "Vulnerable" in line:
132
127
  vuln = {
133
- 'type': _detect_xss_type(line),
134
- 'parameter': _extract_parameter(line),
135
- 'payload': _extract_payload(line),
136
- 'poc': '',
137
- 'cwe': 'CWE-79',
138
- 'raw': line
128
+ "type": _detect_xss_type(line),
129
+ "parameter": _extract_parameter(line),
130
+ "payload": _extract_payload(line),
131
+ "poc": "",
132
+ "cwe": "CWE-79",
133
+ "raw": line,
139
134
  }
140
- result['vulnerabilities'].append(vuln)
135
+ result["vulnerabilities"].append(vuln)
141
136
 
142
- if 'dom' in line.lower():
143
- result['stats']['dom'] += 1
137
+ if "dom" in line.lower():
138
+ result["stats"]["dom"] += 1
144
139
  else:
145
- result['stats']['reflected'] += 1
140
+ result["stats"]["reflected"] += 1
146
141
 
147
- elif line.startswith('[POC]'):
142
+ elif line.startswith("[POC]"):
148
143
  # Add POC to last vulnerability
149
- poc = line.replace('[POC]', '').strip()
150
- if result['vulnerabilities']:
151
- result['vulnerabilities'][-1]['poc'] = poc
144
+ poc = line.replace("[POC]", "").strip()
145
+ if result["vulnerabilities"]:
146
+ result["vulnerabilities"][-1]["poc"] = poc
152
147
 
153
- elif line.startswith('[I]') or 'Found parameter' in line:
154
- result['info'].append(line)
148
+ elif line.startswith("[I]") or "Found parameter" in line:
149
+ result["info"].append(line)
155
150
  param = _extract_discovered_param(line)
156
- if param and param not in result['parameters']:
157
- result['parameters'].append(param)
151
+ if param and param not in result["parameters"]:
152
+ result["parameters"].append(param)
158
153
 
159
- elif line.startswith('[W]') or 'WAF' in line:
160
- result['warnings'].append(line)
154
+ elif line.startswith("[W]") or "WAF" in line:
155
+ result["warnings"].append(line)
161
156
 
162
157
 
163
158
  def _detect_xss_type(text: str) -> str:
164
159
  """Detect the type of XSS from the message."""
165
160
  text_lower = text.lower()
166
- if 'dom' in text_lower:
167
- return 'dom'
168
- elif 'stored' in text_lower:
169
- return 'stored'
161
+ if "dom" in text_lower:
162
+ return "dom"
163
+ elif "stored" in text_lower:
164
+ return "stored"
170
165
  else:
171
- return 'reflected'
166
+ return "reflected"
172
167
 
173
168
 
174
169
  def _extract_parameter(text: str) -> str:
175
170
  """Extract the vulnerable parameter name from text."""
176
171
  # Look for common patterns like ?param=, &param=
177
- match = re.search(r'[?&]([a-zA-Z0-9_-]+)=', text)
172
+ match = re.search(r"[?&]([a-zA-Z0-9_-]+)=", text)
178
173
  if match:
179
174
  return match.group(1)
180
- return ''
175
+ return ""
181
176
 
182
177
 
183
178
  def _extract_payload(text: str) -> str:
184
179
  """Extract the XSS payload from text."""
185
180
  # Look for script tags or event handlers
186
181
  patterns = [
187
- r'(<script[^>]*>.*?</script>)',
188
- r'(<img[^>]*onerror[^>]*>)',
189
- r'(<svg[^>]*onload[^>]*>)',
182
+ r"(<script[^>]*>.*?</script>)",
183
+ r"(<img[^>]*onerror[^>]*>)",
184
+ r"(<svg[^>]*onload[^>]*>)",
190
185
  r'(javascript:[^\s"\']+)',
191
- r'(%3C[^%]*%3E)', # URL encoded
186
+ r"(%3C[^%]*%3E)", # URL encoded
192
187
  ]
193
188
  for pattern in patterns:
194
189
  match = re.search(pattern, text, re.IGNORECASE)
195
190
  if match:
196
191
  return match.group(1)
197
- return ''
192
+ return ""
198
193
 
199
194
 
200
195
  def _extract_discovered_param(text: str) -> str:
201
196
  """Extract discovered parameter name from info message."""
202
197
  # Patterns like "Found parameter: q" or "parameter q"
203
198
  patterns = [
204
- r'parameter[:\s]+([a-zA-Z0-9_-]+)',
205
- r'param[:\s]+([a-zA-Z0-9_-]+)',
199
+ r"parameter[:\s]+([a-zA-Z0-9_-]+)",
200
+ r"param[:\s]+([a-zA-Z0-9_-]+)",
206
201
  ]
207
202
  for pattern in patterns:
208
203
  match = re.search(pattern, text, re.IGNORECASE)
209
204
  if match:
210
205
  return match.group(1)
211
- return ''
206
+ return ""
212
207
 
213
208
 
214
209
  def get_vulnerable_parameters(parsed: Dict[str, Any]) -> List[str]:
215
210
  """Get list of parameters that have XSS vulnerabilities."""
216
211
  params = set()
217
- for vuln in parsed.get('vulnerabilities', []):
218
- param = vuln.get('parameter')
212
+ for vuln in parsed.get("vulnerabilities", []):
213
+ param = vuln.get("parameter")
219
214
  if param:
220
215
  params.add(param)
221
216
  return list(params)
@@ -224,8 +219,8 @@ def get_vulnerable_parameters(parsed: Dict[str, Any]) -> List[str]:
224
219
  def get_pocs(parsed: Dict[str, Any]) -> List[str]:
225
220
  """Get list of proof-of-concept URLs."""
226
221
  pocs = []
227
- for vuln in parsed.get('vulnerabilities', []):
228
- poc = vuln.get('poc')
222
+ for vuln in parsed.get("vulnerabilities", []):
223
+ poc = vuln.get("poc")
229
224
  if poc:
230
225
  pocs.append(poc)
231
226
  return pocs
@@ -233,4 +228,4 @@ def get_pocs(parsed: Dict[str, Any]) -> List[str]:
233
228
 
234
229
  def has_critical_findings(parsed: Dict[str, Any]) -> bool:
235
230
  """Check if there are any XSS vulnerabilities (always critical)."""
236
- return len(parsed.get('vulnerabilities', [])) > 0
231
+ return len(parsed.get("vulnerabilities", [])) > 0
@@ -36,16 +36,16 @@ def parse_dnsrecon_output(output: str, target: str = "") -> Dict[str, Any]:
36
36
  }
37
37
  """
38
38
  result = {
39
- 'target_domain': target,
40
- 'hosts': [],
41
- 'nameservers': [],
42
- 'mail_servers': [],
43
- 'txt_records': [],
44
- 'subdomains': [],
45
- 'count': 0
39
+ "target_domain": target,
40
+ "hosts": [],
41
+ "nameservers": [],
42
+ "mail_servers": [],
43
+ "txt_records": [],
44
+ "subdomains": [],
45
+ "count": 0,
46
46
  }
47
47
 
48
- lines = output.split('\n')
48
+ lines = output.split("\n")
49
49
  seen_hosts = set()
50
50
  seen_subdomains = set()
51
51
 
@@ -53,7 +53,7 @@ def parse_dnsrecon_output(output: str, target: str = "") -> Dict[str, Any]:
53
53
  line_stripped = line.strip()
54
54
 
55
55
  # Skip empty lines and headers
56
- if not line_stripped or line_stripped.startswith('[-]'):
56
+ if not line_stripped or line_stripped.startswith("[-]"):
57
57
  continue
58
58
 
59
59
  # Parse DNS records from dnsrecon output
@@ -66,77 +66,79 @@ def parse_dnsrecon_output(output: str, target: str = "") -> Dict[str, Any]:
66
66
  hostname = None
67
67
  ip = None
68
68
 
69
- if line_stripped.startswith('[*]') or line_stripped.startswith('[+]'):
69
+ if line_stripped.startswith("[*]") or line_stripped.startswith("[+]"):
70
70
  # Format: [*] or [+] <type> <hostname> <ip>
71
71
  # [*] = informational, [+] = found/success
72
72
  parts = line_stripped.split()
73
73
  if len(parts) >= 4:
74
74
  record_type = parts[1]
75
75
  hostname = parts[2].lower()
76
- ip = parts[3] if len(parts) > 3 else ''
77
- elif ' INFO ' in line_stripped:
76
+ ip = parts[3] if len(parts) > 3 else ""
77
+ elif " INFO " in line_stripped:
78
78
  # New format: TIMESTAMP INFO <type> <hostname> <ip>
79
79
  # Split on INFO and parse the rest
80
- info_idx = line_stripped.find(' INFO ')
80
+ info_idx = line_stripped.find(" INFO ")
81
81
  if info_idx != -1:
82
- record_part = line_stripped[info_idx + 6:].strip()
82
+ record_part = line_stripped[info_idx + 6 :].strip()
83
83
  parts = record_part.split()
84
84
  if len(parts) >= 3:
85
85
  record_type = parts[0]
86
86
  hostname = parts[1].lower()
87
- ip = parts[2] if len(parts) > 2 else ''
87
+ ip = parts[2] if len(parts) > 2 else ""
88
88
 
89
89
  if record_type and hostname:
90
90
  # Validate IP (both IPv4 and basic IPv6)
91
- is_ipv4 = re.match(r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$', ip) if ip else False
91
+ is_ipv4 = (
92
+ re.match(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$", ip) if ip else False
93
+ )
92
94
 
93
- if record_type == 'A' and is_ipv4:
95
+ if record_type == "A" and is_ipv4:
94
96
  if hostname not in seen_hosts:
95
97
  seen_hosts.add(hostname)
96
- result['hosts'].append({
97
- 'hostname': hostname,
98
- 'ip': ip,
99
- 'type': 'A'
100
- })
98
+ result["hosts"].append(
99
+ {"hostname": hostname, "ip": ip, "type": "A"}
100
+ )
101
101
  if hostname != target and hostname not in seen_subdomains:
102
102
  seen_subdomains.add(hostname)
103
- result['subdomains'].append(hostname)
103
+ result["subdomains"].append(hostname)
104
104
 
105
- elif record_type == 'NS':
106
- if hostname not in result['nameservers']:
107
- result['nameservers'].append(hostname)
105
+ elif record_type == "NS":
106
+ if hostname not in result["nameservers"]:
107
+ result["nameservers"].append(hostname)
108
108
 
109
- elif record_type == 'MX':
110
- if hostname not in result['mail_servers']:
111
- result['mail_servers'].append(hostname)
109
+ elif record_type == "MX":
110
+ if hostname not in result["mail_servers"]:
111
+ result["mail_servers"].append(hostname)
112
112
 
113
- elif record_type == 'SOA':
113
+ elif record_type == "SOA":
114
114
  # SOA records can also be nameservers
115
- if hostname not in result['nameservers']:
116
- result['nameservers'].append(hostname)
115
+ if hostname not in result["nameservers"]:
116
+ result["nameservers"].append(hostname)
117
117
 
118
118
  # Parse subdomain brute force results: [*] Subdomain: api.example.com IP: 1.2.3.4
119
- subdomain_match = re.search(r'Subdomain:\s+(\S+)\s+IP:\s+(\d+\.\d+\.\d+\.\d+)', line_stripped)
119
+ subdomain_match = re.search(
120
+ r"Subdomain:\s+(\S+)\s+IP:\s+(\d+\.\d+\.\d+\.\d+)", line_stripped
121
+ )
120
122
  if subdomain_match:
121
123
  hostname = subdomain_match.group(1).lower()
122
124
  ip = subdomain_match.group(2)
123
125
  if hostname not in seen_hosts:
124
126
  seen_hosts.add(hostname)
125
- result['hosts'].append({
126
- 'hostname': hostname,
127
- 'ip': ip,
128
- 'type': 'Subdomain'
129
- })
127
+ result["hosts"].append(
128
+ {"hostname": hostname, "ip": ip, "type": "Subdomain"}
129
+ )
130
130
  if hostname not in seen_subdomains:
131
131
  seen_subdomains.add(hostname)
132
- result['subdomains'].append(hostname)
132
+ result["subdomains"].append(hostname)
133
133
 
134
- result['count'] = len(result['hosts'])
134
+ result["count"] = len(result["hosts"])
135
135
 
136
136
  return result
137
137
 
138
138
 
139
- def map_to_hosts(parsed_data: Dict[str, Any], engagement_id: int) -> List[Dict[str, Any]]:
139
+ def map_to_hosts(
140
+ parsed_data: Dict[str, Any], engagement_id: int
141
+ ) -> List[Dict[str, Any]]:
140
142
  """
141
143
  Convert parsed DNSRecon data into host records for database storage.
142
144
 
@@ -151,26 +153,28 @@ def map_to_hosts(parsed_data: Dict[str, Any], engagement_id: int) -> List[Dict[s
151
153
  """
152
154
  hosts = []
153
155
 
154
- for host_data in parsed_data.get('hosts', []):
155
- hostname = host_data.get('hostname', '')
156
- ip = host_data.get('ip', '')
157
- record_type = host_data.get('type', 'Unknown')
156
+ for host_data in parsed_data.get("hosts", []):
157
+ hostname = host_data.get("hostname", "")
158
+ ip = host_data.get("ip", "")
159
+ record_type = host_data.get("type", "Unknown")
158
160
 
159
161
  host = {
160
- 'ip_address': ip,
161
- 'hostname': hostname,
162
- 'os_name': 'Unknown',
163
- 'status': 'up',
164
- 'notes': f"Discovered by dnsrecon ({record_type} record) for domain: {parsed_data.get('target_domain', '')}",
165
- 'tags': ['dns', 'dnsrecon', record_type.lower()],
166
- 'source': 'dnsrecon'
162
+ "ip_address": ip,
163
+ "hostname": hostname,
164
+ "os_name": "Unknown",
165
+ "status": "up",
166
+ "notes": f"Discovered by dnsrecon ({record_type} record) for domain: {parsed_data.get('target_domain', '')}",
167
+ "tags": ["dns", "dnsrecon", record_type.lower()],
168
+ "source": "dnsrecon",
167
169
  }
168
170
  hosts.append(host)
169
171
 
170
172
  return hosts
171
173
 
172
174
 
173
- def map_to_osint(parsed_data: Dict[str, Any], engagement_id: int, job_id: int = None) -> List[Dict[str, Any]]:
175
+ def map_to_osint(
176
+ parsed_data: Dict[str, Any], engagement_id: int, job_id: int = None
177
+ ) -> List[Dict[str, Any]]:
174
178
  """
175
179
  Convert parsed DNSRecon data into OSINT records for database storage.
176
180
 
@@ -185,54 +189,62 @@ def map_to_osint(parsed_data: Dict[str, Any], engagement_id: int, job_id: int =
185
189
  List of OSINT dicts ready for storage
186
190
  """
187
191
  osint_records = []
188
- target = parsed_data.get('target_domain', 'unknown')
192
+ target = parsed_data.get("target_domain", "unknown")
189
193
 
190
194
  # Add nameservers
191
- for ns in parsed_data.get('nameservers', []):
192
- osint_records.append({
193
- 'data_type': 'nameserver',
194
- 'value': ns,
195
- 'source': 'dnsrecon',
196
- 'engagement_id': engagement_id,
197
- 'job_id': job_id,
198
- 'notes': f'Nameserver for {target}'
199
- })
195
+ for ns in parsed_data.get("nameservers", []):
196
+ osint_records.append(
197
+ {
198
+ "data_type": "nameserver",
199
+ "value": ns,
200
+ "source": "dnsrecon",
201
+ "engagement_id": engagement_id,
202
+ "job_id": job_id,
203
+ "notes": f"Nameserver for {target}",
204
+ }
205
+ )
200
206
 
201
207
  # Add mail servers
202
- for mx in parsed_data.get('mail_servers', []):
203
- osint_records.append({
204
- 'data_type': 'mail_server',
205
- 'value': mx,
206
- 'source': 'dnsrecon',
207
- 'engagement_id': engagement_id,
208
- 'job_id': job_id,
209
- 'notes': f'Mail server for {target}'
210
- })
208
+ for mx in parsed_data.get("mail_servers", []):
209
+ osint_records.append(
210
+ {
211
+ "data_type": "mail_server",
212
+ "value": mx,
213
+ "source": "dnsrecon",
214
+ "engagement_id": engagement_id,
215
+ "job_id": job_id,
216
+ "notes": f"Mail server for {target}",
217
+ }
218
+ )
211
219
 
212
220
  # Add TXT records (often contain SPF, DKIM, DMARC, verification codes)
213
- for txt in parsed_data.get('txt_records', []):
214
- osint_records.append({
215
- 'data_type': 'txt_record',
216
- 'value': txt[:500], # Limit length
217
- 'source': 'dnsrecon',
218
- 'engagement_id': engagement_id,
219
- 'job_id': job_id,
220
- 'notes': f'TXT record for {target}'
221
- })
221
+ for txt in parsed_data.get("txt_records", []):
222
+ osint_records.append(
223
+ {
224
+ "data_type": "txt_record",
225
+ "value": txt[:500], # Limit length
226
+ "source": "dnsrecon",
227
+ "engagement_id": engagement_id,
228
+ "job_id": job_id,
229
+ "notes": f"TXT record for {target}",
230
+ }
231
+ )
222
232
 
223
233
  # Add subdomains as hosts
224
- for subdomain in parsed_data.get('subdomains', []):
225
- osint_records.append({
226
- 'data_type': 'host',
227
- 'value': subdomain,
228
- 'source': 'dnsrecon',
229
- 'engagement_id': engagement_id,
230
- 'job_id': job_id,
231
- 'notes': f'Subdomain of {target}'
232
- })
234
+ for subdomain in parsed_data.get("subdomains", []):
235
+ osint_records.append(
236
+ {
237
+ "data_type": "host",
238
+ "value": subdomain,
239
+ "source": "dnsrecon",
240
+ "engagement_id": engagement_id,
241
+ "job_id": job_id,
242
+ "notes": f"Subdomain of {target}",
243
+ }
244
+ )
233
245
 
234
246
  return osint_records
235
247
 
236
248
 
237
249
  # Export the main functions
238
- __all__ = ['parse_dnsrecon_output', 'map_to_hosts', 'map_to_osint']
250
+ __all__ = ["parse_dnsrecon_output", "map_to_hosts", "map_to_osint"]