bbot 2.0.1.4650rc0__tar.gz → 2.1.0.5028rc0__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.
Files changed (410) hide show
  1. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/PKG-INFO +9 -4
  2. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/README.md +6 -2
  3. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/__init__.py +1 -1
  4. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/core.py +0 -2
  5. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/engine.py +4 -3
  6. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/event/base.py +81 -22
  7. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/command.py +1 -1
  8. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/depsinstaller/installer.py +59 -20
  9. bbot-2.1.0.5028rc0/bbot/core/helpers/depsinstaller/sudo_askpass.py +41 -0
  10. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/dns/brute.py +14 -13
  11. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/dns/dns.py +15 -13
  12. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/dns/engine.py +156 -127
  13. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/dns/mock.py +26 -7
  14. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/misc.py +25 -6
  15. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/names_generator.py +17 -3
  16. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/regexes.py +5 -0
  17. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/web/engine.py +17 -11
  18. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/web/web.py +21 -111
  19. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/modules.py +15 -5
  20. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/defaults.yml +5 -2
  21. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/errors.py +0 -8
  22. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/anubisdb.py +1 -1
  23. bbot-2.1.0.5028rc0/bbot/modules/apkpure.py +53 -0
  24. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/baddns.py +48 -23
  25. bbot-2.1.0.5028rc0/bbot/modules/baddns_direct.py +93 -0
  26. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/baddns_zone.py +3 -8
  27. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/badsecrets.py +3 -2
  28. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/base.py +183 -39
  29. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/bevigil.py +5 -5
  30. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/binaryedge.py +6 -3
  31. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/builtwith.py +4 -8
  32. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/c99.py +6 -5
  33. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/certspotter.py +1 -1
  34. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/chaos.py +5 -5
  35. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/code_repository.py +1 -0
  36. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/columbus.py +1 -1
  37. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/crt.py +1 -1
  38. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/deadly/ffuf.py +1 -1
  39. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/deadly/nuclei.py +1 -1
  40. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/deadly/vhost.py +2 -1
  41. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/dehashed.py +1 -1
  42. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/dnsdumpster.py +2 -2
  43. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/docker_pull.py +6 -4
  44. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/dockerhub.py +1 -1
  45. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/dotnetnuke.py +18 -17
  46. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/emailformat.py +1 -1
  47. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/filedownload.py +8 -6
  48. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/fullhunt.py +6 -3
  49. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/generic_ssrf.py +2 -2
  50. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/github_codesearch.py +1 -1
  51. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/github_org.py +4 -4
  52. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/github_workflows.py +3 -3
  53. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/gitlab.py +2 -5
  54. bbot-2.1.0.5028rc0/bbot/modules/google_playstore.py +93 -0
  55. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/hackertarget.py +1 -1
  56. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/httpx.py +0 -3
  57. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/hunterio.py +3 -9
  58. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/iis_shortnames.py +13 -24
  59. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/internal/cloudcheck.py +2 -2
  60. bbot-2.1.0.5028rc0/bbot/modules/internal/dnsresolve.py +318 -0
  61. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/internal/excavate.py +78 -38
  62. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/internal/speculate.py +27 -7
  63. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/internetdb.py +4 -2
  64. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/ip2location.py +3 -5
  65. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/ipstack.py +3 -8
  66. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/leakix.py +6 -6
  67. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/myssl.py +1 -1
  68. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/otx.py +1 -1
  69. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/csv.py +0 -1
  70. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/http.py +20 -14
  71. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/neo4j.py +7 -2
  72. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/slack.py +0 -1
  73. bbot-2.1.0.5028rc0/bbot/modules/output/teams.py +124 -0
  74. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/paramminer_headers.py +1 -1
  75. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/passivetotal.py +2 -2
  76. bbot-2.1.0.5028rc0/bbot/modules/postman.py +88 -0
  77. bbot-2.1.0.5028rc0/bbot/modules/postman_download.py +220 -0
  78. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/rapiddns.py +1 -1
  79. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/securitytrails.py +3 -8
  80. bbot-2.1.0.5028rc0/bbot/modules/securitytxt.py +128 -0
  81. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/shodan_dns.py +7 -9
  82. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/skymem.py +2 -2
  83. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/social.py +1 -0
  84. bbot-2.1.0.5028rc0/bbot/modules/subdomainradar.py +160 -0
  85. bbot-2.1.0.5028rc0/bbot/modules/templates/github.py +46 -0
  86. bbot-2.1.0.5028rc0/bbot/modules/templates/postman.py +21 -0
  87. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/templates/shodan.py +13 -12
  88. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/templates/subdomain_enum.py +50 -14
  89. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/templates/webhook.py +1 -3
  90. bbot-2.1.0.5028rc0/bbot/modules/trickest.py +46 -0
  91. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/trufflehog.py +17 -2
  92. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/unstructured.py +13 -28
  93. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/virustotal.py +6 -23
  94. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/wayback.py +1 -1
  95. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/wpscan.py +9 -9
  96. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/zoomeye.py +6 -3
  97. bbot-2.1.0.5028rc0/bbot/presets/baddns-thorough.yml +12 -0
  98. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/presets/kitchen-sink.yml +1 -0
  99. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/presets/subdomain-enum.yml +7 -7
  100. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/manager.py +4 -14
  101. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/preset/args.py +14 -11
  102. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/preset/environ.py +7 -1
  103. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/preset/path.py +4 -3
  104. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/preset/preset.py +6 -2
  105. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/scanner.py +147 -42
  106. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/bbot_fixtures.py +17 -1
  107. bbot-2.1.0.5028rc0/bbot/test/owasp_mastg.apk +0 -0
  108. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_cli.py +46 -8
  109. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_dns.py +341 -56
  110. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_events.py +95 -15
  111. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_helpers.py +21 -2
  112. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_manager_deduplication.py +1 -1
  113. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_manager_scope_accuracy.py +31 -33
  114. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_modules_basic.py +17 -15
  115. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_presets.py +79 -4
  116. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_python_api.py +3 -2
  117. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_regexes.py +30 -0
  118. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_scan.py +28 -0
  119. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_scope.py +5 -4
  120. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_target.py +3 -3
  121. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_web.py +40 -5
  122. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/base.py +2 -13
  123. bbot-2.1.0.5028rc0/bbot/test/test_step_2/module_tests/test_module_apkpure.py +69 -0
  124. bbot-2.1.0.5028rc0/bbot/test/test_step_2/module_tests/test_module_baddns_direct.py +64 -0
  125. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_bevigil.py +27 -0
  126. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_binaryedge.py +2 -0
  127. bbot-2.1.0.5028rc0/bbot/test/test_step_2/module_tests/test_module_c99.py +151 -0
  128. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_code_repository.py +11 -1
  129. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_credshed.py +1 -1
  130. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dehashed.py +1 -1
  131. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_discord.py +1 -1
  132. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dnsbrute.py +1 -1
  133. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dnsbrute_mutations.py +1 -1
  134. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dnscommonsrv.py +1 -1
  135. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_excavate.py +1 -1
  136. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_git_clone.py +1 -1
  137. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_github_org.py +19 -8
  138. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_github_workflows.py +1 -1
  139. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_gitlab.py +9 -4
  140. bbot-2.1.0.5028rc0/bbot/test/test_step_2/module_tests/test_module_google_playstore.py +83 -0
  141. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_httpx.py +3 -1
  142. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_hunterio.py +67 -3
  143. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_json.py +24 -11
  144. bbot-2.1.0.5028rc0/bbot/test/test_step_2/module_tests/test_module_postman.py +113 -0
  145. bbot-2.1.0.5028rc0/bbot/test/test_step_2/module_tests/test_module_postman_download.py +439 -0
  146. bbot-2.1.0.5028rc0/bbot/test/test_step_2/module_tests/test_module_rapiddns.py +108 -0
  147. bbot-2.1.0.5028rc0/bbot/test/test_step_2/module_tests/test_module_securitytxt.py +50 -0
  148. bbot-2.1.0.5028rc0/bbot/test/test_step_2/module_tests/test_module_shodan_dns.py +40 -0
  149. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_social.py +11 -1
  150. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_sslcert.py +1 -1
  151. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_stdout.py +5 -3
  152. bbot-2.1.0.5028rc0/bbot/test/test_step_2/module_tests/test_module_subdomainradar.py +208 -0
  153. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_teams.py +8 -6
  154. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_trufflehog.py +315 -9
  155. bbot-2.1.0.5028rc0/bbot/test/test_step_2/template_tests/test_template_subdomain_enum.py +221 -0
  156. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/pyproject.toml +9 -7
  157. bbot-2.0.1.4650rc0/bbot/core/helpers/depsinstaller/sudo_askpass.py +0 -5
  158. bbot-2.0.1.4650rc0/bbot/modules/internal/dnsresolve.py +0 -355
  159. bbot-2.0.1.4650rc0/bbot/modules/output/teams.py +0 -23
  160. bbot-2.0.1.4650rc0/bbot/modules/postman.py +0 -164
  161. bbot-2.0.1.4650rc0/bbot/modules/templates/github.py +0 -38
  162. bbot-2.0.1.4650rc0/bbot/modules/trickest.py +0 -75
  163. bbot-2.0.1.4650rc0/bbot/test/test_step_2/module_tests/test_module_c99.py +0 -25
  164. bbot-2.0.1.4650rc0/bbot/test/test_step_2/module_tests/test_module_postman.py +0 -282
  165. bbot-2.0.1.4650rc0/bbot/test/test_step_2/module_tests/test_module_rapiddns.py +0 -16
  166. bbot-2.0.1.4650rc0/bbot/test/test_step_2/module_tests/test_module_shodan_dns.py +0 -21
  167. bbot-2.0.1.4650rc0/bbot/test/test_step_2/template_tests/test_template_subdomain_enum.py +0 -86
  168. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/LICENSE +0 -0
  169. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/cli.py +0 -0
  170. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/__init__.py +0 -0
  171. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/config/__init__.py +0 -0
  172. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/config/files.py +0 -0
  173. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/config/logger.py +0 -0
  174. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/event/__init__.py +0 -0
  175. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/event/helpers.py +0 -0
  176. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/flags.py +0 -0
  177. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/__init__.py +0 -0
  178. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/async_helpers.py +0 -0
  179. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/bloom.py +0 -0
  180. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/cache.py +0 -0
  181. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/depsinstaller/__init__.py +0 -0
  182. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/diff.py +0 -0
  183. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/dns/__init__.py +0 -0
  184. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/dns/helpers.py +0 -0
  185. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/files.py +0 -0
  186. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/helper.py +0 -0
  187. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/interactsh.py +0 -0
  188. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/ntlm.py +0 -0
  189. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/process.py +0 -0
  190. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/ratelimiter.py +0 -0
  191. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/regex.py +0 -0
  192. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/url.py +0 -0
  193. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/validators.py +0 -0
  194. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/web/__init__.py +0 -0
  195. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/web/client.py +0 -0
  196. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/web/ssl_context.py +0 -0
  197. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/wordcloud.py +0 -0
  198. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/core/shared_deps.py +0 -0
  199. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/logger.py +0 -0
  200. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/__init__.py +0 -0
  201. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/ajaxpro.py +0 -0
  202. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/azure_realm.py +0 -0
  203. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/azure_tenant.py +0 -0
  204. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/bucket_amazon.py +0 -0
  205. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/bucket_azure.py +0 -0
  206. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/bucket_digitalocean.py +0 -0
  207. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/bucket_file_enum.py +0 -0
  208. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/bucket_firebase.py +0 -0
  209. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/bucket_google.py +0 -0
  210. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/bypass403.py +0 -0
  211. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/censys.py +0 -0
  212. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/credshed.py +0 -0
  213. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/deadly/dastardly.py +0 -0
  214. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/digitorus.py +0 -0
  215. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/dnsbrute.py +0 -0
  216. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/dnsbrute_mutations.py +0 -0
  217. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/dnscaa.py +0 -0
  218. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/dnscommonsrv.py +0 -0
  219. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/ffuf_shortnames.py +0 -0
  220. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/fingerprintx.py +0 -0
  221. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/git.py +0 -0
  222. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/git_clone.py +0 -0
  223. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/gowitness.py +0 -0
  224. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/host_header.py +0 -0
  225. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/hunt.py +0 -0
  226. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/internal/__init__.py +0 -0
  227. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/internal/aggregate.py +0 -0
  228. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/internal/base.py +0 -0
  229. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/ipneighbor.py +0 -0
  230. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/newsletters.py +0 -0
  231. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/ntlm.py +0 -0
  232. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/oauth.py +0 -0
  233. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/__init__.py +0 -0
  234. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/asset_inventory.py +0 -0
  235. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/base.py +0 -0
  236. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/discord.py +0 -0
  237. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/emails.py +0 -0
  238. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/json.py +0 -0
  239. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/python.py +0 -0
  240. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/splunk.py +0 -0
  241. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/stdout.py +0 -0
  242. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/subdomains.py +0 -0
  243. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/txt.py +0 -0
  244. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/web_report.py +0 -0
  245. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/websocket.py +0 -0
  246. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/paramminer_cookies.py +0 -0
  247. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/paramminer_getparams.py +0 -0
  248. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/pgp.py +0 -0
  249. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/portscan.py +0 -0
  250. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/report/affiliates.py +0 -0
  251. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/report/asn.py +0 -0
  252. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/report/base.py +0 -0
  253. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/robots.py +0 -0
  254. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/secretsdb.py +0 -0
  255. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/sitedossier.py +0 -0
  256. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/smuggler.py +0 -0
  257. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/sslcert.py +0 -0
  258. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/subdomaincenter.py +0 -0
  259. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/telerik.py +0 -0
  260. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/templates/bucket.py +0 -0
  261. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/url_manipulation.py +0 -0
  262. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/urlscan.py +0 -0
  263. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/viewdns.py +0 -0
  264. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/wafw00f.py +0 -0
  265. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/modules/wappalyzer.py +0 -0
  266. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/presets/cloud-enum.yml +0 -0
  267. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/presets/code-enum.yml +0 -0
  268. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/presets/email-enum.yml +0 -0
  269. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/presets/spider.yml +0 -0
  270. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/presets/web/dirbust-heavy.yml +0 -0
  271. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/presets/web/dirbust-light.yml +0 -0
  272. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/presets/web/dotnet-audit.yml +0 -0
  273. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/presets/web/iis-shortnames.yml +0 -0
  274. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/presets/web/paramminer.yml +0 -0
  275. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/presets/web-basic.yml +0 -0
  276. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/presets/web-screenshots.yml +0 -0
  277. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/presets/web-thorough.yml +0 -0
  278. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/__init__.py +0 -0
  279. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/dispatcher.py +0 -0
  280. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/preset/__init__.py +0 -0
  281. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/preset/conditions.py +0 -0
  282. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/stats.py +0 -0
  283. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/target.py +0 -0
  284. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/scripts/docs.py +0 -0
  285. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/__init__.py +0 -0
  286. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/conftest.py +0 -0
  287. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/coverage.cfg +0 -0
  288. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/run_tests.sh +0 -0
  289. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test.conf +0 -0
  290. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_output.ndjson +0 -0
  291. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/__init__.py +0 -0
  292. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test__module__tests.py +0 -0
  293. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_bloom_filter.py +0 -0
  294. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_command.py +0 -0
  295. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_config.py +0 -0
  296. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_depsinstaller.py +0 -0
  297. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_docs.py +0 -0
  298. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_engine.py +0 -0
  299. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_files.py +0 -0
  300. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/__init__.py +0 -0
  301. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/__init__.py +0 -0
  302. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_affiliates.py +0 -0
  303. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_aggregate.py +0 -0
  304. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_ajaxpro.py +0 -0
  305. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_anubisdb.py +0 -0
  306. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_asn.py +0 -0
  307. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_asset_inventory.py +0 -0
  308. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_azure_realm.py +0 -0
  309. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_azure_tenant.py +0 -0
  310. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_baddns.py +0 -0
  311. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_baddns_zone.py +0 -0
  312. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_badsecrets.py +0 -0
  313. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_bucket_amazon.py +0 -0
  314. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_bucket_azure.py +0 -0
  315. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_bucket_digitalocean.py +0 -0
  316. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_bucket_file_enum.py +0 -0
  317. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_bucket_firebase.py +0 -0
  318. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_bucket_google.py +0 -0
  319. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_builtwith.py +0 -0
  320. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_bypass403.py +0 -0
  321. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_censys.py +0 -0
  322. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_certspotter.py +0 -0
  323. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_chaos.py +0 -0
  324. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_cloudcheck.py +0 -0
  325. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_columbus.py +0 -0
  326. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_crt.py +0 -0
  327. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_csv.py +0 -0
  328. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dastardly.py +0 -0
  329. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_digitorus.py +0 -0
  330. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dnscaa.py +0 -0
  331. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dnsdumpster.py +0 -0
  332. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dnsresolve.py +0 -0
  333. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_docker_pull.py +0 -0
  334. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dockerhub.py +0 -0
  335. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dotnetnuke.py +0 -0
  336. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_emailformat.py +0 -0
  337. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_emails.py +0 -0
  338. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_ffuf.py +0 -0
  339. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_ffuf_shortnames.py +0 -0
  340. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_filedownload.py +0 -0
  341. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_fingerprintx.py +0 -0
  342. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_fullhunt.py +0 -0
  343. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_generic_ssrf.py +0 -0
  344. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_git.py +0 -0
  345. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_github_codesearch.py +0 -0
  346. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_gowitness.py +0 -0
  347. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_hackertarget.py +0 -0
  348. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_host_header.py +0 -0
  349. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_http.py +0 -0
  350. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_hunt.py +0 -0
  351. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_iis_shortnames.py +0 -0
  352. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_internetdb.py +0 -0
  353. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_ip2location.py +0 -0
  354. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_ipneighbor.py +0 -0
  355. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_ipstack.py +0 -0
  356. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_leakix.py +0 -0
  357. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_myssl.py +0 -0
  358. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_neo4j.py +0 -0
  359. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_newsletters.py +0 -0
  360. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_ntlm.py +0 -0
  361. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_nuclei.py +0 -0
  362. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_oauth.py +0 -0
  363. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_otx.py +0 -0
  364. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_paramminer_cookies.py +0 -0
  365. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_paramminer_getparams.py +0 -0
  366. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_paramminer_headers.py +0 -0
  367. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_passivetotal.py +0 -0
  368. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_pgp.py +0 -0
  369. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_portscan.py +0 -0
  370. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_python.py +0 -0
  371. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_robots.py +0 -0
  372. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_secretsdb.py +0 -0
  373. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_securitytrails.py +0 -0
  374. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_sitedossier.py +0 -0
  375. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_skymem.py +0 -0
  376. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_slack.py +0 -0
  377. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_smuggler.py +0 -0
  378. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_speculate.py +0 -0
  379. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_splunk.py +0 -0
  380. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_subdomaincenter.py +0 -0
  381. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_subdomains.py +0 -0
  382. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_telerik.py +0 -0
  383. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_trickest.py +0 -0
  384. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_txt.py +0 -0
  385. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_unstructured.py +0 -0
  386. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_url_manipulation.py +0 -0
  387. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_urlscan.py +0 -0
  388. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_vhost.py +0 -0
  389. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_viewdns.py +0 -0
  390. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_virustotal.py +0 -0
  391. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_wafw00f.py +0 -0
  392. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_wappalyzer.py +0 -0
  393. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_wayback.py +0 -0
  394. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_web_report.py +0 -0
  395. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_websocket.py +0 -0
  396. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_wpscan.py +0 -0
  397. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_zoomeye.py +0 -0
  398. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/template_tests/__init__.py +0 -0
  399. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/testsslcert.pem +0 -0
  400. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/test/testsslkey.pem +0 -0
  401. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/wordlists/devops_mutations.txt +0 -0
  402. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/wordlists/ffuf_shortname_candidates.txt +0 -0
  403. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/wordlists/ms_on_prem_subdomains.txt +0 -0
  404. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/wordlists/nameservers.txt +0 -0
  405. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/wordlists/paramminer_headers.txt +0 -0
  406. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/wordlists/paramminer_parameters.txt +0 -0
  407. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/wordlists/raft-small-extensions-lowercase_CLEANED.txt +0 -0
  408. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/wordlists/top_open_ports_nmap.txt +0 -0
  409. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/wordlists/valid_url_schemes.txt +0 -0
  410. {bbot-2.0.1.4650rc0 → bbot-2.1.0.5028rc0}/bbot/wordlists/wordninja_dns.txt.gz +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: bbot
3
- Version: 2.0.1.4650rc0
3
+ Version: 2.1.0.5028rc0
4
4
  Summary: OSINT automation for hackers.
5
5
  Home-page: https://github.com/blacklanternsecurity/bbot
6
6
  License: GPL-3.0
@@ -14,6 +14,7 @@ Classifier: Programming Language :: Python :: 3.9
14
14
  Classifier: Programming Language :: Python :: 3.10
15
15
  Classifier: Programming Language :: Python :: 3.11
16
16
  Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
17
18
  Classifier: Topic :: Security
18
19
  Requires-Dist: ansible (>=7.3,<9.0)
19
20
  Requires-Dist: ansible-runner (>=2.3.2,<3.0.0)
@@ -26,7 +27,7 @@ Requires-Dist: httpx (>=0.27.0,<0.28.0)
26
27
  Requires-Dist: idna (>=3.4,<4.0)
27
28
  Requires-Dist: jinja2 (>=3.1.3,<4.0.0)
28
29
  Requires-Dist: lxml (>=4.9.2,<6.0.0)
29
- Requires-Dist: mmh3 (>=4.1.0,<5.0.0)
30
+ Requires-Dist: mmh3 (>=4.1,<6.0)
30
31
  Requires-Dist: omegaconf (>=2.3.0,<3.0.0)
31
32
  Requires-Dist: psutil (>=5.9.4,<6.0.0)
32
33
  Requires-Dist: pycryptodome (>=3.17,<4.0)
@@ -355,13 +356,17 @@ For more information, see [Targets](https://www.blacklanternsecurity.com/bbot/St
355
356
 
356
357
  Similar to Amass or Subfinder, BBOT supports API keys for various third-party services such as SecurityTrails, etc.
357
358
 
358
- The standard way to do this is to enter your API keys in **`~/.config/bbot/bbot.yml`**:
359
+ The standard way to do this is to enter your API keys in **`~/.config/bbot/bbot.yml`**. Note that multiple API keys are allowed:
359
360
  ```yaml
360
361
  modules:
361
362
  shodan_dns:
362
363
  api_key: 4f41243847da693a4f356c0486114bc6
363
364
  c99:
364
- api_key: 21a270d5f59c9b05813a72bb41707266
365
+ # multiple API keys
366
+ api_key:
367
+ - 21a270d5f59c9b05813a72bb41707266
368
+ - ea8f243d9885cf8ce9876a580224fd3c
369
+ - 5bc6ed268ab6488270e496d3183a1a27
365
370
  virustotal:
366
371
  api_key: dd5f0eee2e4a99b71a939bded450b246
367
372
  securitytrails:
@@ -303,13 +303,17 @@ For more information, see [Targets](https://www.blacklanternsecurity.com/bbot/St
303
303
 
304
304
  Similar to Amass or Subfinder, BBOT supports API keys for various third-party services such as SecurityTrails, etc.
305
305
 
306
- The standard way to do this is to enter your API keys in **`~/.config/bbot/bbot.yml`**:
306
+ The standard way to do this is to enter your API keys in **`~/.config/bbot/bbot.yml`**. Note that multiple API keys are allowed:
307
307
  ```yaml
308
308
  modules:
309
309
  shodan_dns:
310
310
  api_key: 4f41243847da693a4f356c0486114bc6
311
311
  c99:
312
- api_key: 21a270d5f59c9b05813a72bb41707266
312
+ # multiple API keys
313
+ api_key:
314
+ - 21a270d5f59c9b05813a72bb41707266
315
+ - ea8f243d9885cf8ce9876a580224fd3c
316
+ - 5bc6ed268ab6488270e496d3183a1a27
313
317
  virustotal:
314
318
  api_key: dd5f0eee2e4a99b71a939bded450b246
315
319
  securitytrails:
@@ -1,4 +1,4 @@
1
1
  # version placeholder (replaced by poetry-dynamic-versioning)
2
- __version__ = "v2.0.1.4650rc"
2
+ __version__ = "v2.1.0.5028rc"
3
3
 
4
4
  from .scanner import Scanner, Preset
@@ -34,8 +34,6 @@ class BBOTCore:
34
34
  self._logger = None
35
35
  self._files_config = None
36
36
 
37
- self.bbot_sudo_pass = None
38
-
39
37
  self._config = None
40
38
  self._custom_config = None
41
39
 
@@ -643,6 +643,7 @@ class EngineServer(EngineBase):
643
643
  self.log.warning(f"{self.name}: Timeout after {timeout:,} seconds in finished_tasks({tasks})")
644
644
  for task in tasks:
645
645
  task.cancel()
646
+ self._await_cancelled_task(task)
646
647
  else:
647
648
  if not in_exception_chain(e, (KeyboardInterrupt, asyncio.CancelledError)):
648
649
  self.log.error(f"{self.name}: Unhandled exception in finished_tasks({tasks}): {e}")
@@ -664,9 +665,9 @@ class EngineServer(EngineBase):
664
665
  child_task.cancel()
665
666
 
666
667
  for task in [parent_task] + list(child_tasks):
667
- await self._cancel_task(task)
668
+ await self._await_cancelled_task(task)
668
669
 
669
- async def _cancel_task(self, task):
670
+ async def _await_cancelled_task(self, task):
670
671
  try:
671
672
  await asyncio.wait_for(task, timeout=10)
672
673
  except (TimeoutError, asyncio.exceptions.TimeoutError):
@@ -683,4 +684,4 @@ class EngineServer(EngineBase):
683
684
  await self.cancel_task(client_id)
684
685
  for client_id, tasks in self.child_tasks.items():
685
686
  for task in tasks:
686
- await self._cancel_task(task)
687
+ await self._await_cancelled_task(task)
@@ -1,5 +1,6 @@
1
1
  import io
2
2
  import re
3
+ import uuid
3
4
  import json
4
5
  import base64
5
6
  import logging
@@ -24,6 +25,7 @@ from bbot.core.helpers import (
24
25
  is_domain,
25
26
  is_subdomain,
26
27
  is_ip,
28
+ is_ip_type,
27
29
  is_ptr,
28
30
  is_uri,
29
31
  url_depth,
@@ -58,9 +60,10 @@ class BaseEvent:
58
60
 
59
61
  Attributes:
60
62
  type (str): Specifies the type of the event, e.g., `IP_ADDRESS`, `DNS_NAME`.
61
- id (str): A unique identifier for the event.
63
+ id (str): An identifier for the event (event type + sha1 hash of data). NOT universally unique.
64
+ uuid (UUID): A universally unique identifier for the event.
62
65
  data (str or dict): The main data for the event, e.g., a URL or IP address.
63
- data_graph (str): Representation of `self.data` for Neo4j graph nodes.
66
+ data_graph (str): Representation of `self.data` for graph nodes (e.g. Neo4j).
64
67
  data_human (str): Representation of `self.data` for human output.
65
68
  data_id (str): Representation of `self.data` used to calculate the event's ID (and ultimately its hash, which is used for deduplication)
66
69
  data_json (str): Representation of `self.data` to be used in JSON serialization.
@@ -75,6 +78,7 @@ class BaseEvent:
75
78
  resolved_hosts (list of str): List of hosts to which the event data resolves, applicable for URLs and DNS names.
76
79
  parent (BaseEvent): The parent event that led to the discovery of this event.
77
80
  parent_id (str): The `id` attribute of the parent event.
81
+ parent_uuid (str): The `uuid` attribute of the parent event.
78
82
  tags (set of str): Descriptive tags for the event, e.g., `mx-record`, `in-scope`.
79
83
  module (BaseModule): The module that discovered the event.
80
84
  module_sequence (str): The sequence of modules that participated in the discovery.
@@ -154,7 +158,7 @@ class BaseEvent:
154
158
  Raises:
155
159
  ValidationError: If either `scan` or `parent` are not specified and `_dummy` is False.
156
160
  """
157
-
161
+ self._uuid = uuid.uuid4()
158
162
  self._id = None
159
163
  self._hash = None
160
164
  self._data = None
@@ -166,11 +170,13 @@ class BaseEvent:
166
170
  self._parent = None
167
171
  self._priority = None
168
172
  self._parent_id = None
173
+ self._parent_uuid = None
169
174
  self._host_original = None
170
175
  self._scope_distance = None
171
176
  self._module_priority = None
172
177
  self._resolved_hosts = set()
173
178
  self.dns_children = dict()
179
+ self.raw_dns_records = dict()
174
180
  self._discovery_context = ""
175
181
  self._discovery_context_regex = re.compile(r"\{(?:event|module)[^}]*\}")
176
182
  self.web_spider_distance = 0
@@ -347,6 +353,12 @@ class BaseEvent:
347
353
  return 80
348
354
  return self._port
349
355
 
356
+ @property
357
+ def netloc(self):
358
+ if self.host and is_ip_type(self.host, network=False):
359
+ return make_netloc(self.host, self.port)
360
+ return None
361
+
350
362
  @property
351
363
  def host_stem(self):
352
364
  """
@@ -379,10 +391,20 @@ class BaseEvent:
379
391
  """
380
392
  This event's full discovery context, including those of all its parents
381
393
  """
382
- parent_path = []
394
+ discovery_path = []
395
+ if self.parent is not None and self.parent is not self:
396
+ discovery_path = self.parent.discovery_path
397
+ return discovery_path + [self.discovery_context]
398
+
399
+ @property
400
+ def parent_chain(self):
401
+ """
402
+ This event's full discovery context, including those of all its parents
403
+ """
404
+ parent_chain = []
383
405
  if self.parent is not None and self.parent is not self:
384
- parent_path = self.parent.discovery_path
385
- return parent_path + [[self.id, self.discovery_context]]
406
+ parent_chain = self.parent.parent_chain
407
+ return parent_chain + [str(self.uuid)]
386
408
 
387
409
  @property
388
410
  def words(self):
@@ -425,11 +447,6 @@ class BaseEvent:
425
447
  no_host_information = not bool(self.host)
426
448
  return self._always_emit or always_emit_tags or no_host_information
427
449
 
428
- @property
429
- def quick_emit(self):
430
- no_host_information = not bool(self.host)
431
- return self._quick_emit or no_host_information
432
-
433
450
  @property
434
451
  def id(self):
435
452
  """
@@ -439,6 +456,13 @@ class BaseEvent:
439
456
  self._id = f"{self.type}:{self.data_hash.hex()}"
440
457
  return self._id
441
458
 
459
+ @property
460
+ def uuid(self):
461
+ """
462
+ A universally unique identifier for the event
463
+ """
464
+ return f"{self.type}:{self._uuid}"
465
+
442
466
  @property
443
467
  def data_hash(self):
444
468
  """
@@ -556,6 +580,13 @@ class BaseEvent:
556
580
  return parent_id
557
581
  return self._parent_id
558
582
 
583
+ @property
584
+ def parent_uuid(self):
585
+ parent_uuid = getattr(self.get_parent(), "uuid", None)
586
+ if parent_uuid is not None:
587
+ return parent_uuid
588
+ return self._parent_uuid
589
+
559
590
  @property
560
591
  def validators(self):
561
592
  """
@@ -722,12 +753,12 @@ class BaseEvent:
722
753
  Returns:
723
754
  dict: JSON-serializable dictionary representation of the event object.
724
755
  """
725
- # type, ID, scope description
726
756
  j = dict()
727
- for i in ("type", "id", "scope_description"):
757
+ # type, ID, scope description
758
+ for i in ("type", "id", "uuid", "scope_description", "netloc"):
728
759
  v = getattr(self, i, "")
729
760
  if v:
730
- j.update({i: v})
761
+ j.update({i: str(v)})
731
762
  # event data
732
763
  data_attr = getattr(self, f"data_{mode}", None)
733
764
  if data_attr is not None:
@@ -743,6 +774,8 @@ class BaseEvent:
743
774
  j["host"] = str(self.host)
744
775
  j["resolved_hosts"] = sorted(str(h) for h in self.resolved_hosts)
745
776
  j["dns_children"] = {k: list(v) for k, v in self.dns_children.items()}
777
+ if isinstance(self.port, int):
778
+ j["port"] = self.port
746
779
  # web spider distance
747
780
  web_spider_distance = getattr(self, "web_spider_distance", None)
748
781
  if web_spider_distance is not None:
@@ -758,6 +791,9 @@ class BaseEvent:
758
791
  parent_id = self.parent_id
759
792
  if parent_id:
760
793
  j["parent"] = parent_id
794
+ parent_uuid = self.parent_uuid
795
+ if parent_uuid:
796
+ j["parent_uuid"] = parent_uuid
761
797
  # tags
762
798
  if self.tags:
763
799
  j.update({"tags": list(self.tags)})
@@ -770,6 +806,7 @@ class BaseEvent:
770
806
  # discovery context
771
807
  j["discovery_context"] = self.discovery_context
772
808
  j["discovery_path"] = self.discovery_path
809
+ j["parent_chain"] = self.parent_chain
773
810
 
774
811
  # normalize non-primitive python objects
775
812
  for k, v in list(j.items()):
@@ -909,6 +946,10 @@ class SCAN(BaseEvent):
909
946
  def discovery_path(self):
910
947
  return []
911
948
 
949
+ @property
950
+ def parent_chain(self):
951
+ return []
952
+
912
953
 
913
954
  class FINISHED(BaseEvent):
914
955
  """
@@ -1053,6 +1094,17 @@ class DnsEvent(BaseEvent):
1053
1094
  if parent_module_type == "DNS":
1054
1095
  self.dns_resolve_distance += 1
1055
1096
  # self.add_tag(f"resolve-distance-{self.dns_resolve_distance}")
1097
+ # tag subdomain / domain
1098
+ if is_subdomain(self.host):
1099
+ self.add_tag("subdomain")
1100
+ elif is_domain(self.host):
1101
+ self.add_tag("domain")
1102
+ # tag private IP
1103
+ try:
1104
+ if self.host.is_private:
1105
+ self.add_tag("private-ip")
1106
+ except AttributeError:
1107
+ pass
1056
1108
 
1057
1109
 
1058
1110
  class IP_RANGE(DnsEvent):
@@ -1069,13 +1121,6 @@ class IP_RANGE(DnsEvent):
1069
1121
 
1070
1122
 
1071
1123
  class DNS_NAME(DnsEvent):
1072
- def __init__(self, *args, **kwargs):
1073
- super().__init__(*args, **kwargs)
1074
- if is_subdomain(self.data):
1075
- self.add_tag("subdomain")
1076
- elif is_domain(self.data):
1077
- self.add_tag("domain")
1078
-
1079
1124
  def sanitize_data(self, data):
1080
1125
  return validators.validate_host(data)
1081
1126
 
@@ -1498,11 +1543,18 @@ class FILESYSTEM(DictPathEvent):
1498
1543
  pass
1499
1544
 
1500
1545
 
1501
- class RAW_DNS_RECORD(DictHostEvent):
1546
+ class RAW_DNS_RECORD(DictHostEvent, DnsEvent):
1502
1547
  # don't emit raw DNS records for affiliates
1503
1548
  _always_emit_tags = ["target"]
1504
1549
 
1505
1550
 
1551
+ class MOBILE_APP(DictEvent):
1552
+ _always_emit = True
1553
+
1554
+ def _pretty_string(self):
1555
+ return self.data["url"]
1556
+
1557
+
1506
1558
  def make_event(
1507
1559
  data,
1508
1560
  event_type=None,
@@ -1671,6 +1723,9 @@ def event_from_json(j, siem_friendly=False):
1671
1723
  data = j["data"]
1672
1724
  kwargs["data"] = data
1673
1725
  event = make_event(**kwargs)
1726
+ event_uuid = j.get("uuid", None)
1727
+ if event_uuid is not None:
1728
+ event._uuid = uuid.UUID(event_uuid.split(":")[-1])
1674
1729
 
1675
1730
  resolved_hosts = j.get("resolved_hosts", [])
1676
1731
  event._resolved_hosts = set(resolved_hosts)
@@ -1680,6 +1735,10 @@ def event_from_json(j, siem_friendly=False):
1680
1735
  parent_id = j.get("parent", None)
1681
1736
  if parent_id is not None:
1682
1737
  event._parent_id = parent_id
1738
+ parent_uuid = j.get("parent_uuid", None)
1739
+ if parent_uuid is not None:
1740
+ parent_type, parent_uuid = parent_uuid.split(":", 1)
1741
+ event._parent_uuid = parent_type + ":" + str(uuid.UUID(parent_uuid))
1683
1742
  return event
1684
1743
  except KeyError as e:
1685
1744
  raise ValidationError(f"Event missing required field: {e}")
@@ -295,7 +295,7 @@ def _prepare_command_kwargs(self, command, kwargs):
295
295
  if sudo and os.geteuid() != 0:
296
296
  self.depsinstaller.ensure_root()
297
297
  env["SUDO_ASKPASS"] = str((self.tools_dir / self.depsinstaller.askpass_filename).resolve())
298
- env["BBOT_SUDO_PASS"] = self.depsinstaller._sudo_password
298
+ env["BBOT_SUDO_PASS"] = self.depsinstaller.encrypted_sudo_pw
299
299
  kwargs["env"] = env
300
300
 
301
301
  PATH = os.environ.get("PATH", "")
@@ -10,10 +10,11 @@ from pathlib import Path
10
10
  from threading import Lock
11
11
  from itertools import chain
12
12
  from contextlib import suppress
13
+ from secrets import token_bytes
13
14
  from ansible_runner.interface import run
14
15
  from subprocess import CalledProcessError
15
16
 
16
- from ..misc import can_sudo_without_password, os_platform
17
+ from ..misc import can_sudo_without_password, os_platform, rm_at_exit
17
18
 
18
19
  log = logging.getLogger("bbot.core.helpers.depsinstaller")
19
20
 
@@ -29,14 +30,13 @@ class DepsInstaller:
29
30
  http_timeout = self.web_config.get("http_timeout", 30)
30
31
  os.environ["ANSIBLE_TIMEOUT"] = str(http_timeout)
31
32
 
33
+ # cache encrypted sudo pass
32
34
  self.askpass_filename = "sudo_askpass.py"
35
+ self._sudo_password = None
36
+ self._sudo_cache_setup = False
37
+ self._setup_sudo_cache()
33
38
  self._installed_sudo_askpass = False
34
- self._sudo_password = os.environ.get("BBOT_SUDO_PASS", None)
35
- if self._sudo_password is None:
36
- if self.core.bbot_sudo_pass is not None:
37
- self._sudo_password = self.core.bbot_sudo_pass
38
- elif can_sudo_without_password():
39
- self._sudo_password = ""
39
+
40
40
  self.data_dir = self.parent_helper.cache_dir / "depsinstaller"
41
41
  self.parent_helper.mkdir(self.data_dir)
42
42
  self.setup_status_cache = self.data_dir / "setup_status.json"
@@ -314,20 +314,27 @@ class DepsInstaller:
314
314
 
315
315
  def ensure_root(self, message=""):
316
316
  self._install_sudo_askpass()
317
+ # skip if we've already done this
318
+ if self._sudo_password is not None:
319
+ return
317
320
  with self.ensure_root_lock:
318
- if os.geteuid() != 0 and self._sudo_password is None:
319
- if message:
320
- log.warning(message)
321
- while not self._sudo_password:
322
- # sleep for a split second to flush previous log messages
323
- sleep(0.1)
324
- password = getpass.getpass(prompt="[USER] Please enter sudo password: ")
325
- if self.parent_helper.verify_sudo_password(password):
326
- log.success("Authentication successful")
327
- self._sudo_password = password
328
- self.core.bbot_sudo_pass = password
329
- else:
330
- log.warning("Incorrect password")
321
+ # first check if the environment variable is set
322
+ _sudo_password = os.environ.get("BBOT_SUDO_PASS", None)
323
+ if _sudo_password is not None or os.geteuid() == 0 or can_sudo_without_password():
324
+ # if we're already root or we can sudo without a password, there's no need to prompt
325
+ return
326
+
327
+ if message:
328
+ log.warning(message)
329
+ while not self._sudo_password:
330
+ # sleep for a split second to flush previous log messages
331
+ sleep(0.1)
332
+ _sudo_password = getpass.getpass(prompt="[USER] Please enter sudo password: ")
333
+ if self.parent_helper.verify_sudo_password(_sudo_password):
334
+ log.success("Authentication successful")
335
+ self._sudo_password = _sudo_password
336
+ else:
337
+ log.warning("Incorrect password")
331
338
 
332
339
  def install_core_deps(self):
333
340
  to_install = set()
@@ -343,6 +350,38 @@ class DepsInstaller:
343
350
  self.ensure_root()
344
351
  self.apt_install(list(to_install))
345
352
 
353
+ def _setup_sudo_cache(self):
354
+ if not self._sudo_cache_setup:
355
+ self._sudo_cache_setup = True
356
+ # write temporary encryption key, to be deleted upon scan completion
357
+ self._sudo_temp_keyfile = self.parent_helper.temp_filename()
358
+ # remove it at exit
359
+ rm_at_exit(self._sudo_temp_keyfile)
360
+ # generate random 32-byte key
361
+ random_key = token_bytes(32)
362
+ # write key to file and set secure permissions
363
+ self._sudo_temp_keyfile.write_bytes(random_key)
364
+ self._sudo_temp_keyfile.chmod(0o600)
365
+ # export path to environment variable, for use in askpass script
366
+ os.environ["BBOT_SUDO_KEYFILE"] = str(self._sudo_temp_keyfile.resolve())
367
+
368
+ @property
369
+ def encrypted_sudo_pw(self):
370
+ if self._sudo_password is None:
371
+ return ""
372
+ return self._encrypt_sudo_pw(self._sudo_password)
373
+
374
+ def _encrypt_sudo_pw(self, pw):
375
+ from Crypto.Cipher import AES
376
+ from Crypto.Util.Padding import pad
377
+
378
+ key = self._sudo_temp_keyfile.read_bytes()
379
+ cipher = AES.new(key, AES.MODE_CBC)
380
+ ct_bytes = cipher.encrypt(pad(pw.encode(), AES.block_size))
381
+ iv = cipher.iv.hex()
382
+ ct = ct_bytes.hex()
383
+ return f"{iv}:{ct}"
384
+
346
385
  def _install_sudo_askpass(self):
347
386
  if not self._installed_sudo_askpass:
348
387
  self._installed_sudo_askpass = True
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env python3
2
+ import os
3
+ import sys
4
+ from pathlib import Path
5
+ from Crypto.Cipher import AES
6
+ from Crypto.Util.Padding import unpad
7
+
8
+ ENV_VAR_NAME = "BBOT_SUDO_PASS"
9
+ KEY_ENV_VAR_PATH = "BBOT_SUDO_KEYFILE"
10
+
11
+
12
+ def decrypt_password(encrypted_data, key):
13
+ iv, ciphertext = encrypted_data.split(":")
14
+ iv = bytes.fromhex(iv)
15
+ ct = bytes.fromhex(ciphertext)
16
+ cipher = AES.new(key, AES.MODE_CBC, iv)
17
+ pt = unpad(cipher.decrypt(ct), AES.block_size)
18
+ return pt.decode("utf-8")
19
+
20
+
21
+ def main():
22
+ encrypted_password = os.environ.get(ENV_VAR_NAME, "")
23
+ # remove variable from environment once we've got it
24
+ os.environ.pop(ENV_VAR_NAME, None)
25
+ encryption_keypath = Path(os.environ.get(KEY_ENV_VAR_PATH, ""))
26
+
27
+ if not encrypted_password or not encryption_keypath.is_file():
28
+ print("Error: Encrypted password or encryption key not found in environment variables.", file=sys.stderr)
29
+ sys.exit(1)
30
+
31
+ try:
32
+ key = encryption_keypath.read_bytes()
33
+ decrypted_password = decrypt_password(encrypted_password, key)
34
+ print(decrypted_password, end="")
35
+ except Exception as e:
36
+ print(f'Error decrypting password "{encrypted_password}": {str(e)}', file=sys.stderr)
37
+ sys.exit(1)
38
+
39
+
40
+ if __name__ == "__main__":
41
+ main()
@@ -15,15 +15,17 @@ class DNSBrute:
15
15
  >>> results = await self.helpers.dns.brute(self, domain, subdomains)
16
16
  """
17
17
 
18
- nameservers_url = (
18
+ _nameservers_url = (
19
19
  "https://raw.githubusercontent.com/blacklanternsecurity/public-dns-servers/master/nameservers.txt"
20
20
  )
21
21
 
22
22
  def __init__(self, parent_helper):
23
23
  self.parent_helper = parent_helper
24
24
  self.log = logging.getLogger("bbot.helper.dns.brute")
25
+ self.dns_config = self.parent_helper.config.get("dns", {})
25
26
  self.num_canaries = 100
26
- self.max_resolvers = self.parent_helper.config.get("dns", {}).get("brute_threads", 1000)
27
+ self.max_resolvers = self.dns_config.get("brute_threads", 1000)
28
+ self.nameservers_url = self.dns_config.get("brute_nameservers", self._nameservers_url)
27
29
  self.devops_mutations = list(self.parent_helper.word_cloud.devops_mutations)
28
30
  self.digit_regex = self.parent_helper.re.compile(r"\d+")
29
31
  self._resolver_file = None
@@ -39,18 +41,12 @@ class DNSBrute:
39
41
  type = "A"
40
42
  type = str(type).strip().upper()
41
43
 
42
- domain_wildcard_rdtypes = set()
43
- for _domain, rdtypes in (await self.parent_helper.dns.is_wildcard_domain(domain)).items():
44
- for rdtype, results in rdtypes.items():
45
- if results:
46
- domain_wildcard_rdtypes.add(rdtype)
47
- if any([r in domain_wildcard_rdtypes for r in (type, "CNAME")]):
48
- self.log.info(
49
- f"Aborting massdns on {domain} because it's a wildcard domain ({','.join(domain_wildcard_rdtypes)})"
44
+ wildcard_rdtypes = await self.parent_helper.dns.is_wildcard_domain(domain, (type, "CNAME"))
45
+ if wildcard_rdtypes:
46
+ self.log.hugewarning(
47
+ f"Aborting massdns on {domain} because it's a wildcard domain ({','.join(wildcard_rdtypes)})"
50
48
  )
51
49
  return []
52
- else:
53
- self.log.debug(f"{domain}: A is not in domain_wildcard_rdtypes:{domain_wildcard_rdtypes}")
54
50
 
55
51
  canaries = self.gen_random_subdomains(self.num_canaries)
56
52
  canaries_list = list(canaries)
@@ -148,10 +144,15 @@ class DNSBrute:
148
144
 
149
145
  async def resolver_file(self):
150
146
  if self._resolver_file is None:
151
- self._resolver_file = await self.parent_helper.wordlist(
147
+ self._resolver_file_original = await self.parent_helper.wordlist(
152
148
  self.nameservers_url,
153
149
  cache_hrs=24 * 7,
154
150
  )
151
+ nameservers = set(self.parent_helper.read_file(self._resolver_file_original))
152
+ nameservers.difference_update(self.parent_helper.dns.system_resolvers)
153
+ # exclude system nameservers from brute-force
154
+ # this helps prevent rate-limiting which might cause BBOT's main dns queries to fail
155
+ self._resolver_file = self.parent_helper.tempfile(nameservers, pipe=False)
155
156
  return self._resolver_file
156
157
 
157
158
  def gen_random_subdomains(self, n=50):
@@ -66,7 +66,7 @@ class DNSHelper(EngineClient):
66
66
  self.resolver.timeout = self.timeout
67
67
  self.resolver.lifetime = self.timeout
68
68
 
69
- self.runaway_limit = self.config.get("runaway_limit", 5)
69
+ self.runaway_limit = self.dns_config.get("runaway_limit", 5)
70
70
 
71
71
  # wildcard handling
72
72
  self.wildcard_disable = self.dns_config.get("wildcard_disable", False)
@@ -117,8 +117,11 @@ class DNSHelper(EngineClient):
117
117
  self._brute = DNSBrute(self.parent_helper)
118
118
  return self._brute
119
119
 
120
- @async_cachedmethod(lambda self: self._is_wildcard_cache)
121
- async def is_wildcard(self, query, ips=None, rdtype=None):
120
+ @async_cachedmethod(
121
+ lambda self: self._is_wildcard_cache,
122
+ key=lambda query, rdtypes, raw_dns_records: (query, tuple(sorted(rdtypes)), bool(raw_dns_records)),
123
+ )
124
+ async def is_wildcard(self, query, rdtypes, raw_dns_records=None):
122
125
  """
123
126
  Use this method to check whether a *host* is a wildcard entry
124
127
 
@@ -150,9 +153,6 @@ class DNSHelper(EngineClient):
150
153
  Note:
151
154
  `is_wildcard` can be True, False, or None (indicating that wildcard detection was inconclusive)
152
155
  """
153
- if [ips, rdtype].count(None) == 1:
154
- raise ValueError("Both ips and rdtype must be specified")
155
-
156
156
  query = self._wildcard_prevalidation(query)
157
157
  if not query:
158
158
  return {}
@@ -161,15 +161,17 @@ class DNSHelper(EngineClient):
161
161
  if is_domain(query):
162
162
  return {}
163
163
 
164
- return await self.run_and_return("is_wildcard", query=query, ips=ips, rdtype=rdtype)
164
+ return await self.run_and_return("is_wildcard", query=query, rdtypes=rdtypes, raw_dns_records=raw_dns_records)
165
165
 
166
- @async_cachedmethod(lambda self: self._is_wildcard_domain_cache)
167
- async def is_wildcard_domain(self, domain, log_info=False):
166
+ @async_cachedmethod(
167
+ lambda self: self._is_wildcard_domain_cache, key=lambda domain, rdtypes: (domain, tuple(sorted(rdtypes)))
168
+ )
169
+ async def is_wildcard_domain(self, domain, rdtypes):
168
170
  domain = self._wildcard_prevalidation(domain)
169
171
  if not domain:
170
172
  return {}
171
173
 
172
- return await self.run_and_return("is_wildcard_domain", domain=domain, log_info=False)
174
+ return await self.run_and_return("is_wildcard_domain", domain=domain, rdtypes=rdtypes)
173
175
 
174
176
  def _wildcard_prevalidation(self, host):
175
177
  if self.wildcard_disable:
@@ -192,8 +194,8 @@ class DNSHelper(EngineClient):
192
194
 
193
195
  return host
194
196
 
195
- async def _mock_dns(self, mock_data):
197
+ async def _mock_dns(self, mock_data, custom_lookup_fn=None):
196
198
  from .mock import MockResolver
197
199
 
198
- self.resolver = MockResolver(mock_data)
199
- await self.run_and_return("_mock_dns", mock_data=mock_data)
200
+ self.resolver = MockResolver(mock_data, custom_lookup_fn=custom_lookup_fn)
201
+ await self.run_and_return("_mock_dns", mock_data=mock_data, custom_lookup_fn=custom_lookup_fn)