secator 0.6.0__tar.gz → 0.7.0__tar.gz

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.

Potentially problematic release.


This version of secator might be problematic. Click here for more details.

Files changed (212) hide show
  1. {secator-0.6.0 → secator-0.7.0}/CHANGELOG.md +47 -0
  2. {secator-0.6.0 → secator-0.7.0}/Dockerfile +2 -1
  3. {secator-0.6.0 → secator-0.7.0}/PKG-INFO +11 -5
  4. secator-0.7.0/pyproject.toml +97 -0
  5. secator-0.7.0/secator/celery.py +344 -0
  6. secator-0.7.0/secator/celery_utils.py +268 -0
  7. {secator-0.6.0 → secator-0.7.0}/secator/cli.py +327 -106
  8. {secator-0.6.0 → secator-0.7.0}/secator/config.py +27 -11
  9. {secator-0.6.0 → secator-0.7.0}/secator/configs/workflows/host_recon.yaml +5 -3
  10. {secator-0.6.0 → secator-0.7.0}/secator/configs/workflows/port_scan.yaml +7 -3
  11. secator-0.7.0/secator/configs/workflows/url_bypass.yaml +10 -0
  12. {secator-0.6.0 → secator-0.7.0}/secator/configs/workflows/url_vuln.yaml +1 -1
  13. {secator-0.6.0 → secator-0.7.0}/secator/decorators.py +169 -92
  14. {secator-0.6.0 → secator-0.7.0}/secator/definitions.py +10 -3
  15. {secator-0.6.0 → secator-0.7.0}/secator/exporters/__init__.py +7 -5
  16. secator-0.7.0/secator/exporters/console.py +10 -0
  17. secator-0.7.0/secator/exporters/csv.py +37 -0
  18. {secator-0.6.0 → secator-0.7.0}/secator/exporters/gdrive.py +16 -11
  19. {secator-0.6.0 → secator-0.7.0}/secator/exporters/json.py +3 -1
  20. secator-0.7.0/secator/exporters/table.py +35 -0
  21. secator-0.7.0/secator/exporters/txt.py +28 -0
  22. secator-0.7.0/secator/hooks/gcs.py +53 -0
  23. {secator-0.6.0 → secator-0.7.0}/secator/hooks/mongodb.py +53 -27
  24. secator-0.7.0/secator/output_types/__init__.py +42 -0
  25. {secator-0.6.0 → secator-0.7.0}/secator/output_types/_base.py +11 -1
  26. secator-0.7.0/secator/output_types/error.py +36 -0
  27. {secator-0.6.0 → secator-0.7.0}/secator/output_types/exploit.py +1 -1
  28. secator-0.7.0/secator/output_types/info.py +24 -0
  29. {secator-0.6.0 → secator-0.7.0}/secator/output_types/ip.py +7 -0
  30. {secator-0.6.0 → secator-0.7.0}/secator/output_types/port.py +8 -1
  31. {secator-0.6.0 → secator-0.7.0}/secator/output_types/progress.py +5 -0
  32. {secator-0.6.0 → secator-0.7.0}/secator/output_types/record.py +3 -1
  33. secator-0.7.0/secator/output_types/stat.py +33 -0
  34. {secator-0.6.0 → secator-0.7.0}/secator/output_types/tag.py +6 -4
  35. {secator-0.6.0 → secator-0.7.0}/secator/output_types/url.py +6 -3
  36. {secator-0.6.0 → secator-0.7.0}/secator/output_types/vulnerability.py +3 -2
  37. secator-0.7.0/secator/output_types/warning.py +24 -0
  38. secator-0.7.0/secator/report.py +127 -0
  39. {secator-0.6.0 → secator-0.7.0}/secator/rich.py +44 -39
  40. secator-0.7.0/secator/runners/_base.py +897 -0
  41. secator-0.7.0/secator/runners/_helpers.py +86 -0
  42. secator-0.7.0/secator/runners/celery.py +18 -0
  43. {secator-0.6.0 → secator-0.7.0}/secator/runners/command.py +364 -211
  44. {secator-0.6.0 → secator-0.7.0}/secator/runners/scan.py +8 -24
  45. secator-0.7.0/secator/runners/task.py +74 -0
  46. {secator-0.6.0 → secator-0.7.0}/secator/runners/workflow.py +41 -40
  47. secator-0.7.0/secator/scans/__init__.py +28 -0
  48. {secator-0.6.0 → secator-0.7.0}/secator/serializers/dataclass.py +6 -0
  49. secator-0.7.0/secator/serializers/json.py +20 -0
  50. secator-0.7.0/secator/serializers/regex.py +25 -0
  51. {secator-0.6.0 → secator-0.7.0}/secator/tasks/_categories.py +5 -2
  52. secator-0.7.0/secator/tasks/bbot.py +293 -0
  53. secator-0.7.0/secator/tasks/bup.py +98 -0
  54. {secator-0.6.0 → secator-0.7.0}/secator/tasks/cariddi.py +38 -49
  55. {secator-0.6.0 → secator-0.7.0}/secator/tasks/dalfox.py +3 -0
  56. {secator-0.6.0 → secator-0.7.0}/secator/tasks/dirsearch.py +12 -23
  57. secator-0.7.0/secator/tasks/dnsx.py +76 -0
  58. {secator-0.6.0 → secator-0.7.0}/secator/tasks/dnsxbrute.py +2 -0
  59. {secator-0.6.0 → secator-0.7.0}/secator/tasks/feroxbuster.py +8 -17
  60. {secator-0.6.0 → secator-0.7.0}/secator/tasks/ffuf.py +3 -2
  61. {secator-0.6.0 → secator-0.7.0}/secator/tasks/fping.py +3 -3
  62. {secator-0.6.0 → secator-0.7.0}/secator/tasks/gau.py +5 -0
  63. {secator-0.6.0 → secator-0.7.0}/secator/tasks/gf.py +2 -2
  64. {secator-0.6.0 → secator-0.7.0}/secator/tasks/gospider.py +4 -0
  65. {secator-0.6.0 → secator-0.7.0}/secator/tasks/grype.py +9 -9
  66. secator-0.7.0/secator/tasks/h8mail.py +70 -0
  67. {secator-0.6.0 → secator-0.7.0}/secator/tasks/httpx.py +58 -21
  68. {secator-0.6.0 → secator-0.7.0}/secator/tasks/katana.py +18 -22
  69. {secator-0.6.0 → secator-0.7.0}/secator/tasks/maigret.py +26 -24
  70. {secator-0.6.0 → secator-0.7.0}/secator/tasks/mapcidr.py +2 -3
  71. {secator-0.6.0 → secator-0.7.0}/secator/tasks/msfconsole.py +4 -16
  72. {secator-0.6.0 → secator-0.7.0}/secator/tasks/naabu.py +3 -1
  73. {secator-0.6.0 → secator-0.7.0}/secator/tasks/nmap.py +50 -35
  74. {secator-0.6.0 → secator-0.7.0}/secator/tasks/nuclei.py +9 -2
  75. {secator-0.6.0 → secator-0.7.0}/secator/tasks/searchsploit.py +17 -9
  76. {secator-0.6.0 → secator-0.7.0}/secator/tasks/subfinder.py +5 -1
  77. {secator-0.6.0 → secator-0.7.0}/secator/tasks/wpscan.py +79 -93
  78. {secator-0.6.0 → secator-0.7.0}/secator/template.py +61 -45
  79. secator-0.7.0/secator/thread.py +24 -0
  80. secator-0.7.0/secator/utils.py +691 -0
  81. {secator-0.6.0 → secator-0.7.0}/secator/utils_test.py +48 -23
  82. secator-0.7.0/secator/workflows/__init__.py +28 -0
  83. {secator-0.6.0 → secator-0.7.0}/tests/fixtures/ls.py +1 -1
  84. {secator-0.6.0 → secator-0.7.0}/tests/integration/inputs.py +5 -4
  85. {secator-0.6.0 → secator-0.7.0}/tests/integration/outputs.py +38 -21
  86. {secator-0.6.0 → secator-0.7.0}/tests/integration/setup.sh +1 -0
  87. secator-0.7.0/tests/integration/test_addons.py +23 -0
  88. secator-0.7.0/tests/integration/test_celery.py +195 -0
  89. {secator-0.6.0 → secator-0.7.0}/tests/integration/test_scans.py +5 -26
  90. {secator-0.6.0 → secator-0.7.0}/tests/integration/test_tasks.py +11 -40
  91. {secator-0.6.0 → secator-0.7.0}/tests/integration/test_worker.py +20 -10
  92. {secator-0.6.0 → secator-0.7.0}/tests/integration/test_workflows.py +24 -29
  93. {secator-0.6.0 → secator-0.7.0}/tests/integration/wordlist.txt +2 -1
  94. secator-0.7.0/tests/performance/loadtester.py +77 -0
  95. secator-0.7.0/tests/performance/test_worker.py +31 -0
  96. secator-0.7.0/tests/unit/test_celery.py +117 -0
  97. secator-0.7.0/tests/unit/test_config.py +156 -0
  98. {secator-0.6.0 → secator-0.7.0}/tests/unit/test_offline.py +18 -10
  99. secator-0.7.0/tests/unit/test_runners.py +435 -0
  100. {secator-0.6.0 → secator-0.7.0}/tests/unit/test_tasks.py +68 -113
  101. secator-0.7.0/tests/unit/test_template.py +126 -0
  102. secator-0.7.0/tests/unit/test_utils.py +40 -0
  103. secator-0.6.0/pyproject.toml +0 -89
  104. secator-0.6.0/secator/celery.py +0 -369
  105. secator-0.6.0/secator/exporters/csv.py +0 -29
  106. secator-0.6.0/secator/exporters/table.py +0 -7
  107. secator-0.6.0/secator/exporters/txt.py +0 -24
  108. secator-0.6.0/secator/output_types/__init__.py +0 -24
  109. secator-0.6.0/secator/report.py +0 -95
  110. secator-0.6.0/secator/runners/_base.py +0 -910
  111. secator-0.6.0/secator/runners/_helpers.py +0 -172
  112. secator-0.6.0/secator/runners/task.py +0 -108
  113. secator-0.6.0/secator/serializers/json.py +0 -15
  114. secator-0.6.0/secator/serializers/regex.py +0 -17
  115. secator-0.6.0/secator/tasks/dnsx.py +0 -57
  116. secator-0.6.0/secator/tasks/h8mail.py +0 -80
  117. secator-0.6.0/secator/utils.py +0 -441
  118. secator-0.6.0/tests/performance/loadtester.py +0 -55
  119. secator-0.6.0/tests/unit/test_celery.py +0 -39
  120. secator-0.6.0/tests/unit/test_config.py +0 -71
  121. secator-0.6.0/tests/unit/test_template.py +0 -53
  122. secator-0.6.0/tests/unit/test_workflows.py +0 -75
  123. {secator-0.6.0 → secator-0.7.0}/.flake8 +0 -0
  124. {secator-0.6.0 → secator-0.7.0}/.gitignore +0 -0
  125. {secator-0.6.0 → secator-0.7.0}/CONTRIBUTING.md +0 -0
  126. {secator-0.6.0 → secator-0.7.0}/LICENSE +0 -0
  127. {secator-0.6.0 → secator-0.7.0}/README.md +0 -0
  128. {secator-0.6.0 → secator-0.7.0}/SECURITY.md +0 -0
  129. {secator-0.6.0 → secator-0.7.0}/cloudbuild.yaml +0 -0
  130. {secator-0.6.0 → secator-0.7.0}/helm/.helmignore +0 -0
  131. {secator-0.6.0 → secator-0.7.0}/helm/Chart.yaml +0 -0
  132. {secator-0.6.0 → secator-0.7.0}/helm/templates/redis-service.yaml +0 -0
  133. {secator-0.6.0 → secator-0.7.0}/helm/templates/redis.yaml +0 -0
  134. {secator-0.6.0 → secator-0.7.0}/helm/templates/secator-manager.yaml +0 -0
  135. {secator-0.6.0 → secator-0.7.0}/helm/templates/secator-worker.yaml +0 -0
  136. {secator-0.6.0 → secator-0.7.0}/helm/values.yaml +0 -0
  137. {secator-0.6.0 → secator-0.7.0}/images/aliases.cast +0 -0
  138. {secator-0.6.0 → secator-0.7.0}/images/aliases.gif +0 -0
  139. {secator-0.6.0 → secator-0.7.0}/images/demo.gif +0 -0
  140. {secator-0.6.0 → secator-0.7.0}/images/demo.tap +0 -0
  141. {secator-0.6.0 → secator-0.7.0}/images/fmt.cast +0 -0
  142. {secator-0.6.0 → secator-0.7.0}/images/fmt.gif +0 -0
  143. {secator-0.6.0 → secator-0.7.0}/images/help.png +0 -0
  144. {secator-0.6.0 → secator-0.7.0}/images/input.cast +0 -0
  145. {secator-0.6.0 → secator-0.7.0}/images/input.gif +0 -0
  146. {secator-0.6.0 → secator-0.7.0}/images/pipe.cast +0 -0
  147. {secator-0.6.0 → secator-0.7.0}/images/pipe.gif +0 -0
  148. {secator-0.6.0 → secator-0.7.0}/images/short_demo.cast +0 -0
  149. {secator-0.6.0 → secator-0.7.0}/images/short_demo.gif +0 -0
  150. {secator-0.6.0 → secator-0.7.0}/scripts/download_cves.sh +0 -0
  151. {secator-0.6.0 → secator-0.7.0}/scripts/install.sh +0 -0
  152. {secator-0.6.0 → secator-0.7.0}/scripts/install_asciinema.sh +0 -0
  153. {secator-0.6.0 → secator-0.7.0}/scripts/install_go.sh +0 -0
  154. {secator-0.6.0 → secator-0.7.0}/scripts/install_ruby.sh +0 -0
  155. {secator-0.6.0 → secator-0.7.0}/scripts/msf/exploit_cve.rc +0 -0
  156. {secator-0.6.0 → secator-0.7.0}/scripts/msf/ftp_anonymous.rc +0 -0
  157. {secator-0.6.0 → secator-0.7.0}/scripts/msf/ftp_version.rc +0 -0
  158. {secator-0.6.0 → secator-0.7.0}/scripts/msf/ftp_vsftpd_234_backdoor.rc +0 -0
  159. {secator-0.6.0 → secator-0.7.0}/scripts/msf/redis.rc +0 -0
  160. {secator-0.6.0 → secator-0.7.0}/scripts/msfinstall.sh +0 -0
  161. {secator-0.6.0 → secator-0.7.0}/scripts/stories/STORY.md +0 -0
  162. {secator-0.6.0 → secator-0.7.0}/scripts/stories/aliases.sh +0 -0
  163. {secator-0.6.0 → secator-0.7.0}/scripts/stories/demo.sh +0 -0
  164. {secator-0.6.0 → secator-0.7.0}/scripts/stories/fmt.sh +0 -0
  165. {secator-0.6.0 → secator-0.7.0}/scripts/stories/input.sh +0 -0
  166. {secator-0.6.0 → secator-0.7.0}/scripts/stories/pipe.sh +0 -0
  167. {secator-0.6.0 → secator-0.7.0}/scripts/stories/short_demo.sh +0 -0
  168. {secator-0.6.0 → secator-0.7.0}/secator/.gitignore +0 -0
  169. {secator-0.6.0 → secator-0.7.0}/secator/__init__.py +0 -0
  170. {secator-0.6.0 → secator-0.7.0}/secator/configs/__init__.py +0 -0
  171. {secator-0.6.0 → secator-0.7.0}/secator/configs/profiles/__init__.py +0 -0
  172. {secator-0.6.0 → secator-0.7.0}/secator/configs/profiles/aggressive.yaml +0 -0
  173. {secator-0.6.0 → secator-0.7.0}/secator/configs/profiles/default.yaml +0 -0
  174. {secator-0.6.0 → secator-0.7.0}/secator/configs/profiles/stealth.yaml +0 -0
  175. {secator-0.6.0 → secator-0.7.0}/secator/configs/scans/__init__.py +0 -0
  176. {secator-0.6.0 → secator-0.7.0}/secator/configs/scans/domain.yaml +0 -0
  177. {secator-0.6.0 → secator-0.7.0}/secator/configs/scans/host.yaml +0 -0
  178. {secator-0.6.0 → secator-0.7.0}/secator/configs/scans/network.yaml +0 -0
  179. {secator-0.6.0 → secator-0.7.0}/secator/configs/scans/subdomain.yaml +0 -0
  180. {secator-0.6.0 → secator-0.7.0}/secator/configs/scans/url.yaml +0 -0
  181. {secator-0.6.0 → secator-0.7.0}/secator/configs/workflows/__init__.py +0 -0
  182. {secator-0.6.0 → secator-0.7.0}/secator/configs/workflows/cidr_recon.yaml +0 -0
  183. {secator-0.6.0 → secator-0.7.0}/secator/configs/workflows/code_scan.yaml +0 -0
  184. {secator-0.6.0 → secator-0.7.0}/secator/configs/workflows/subdomain_recon.yaml +0 -0
  185. {secator-0.6.0 → secator-0.7.0}/secator/configs/workflows/url_crawl.yaml +0 -0
  186. {secator-0.6.0 → secator-0.7.0}/secator/configs/workflows/url_dirsearch.yaml +0 -0
  187. {secator-0.6.0 → secator-0.7.0}/secator/configs/workflows/url_fuzz.yaml +0 -0
  188. {secator-0.6.0 → secator-0.7.0}/secator/configs/workflows/url_nuclei.yaml +0 -0
  189. {secator-0.6.0 → secator-0.7.0}/secator/configs/workflows/user_hunt.yaml +0 -0
  190. {secator-0.6.0 → secator-0.7.0}/secator/configs/workflows/wordpress.yaml +0 -0
  191. {secator-0.6.0 → secator-0.7.0}/secator/exporters/_base.py +0 -0
  192. {secator-0.6.0 → secator-0.7.0}/secator/hooks/__init__.py +0 -0
  193. {secator-0.6.0 → secator-0.7.0}/secator/installer.py +0 -0
  194. {secator-0.6.0 → secator-0.7.0}/secator/output_types/subdomain.py +0 -0
  195. {secator-0.6.0 → secator-0.7.0}/secator/output_types/target.py +0 -0
  196. {secator-0.6.0 → secator-0.7.0}/secator/output_types/user_account.py +0 -0
  197. {secator-0.6.0 → secator-0.7.0}/secator/runners/__init__.py +0 -0
  198. {secator-0.6.0 → secator-0.7.0}/secator/serializers/__init__.py +0 -0
  199. {secator-0.6.0 → secator-0.7.0}/secator/tasks/__init__.py +0 -0
  200. {secator-0.6.0 → secator-0.7.0}/tests/__init__.py +0 -0
  201. {secator-0.6.0 → secator-0.7.0}/tests/fixtures/h8mail_breach.txt +0 -0
  202. {secator-0.6.0 → secator-0.7.0}/tests/fixtures/msfconsole_input.rc +0 -0
  203. {secator-0.6.0 → secator-0.7.0}/tests/fixtures/nmap_output.xml +0 -0
  204. {secator-0.6.0 → secator-0.7.0}/tests/integration/__init__.py +0 -0
  205. {secator-0.6.0 → secator-0.7.0}/tests/integration/teardown.sh +0 -0
  206. {secator-0.6.0 → secator-0.7.0}/tests/integration/wordlist_dns.txt +0 -0
  207. {secator-0.6.0 → secator-0.7.0}/tests/integration/wordpress_toolbox/Dockerfile +0 -0
  208. {secator-0.6.0 → secator-0.7.0}/tests/integration/wordpress_toolbox/Makefile +0 -0
  209. {secator-0.6.0 → secator-0.7.0}/tests/performance/__init__.py +0 -0
  210. {secator-0.6.0 → secator-0.7.0}/tests/unit/__init__.py +0 -0
  211. {secator-0.6.0 → secator-0.7.0}/tests/unit/test_scans.py +0 -0
  212. {secator-0.6.0 → secator-0.7.0}/tests/unit/test_serializers.py +0 -0
@@ -1,5 +1,52 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.7.0](https://github.com/freelabz/secator/compare/v0.6.0...v0.7.0) (2024-11-13)
4
+
5
+
6
+ ### Features
7
+
8
+ * **`bup`:** add proxy option and progress indicator ([#444](https://github.com/freelabz/secator/issues/444)) ([d5c63c8](https://github.com/freelabz/secator/commit/d5c63c81c6465a142ce70e4800effc02d526a243))
9
+ * **`dnsx`:** add IP output type on dnsx A record ([#426](https://github.com/freelabz/secator/issues/426)) ([629439e](https://github.com/freelabz/secator/commit/629439e459a6eefd5cbe68e9fc3a317371ba7987))
10
+ * **`naabu`/`nmap`:** help for defaults and change workflow opts ([#438](https://github.com/freelabz/secator/issues/438)) ([4dd0055](https://github.com/freelabz/secator/commit/4dd00556648e691a093887d294325b00409ac04a))
11
+ * **`nmap`:** add udp scan (`-sU`) and change default scan opts ([#418](https://github.com/freelabz/secator/issues/418)) ([36c6ff3](https://github.com/freelabz/secator/commit/36c6ff3766f88ac311c1bfea86a1b5e8686dd94e))
12
+ * add url_bypass workflow based on bup ([e96b1bc](https://github.com/freelabz/secator/commit/e96b1bc9906cd2f9aa3eb5b3770594811f242abd))
13
+ * chunk dalfox input by 1 ([#443](https://github.com/freelabz/secator/issues/443)) ([26c38d7](https://github.com/freelabz/secator/commit/26c38d79e89be3d35f464e89c6973b7beadb6ac4))
14
+ * **cli:** misc bug fixes and features ([#445](https://github.com/freelabz/secator/issues/445)) ([fccfdb8](https://github.com/freelabz/secator/commit/fccfdb8ca38dcd3a2c559429a7d58d46ecac49a6))
15
+ * **hooks:** explicit output type yield in static hooks ([#439](https://github.com/freelabz/secator/issues/439)) ([2d1f8e6](https://github.com/freelabz/secator/commit/2d1f8e6b7b77210028efe2c2c56866efbd6b0152))
16
+ * **katana:** add form_fill option ([#419](https://github.com/freelabz/secator/issues/419)) ([bebddb1](https://github.com/freelabz/secator/commit/bebddb1e2fae460403adda2d84b9ae515ca977aa))
17
+ * **refactor:** improve performance, add on_interval hook, rework CLI opts ([#473](https://github.com/freelabz/secator/issues/473)) ([4a22a70](https://github.com/freelabz/secator/commit/4a22a7082fe1edf50644034cfc54b11653b47aa4))
18
+ * **runner:** add GCS driver and secator threads ([#476](https://github.com/freelabz/secator/issues/476)) ([cae475a](https://github.com/freelabz/secator/commit/cae475a2fe15742ccd80d40c28ad41aa1ffc5348))
19
+ * **runner:** add skip_if_no_inputs to workflows ([#482](https://github.com/freelabz/secator/issues/482)) ([5546b82](https://github.com/freelabz/secator/commit/5546b82756d6aad0d227072d5a3b1149c44306e8))
20
+ * **runner:** on serialized hooks ([#424](https://github.com/freelabz/secator/issues/424)) ([fde6cd7](https://github.com/freelabz/secator/commit/fde6cd7f6cba015b08b370bfd14b0aca3f4a4018))
21
+ * **runner:** rework Celery core and mix fixes ([#450](https://github.com/freelabz/secator/issues/450)) ([b72f152](https://github.com/freelabz/secator/commit/b72f15286bb29ae60568309907d4dad41d4fbacb))
22
+ * sudo prompt check test ([#432](https://github.com/freelabz/secator/issues/432)) ([f45b123](https://github.com/freelabz/secator/commit/f45b1230fd6313342ebdda5a359c1285f2d80aa8))
23
+ * sudo prompts in non-tty mode ([#431](https://github.com/freelabz/secator/issues/431)) ([0e26b55](https://github.com/freelabz/secator/commit/0e26b55c168bfd69c212bc7667ef1b97e89e6bd5))
24
+ * **tasks:** bbot integration ([#375](https://github.com/freelabz/secator/issues/375)) ([2f0dea4](https://github.com/freelabz/secator/commit/2f0dea4f4cac3370129d0adf0000c8d0efa54361))
25
+ * **tasks:** bup integration ([#398](https://github.com/freelabz/secator/issues/398)) ([ed636aa](https://github.com/freelabz/secator/commit/ed636aad7d90baa7b3b73baebc8f5be002dd796a))
26
+
27
+
28
+ ### Bug Fixes
29
+
30
+ * **cli:** proper opts override for workflows ([#436](https://github.com/freelabz/secator/issues/436)) ([1d1eaa3](https://github.com/freelabz/secator/commit/1d1eaa3283b3d5e9650b452e3865476e6a60a086))
31
+ * **dalfox:** restore input_chunk_size to default ([8f0a3b4](https://github.com/freelabz/secator/commit/8f0a3b4976e20afc2fb708483c7f8885b2b9f3d9))
32
+ * dnsx parsing output loading error ([#422](https://github.com/freelabz/secator/issues/422)) ([b9e98da](https://github.com/freelabz/secator/commit/b9e98da2b5378957076e1d8f0afd3948d5bcb5f6))
33
+ * empty CVE should pass ([#478](https://github.com/freelabz/secator/issues/478)) ([0644d68](https://github.com/freelabz/secator/commit/0644d68ccb92a4c38e8210e39f14f0850d84348d))
34
+ * gcs bug with empty paths ([549ac4c](https://github.com/freelabz/secator/commit/549ac4c8e7391a829cf1a6c5a43ad291bec1b34a))
35
+ * gcs bug with empty paths ([2d57e1a](https://github.com/freelabz/secator/commit/2d57e1ad4669587cf0abb0a59b0918cf72107d72))
36
+ * get_opt_value default value and reorg hooks ([#429](https://github.com/freelabz/secator/issues/429)) ([a44a36d](https://github.com/freelabz/secator/commit/a44a36d37f888787927ec6dfc891e86dab071aa4))
37
+ * mix bugfixes for stable release ([b743925](https://github.com/freelabz/secator/commit/b7439258c9cdadc7bd14a0a0b49e2db2d0f5b537))
38
+ * nmap defaults ([396f68a](https://github.com/freelabz/secator/commit/396f68a325a5a8f1a9379d314979dbf85a9c95c7))
39
+ * **nmap:** undefined service name ([#437](https://github.com/freelabz/secator/issues/437)) ([596f1af](https://github.com/freelabz/secator/commit/596f1aff53e9add73e1587497aee82465d212300))
40
+ * runner opts processing ([#477](https://github.com/freelabz/secator/issues/477)) ([d788e9d](https://github.com/freelabz/secator/commit/d788e9d3e508a849119d418bcc5ce371c6c53c6c))
41
+ * runner toDict() errors ([#475](https://github.com/freelabz/secator/issues/475)) ([b43c866](https://github.com/freelabz/secator/commit/b43c8669808651368536fa121be2ce79de7556aa))
42
+ * **runner:** bug with no inputs ([#483](https://github.com/freelabz/secator/issues/483)) ([4db7b46](https://github.com/freelabz/secator/commit/4db7b460a949e6b74b5837f0f1e3b5ca51b39094))
43
+ * **url_vuln:** repair bad condition ([214c8ab](https://github.com/freelabz/secator/commit/214c8abf7cad4916c8301ff056d894cc0bc26b28))
44
+
45
+
46
+ ### Documentation
47
+
48
+ * add package json ([#415](https://github.com/freelabz/secator/issues/415)) ([f9a7c2f](https://github.com/freelabz/secator/commit/f9a7c2fc5df11506cce0d81babf1f7790b80465a))
49
+
3
50
  ## [0.6.0](https://github.com/freelabz/secator/compare/v0.5.2...v0.6.0) (2024-07-25)
4
51
 
5
52
 
@@ -37,7 +37,8 @@ COPY . /code/
37
37
  RUN pipx install .
38
38
  RUN secator install tools
39
39
  RUN secator install addons worker
40
- RUN secator install addons google
40
+ RUN secator install addons gdrive
41
+ RUN secator install addons gcs
41
42
  RUN secator install addons mongodb
42
43
  RUN secator install addons redis
43
44
  RUN secator install addons dev
@@ -1,11 +1,10 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: secator
3
- Version: 0.6.0
3
+ Version: 0.7.0
4
4
  Summary: The pentester's swiss knife.
5
5
  Project-URL: Homepage, https://github.com/freelabz/secator
6
6
  Project-URL: Issues, https://github.com/freelabz/secator/issues
7
7
  Author-email: FreeLabz <sales@freelabz.com>
8
- License-File: LICENSE
9
8
  Keywords: automation,cybersecurity,pentest,recon,vulnerability
10
9
  Classifier: Development Status :: 3 - Alpha
11
10
  Classifier: Intended Audience :: Developers
@@ -25,16 +24,20 @@ Requires-Dist: cpe<2
25
24
  Requires-Dist: dotmap<2
26
25
  Requires-Dist: free-proxy<2
27
26
  Requires-Dist: furl<3
27
+ Requires-Dist: greenlet<4
28
28
  Requires-Dist: humanize<5
29
29
  Requires-Dist: ifaddr<1
30
30
  Requires-Dist: jinja2<4
31
31
  Requires-Dist: packaging<25
32
+ Requires-Dist: psutil<7
32
33
  Requires-Dist: pydantic<3
33
34
  Requires-Dist: python-dotenv<2
34
35
  Requires-Dist: pyyaml<7
35
36
  Requires-Dist: requests<3
37
+ Requires-Dist: retry<1
36
38
  Requires-Dist: rich-click<1.7
37
39
  Requires-Dist: rich<14
40
+ Requires-Dist: tldextract<6
38
41
  Requires-Dist: typing-extensions<5
39
42
  Requires-Dist: validators<1
40
43
  Requires-Dist: xmltodict<1
@@ -44,10 +47,13 @@ Provides-Extra: dev
44
47
  Requires-Dist: asciinema-automation<1; extra == 'dev'
45
48
  Requires-Dist: coverage<8; extra == 'dev'
46
49
  Requires-Dist: flake8<8; extra == 'dev'
50
+ Requires-Dist: pytest<9; extra == 'dev'
47
51
  Requires-Dist: watchdog<3; extra == 'dev'
48
- Provides-Extra: google
49
- Requires-Dist: google-api-python-client<3; extra == 'google'
50
- Requires-Dist: gspread<7; extra == 'google'
52
+ Provides-Extra: gcs
53
+ Requires-Dist: google-cloud-storage<3; extra == 'gcs'
54
+ Provides-Extra: gdrive
55
+ Requires-Dist: google-api-python-client<3; extra == 'gdrive'
56
+ Requires-Dist: gspread<7; extra == 'gdrive'
51
57
  Provides-Extra: mongodb
52
58
  Requires-Dist: pymongo<5; extra == 'mongodb'
53
59
  Provides-Extra: redis
@@ -0,0 +1,97 @@
1
+ [build-system]
2
+ requires = ['hatchling']
3
+ build-backend = 'hatchling.build'
4
+
5
+ [project]
6
+ name = 'secator'
7
+ version = "0.7.0"
8
+ authors = [{ name = 'FreeLabz', email = 'sales@freelabz.com' }]
9
+ readme = 'README.md'
10
+ description = "The pentester's swiss knife."
11
+ requires-python = '>=3.8'
12
+ keywords = [
13
+ 'cybersecurity',
14
+ 'recon',
15
+ 'vulnerability',
16
+ 'pentest',
17
+ 'automation'
18
+ ]
19
+ classifiers = [
20
+ 'Development Status :: 3 - Alpha',
21
+ 'Intended Audience :: Developers',
22
+ 'Intended Audience :: Information Technology',
23
+ 'License :: Free for non-commercial use',
24
+ 'Operating System :: Unix',
25
+ 'Programming Language :: Python',
26
+ 'Programming Language :: Python :: 3',
27
+ 'Programming Language :: Python :: 3.8',
28
+ 'Programming Language :: Python :: 3.9',
29
+ 'Programming Language :: Python :: 3.10',
30
+ 'Programming Language :: Python :: 3.11',
31
+ ]
32
+ dependencies = [
33
+ 'beautifulsoup4 <= 5',
34
+ 'celery < 6',
35
+ 'cpe < 2',
36
+ 'dotmap < 2',
37
+ 'free-proxy < 2',
38
+ 'furl < 3',
39
+ 'greenlet < 4',
40
+ 'humanize < 5',
41
+ 'ifaddr < 1',
42
+ 'jinja2 < 4',
43
+ 'packaging < 25',
44
+ 'python-dotenv < 2',
45
+ 'pyyaml < 7',
46
+ 'pydantic < 3',
47
+ 'requests < 3',
48
+ 'rich < 14',
49
+ 'rich-click < 1.7',
50
+ 'psutil < 7',
51
+ 'retry < 1',
52
+ 'tldextract < 6',
53
+ 'typing_extensions < 5',
54
+ 'validators < 1',
55
+ 'xmltodict < 1'
56
+ ]
57
+
58
+ [project.optional-dependencies]
59
+ dev = [
60
+ 'coverage < 8',
61
+ 'flake8 < 8',
62
+ 'pytest < 9',
63
+ 'watchdog < 3',
64
+ 'asciinema-automation < 1',
65
+ ]
66
+ build = [
67
+ 'hatch < 2',
68
+ ]
69
+ trace = [
70
+ 'memray < 2',
71
+ 'pyinstrument < 5',
72
+ ]
73
+ worker = [
74
+ 'gevent < 25',
75
+ 'eventlet < 1',
76
+ 'flower < 3',
77
+ ]
78
+ redis = [
79
+ 'redis < 6',
80
+ ]
81
+ mongodb = [
82
+ 'pymongo < 5',
83
+ ]
84
+ gdrive = [
85
+ 'google-api-python-client < 3',
86
+ 'gspread < 7'
87
+ ]
88
+ gcs = [
89
+ 'google-cloud-storage < 3'
90
+ ]
91
+
92
+ [project.scripts]
93
+ secator = 'secator.cli:cli'
94
+
95
+ [project.urls]
96
+ Homepage = 'https://github.com/freelabz/secator'
97
+ Issues = 'https://github.com/freelabz/secator/issues'
@@ -0,0 +1,344 @@
1
+ import gc
2
+ import logging
3
+ import sys
4
+ import uuid
5
+
6
+ from time import time
7
+
8
+ from celery import Celery, chain, chord, signals
9
+ from celery.app import trace
10
+
11
+ from rich.logging import RichHandler
12
+ from retry import retry
13
+
14
+ from secator.config import CONFIG
15
+ from secator.output_types import Info, Warning, Error
16
+ from secator.rich import console
17
+ from secator.runners import Scan, Task, Workflow
18
+ from secator.runners._helpers import run_extractors
19
+ from secator.utils import (debug, deduplicate, flatten, should_update)
20
+
21
+ IN_CELERY_WORKER_PROCESS = sys.argv and ('secator.celery.app' in sys.argv or 'worker' in sys.argv)
22
+
23
+ #---------#
24
+ # Logging #
25
+ #---------#
26
+
27
+ rich_handler = RichHandler(rich_tracebacks=True)
28
+ rich_handler.setLevel(logging.INFO)
29
+ logging.basicConfig(
30
+ level='NOTSET',
31
+ format="%(threadName)s:%(message)s",
32
+ datefmt="[%X]",
33
+ handlers=[rich_handler],
34
+ force=True)
35
+ logging.getLogger('kombu').setLevel(logging.ERROR)
36
+ logging.getLogger('celery').setLevel(logging.INFO if CONFIG.debug.level > 6 else logging.WARNING)
37
+ logger = logging.getLogger(__name__)
38
+ trace.LOG_SUCCESS = "Task %(name)s[%(id)s] succeeded in %(runtime)ss"
39
+
40
+
41
+ #------------#
42
+ # Celery app #
43
+ #------------#
44
+
45
+ app = Celery(__name__)
46
+ app.conf.update({
47
+ # Content types
48
+ 'accept_content': ['application/x-python-serialize', 'application/json'],
49
+
50
+ # Broker config
51
+ 'broker_url': CONFIG.celery.broker_url,
52
+ 'broker_transport_options': {
53
+ 'data_folder_in': CONFIG.dirs.celery_data,
54
+ 'data_folder_out': CONFIG.dirs.celery_data,
55
+ 'control_folder': CONFIG.dirs.celery_data,
56
+ 'visibility_timeout': CONFIG.celery.broker_visibility_timeout,
57
+ },
58
+ 'broker_connection_retry_on_startup': True,
59
+ 'broker_pool_limit': CONFIG.celery.broker_pool_limit,
60
+ 'broker_connection_timeout': CONFIG.celery.broker_connection_timeout,
61
+
62
+ # Result backend config
63
+ 'result_backend': CONFIG.celery.result_backend,
64
+ 'result_expires': CONFIG.celery.result_expires,
65
+ 'result_extended': True,
66
+ 'result_backend_thread_safe': True,
67
+ 'result_serializer': 'pickle',
68
+ # 'result_backend_transport_options': {'master_name': 'mymaster'}, # for Redis HA backend
69
+
70
+ # Task config
71
+ 'task_acks_late': False,
72
+ 'task_compression': 'gzip',
73
+ 'task_create_missing_queues': True,
74
+ 'task_eager_propagates': False,
75
+ 'task_reject_on_worker_lost': False,
76
+ 'task_routes': {
77
+ 'secator.celery.run_workflow': {'queue': 'celery'},
78
+ 'secator.celery.run_scan': {'queue': 'celery'},
79
+ 'secator.celery.run_task': {'queue': 'celery'},
80
+ 'secator.hooks.mongodb.tag_duplicates': {'queue': 'mongodb'}
81
+ },
82
+ 'task_store_eager_result': True,
83
+ # 'task_send_sent_event': True, # TODO: consider enabling this for Flower monitoring
84
+ 'task_serializer': 'pickle',
85
+
86
+ # Worker config
87
+ # 'worker_direct': True, # TODO: consider enabling this to allow routing to specific workers
88
+ 'worker_max_tasks_per_child': 10,
89
+ # 'worker_max_memory_per_child': 100000 # TODO: consider enabling this
90
+ 'worker_pool_restarts': True,
91
+ 'worker_prefetch_multiplier': 1,
92
+ # 'worker_send_task_events': True, # TODO: consider enabling this for Flower monitoring
93
+ })
94
+ app.autodiscover_tasks(['secator.hooks.mongodb'], related_name=None)
95
+
96
+
97
+ def maybe_override_logging():
98
+ def decorator(func):
99
+ if CONFIG.celery.override_default_logging:
100
+ return signals.setup_logging.connect(func)
101
+ else:
102
+ return func
103
+ return decorator
104
+
105
+
106
+ @maybe_override_logging()
107
+ def void(*args, **kwargs):
108
+ """Override celery's logging setup to prevent it from altering our settings.
109
+ github.com/celery/celery/issues/1867
110
+ """
111
+ pass
112
+
113
+
114
+ @retry(Exception, tries=3, delay=2)
115
+ def update_state(celery_task, task, force=False):
116
+ """Update task state to add metadata information."""
117
+ if task.sync:
118
+ return
119
+ if not force and not should_update(CONFIG.runners.backend_update_frequency, task.last_updated_celery):
120
+ return
121
+ task.last_updated_celery = time()
122
+ debug(
123
+ '',
124
+ sub='celery.state',
125
+ id=celery_task.request.id,
126
+ obj={task.unique_name: task.status, 'count': task.self_findings_count},
127
+ obj_after=False,
128
+ verbose=True
129
+ )
130
+ return celery_task.update_state(
131
+ state='RUNNING',
132
+ meta=task.celery_state
133
+ )
134
+
135
+
136
+ def revoke_task(task_id, task_name=None):
137
+ message = f'Revoked task {task_id}'
138
+ if task_name:
139
+ message += f' ({task_name})'
140
+ app.control.revoke(task_id, terminate=True)
141
+ console.print(Info(message=message))
142
+
143
+
144
+ #--------------#
145
+ # Celery tasks #
146
+ #--------------#
147
+
148
+
149
+ def chunker(seq, size):
150
+ return (seq[pos:pos + size] for pos in range(0, len(seq), size))
151
+
152
+
153
+ def break_task(task, task_opts, targets, results=[], chunk_size=1):
154
+ """Break a task into multiple of the same type."""
155
+ chunks = targets
156
+ if chunk_size > 1:
157
+ chunks = list(chunker(targets, chunk_size))
158
+ debug(
159
+ '',
160
+ obj={task.unique_name: 'CHUNKED', 'chunk_size': chunk_size, 'chunks': len(chunks), 'target_count': len(targets)},
161
+ obj_after=False,
162
+ sub='celery.state',
163
+ verbose=True
164
+ )
165
+
166
+ # Clone opts
167
+ opts = task_opts.copy()
168
+
169
+ # Build signatures
170
+ sigs = []
171
+ task.ids_map = {}
172
+ for ix, chunk in enumerate(chunks):
173
+ if not isinstance(chunk, list):
174
+ chunk = [chunk]
175
+ if len(chunks) > 0: # add chunk to task opts for tracking chunks exec
176
+ opts['chunk'] = ix + 1
177
+ opts['chunk_count'] = len(chunks)
178
+ task_id = str(uuid.uuid4())
179
+ opts['has_parent'] = True
180
+ opts['enable_duplicate_check'] = False
181
+ sig = type(task).s(chunk, **opts).set(queue=type(task).profile, task_id=task_id)
182
+ full_name = f'{task.name}_{ix + 1}'
183
+ task.add_subtask(task_id, task.name, f'{task.name}_{ix + 1}')
184
+ info = Info(message=f'Celery chunked task created: {task_id}', _source=full_name, _uuid=str(uuid.uuid4()))
185
+ task.add_result(info)
186
+ sigs.append(sig)
187
+
188
+ # Build Celery workflow
189
+ workflow = chain(
190
+ forward_results.s(results).set(queue='io'),
191
+ chord(
192
+ tuple(sigs),
193
+ forward_results.s().set(queue='io'),
194
+ )
195
+ )
196
+ if task.sync:
197
+ task.print_item = False
198
+ task.results = workflow.apply().get()
199
+ else:
200
+ result = workflow.apply_async()
201
+ task.celery_result = result
202
+
203
+
204
+ @app.task(bind=True)
205
+ def run_task(self, args=[], kwargs={}):
206
+ kwargs['context']['celery_id'] = self.request.id
207
+ task = Task(*args, **kwargs)
208
+ task.run()
209
+
210
+
211
+ @app.task(bind=True)
212
+ def run_workflow(self, args=[], kwargs={}):
213
+ kwargs['context']['celery_id'] = self.request.id
214
+ workflow = Workflow(*args, **kwargs)
215
+ workflow.run()
216
+
217
+
218
+ @app.task(bind=True)
219
+ def run_scan(self, args=[], kwargs={}):
220
+ if 'context' not in kwargs:
221
+ kwargs['context'] = {}
222
+ kwargs['context']['celery_id'] = self.request.id
223
+ scan = Scan(*args, **kwargs)
224
+ scan.run()
225
+
226
+
227
+ @app.task(bind=True)
228
+ def run_command(self, results, name, targets, opts={}):
229
+ chunk = opts.get('chunk')
230
+ sync = opts.get('sync', True)
231
+
232
+ # Set Celery request id in context
233
+ context = opts.get('context', {})
234
+ context['celery_id'] = self.request.id
235
+ opts['context'] = context
236
+ opts['print_remote_info'] = False
237
+ opts['results'] = results
238
+
239
+ # If we are in a Celery worker, print everything, always
240
+ if IN_CELERY_WORKER_PROCESS:
241
+ opts.update({
242
+ 'print_item': True,
243
+ 'print_line': True,
244
+ 'print_cmd': True
245
+ })
246
+
247
+ # Flatten + dedupe results
248
+ results = flatten(results)
249
+ results = deduplicate(results, attr='_uuid')
250
+
251
+ # Get expanded targets
252
+ if not chunk and results:
253
+ targets, opts = run_extractors(results, opts, targets)
254
+ debug('after extractors', obj={'targets': targets, 'opts': opts}, sub='celery.state')
255
+
256
+ try:
257
+ # Get task class
258
+ task_cls = Task.get_task_class(name)
259
+
260
+ # Check if chunkable
261
+ many_targets = len(targets) > 1
262
+ targets_over_chunk_size = task_cls.input_chunk_size and len(targets) > task_cls.input_chunk_size
263
+ has_file_flag = task_cls.file_flag is not None
264
+ chunk_it = (sync and many_targets and not has_file_flag) or (not sync and many_targets and targets_over_chunk_size)
265
+ task_opts = opts.copy()
266
+ task_opts.update({
267
+ 'print_remote_info': False,
268
+ 'has_children': chunk_it,
269
+ })
270
+ if chunk_it:
271
+ task_opts['print_cmd'] = False
272
+ task = task_cls(targets, **task_opts)
273
+ debug(
274
+ '',
275
+ obj={
276
+ f'{task.unique_name}': 'CHUNK STATUS',
277
+ 'chunk_it': chunk_it,
278
+ 'sync': task.sync,
279
+ 'many_targets': many_targets,
280
+ 'targets_over_chunk_size': targets_over_chunk_size,
281
+ },
282
+ obj_after=False,
283
+ id=self.request.id,
284
+ sub='celery.state',
285
+ verbose=True
286
+ )
287
+
288
+ # Chunk task if needed
289
+ if chunk_it:
290
+ chunk_size = task_cls.input_chunk_size if has_file_flag else 1
291
+ break_task(
292
+ task,
293
+ opts,
294
+ targets,
295
+ results=results,
296
+ chunk_size=chunk_size)
297
+
298
+ # Update state before starting
299
+ update_state(self, task)
300
+
301
+ # Update state for each item found
302
+ for _ in task:
303
+ update_state(self, task)
304
+
305
+ except BaseException as e:
306
+ error = Error.from_exception(e)
307
+ error._source = task.unique_name
308
+ error._uuid = str(uuid.uuid4())
309
+ task.add_result(error, print=True)
310
+ task.stop_celery_tasks()
311
+
312
+ finally:
313
+ update_state(self, task, force=True)
314
+ gc.collect()
315
+ debug('', obj={task.unique_name: task.status, 'results': task.results}, sub='celery.results', verbose=True)
316
+ return task.results
317
+
318
+
319
+ @app.task
320
+ def forward_results(results):
321
+ if isinstance(results, list):
322
+ for ix, item in enumerate(results):
323
+ if isinstance(item, dict) and 'results' in item:
324
+ results[ix] = item['results']
325
+ elif 'results' in results:
326
+ results = results['results']
327
+ results = flatten(results)
328
+ results = deduplicate(results, attr='_uuid')
329
+ return results
330
+
331
+ #--------------#
332
+ # Celery utils #
333
+ #--------------#
334
+
335
+
336
+ def is_celery_worker_alive():
337
+ """Check if a Celery worker is available."""
338
+ result = app.control.broadcast('ping', reply=True, limit=1, timeout=1)
339
+ result = bool(result)
340
+ if result:
341
+ console.print(Info(message='Celery worker is alive !'))
342
+ else:
343
+ console.print(Warning(message='No Celery worker alive.'))
344
+ return result