bbot 2.1.0.4959rc0__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 (400) hide show
  1. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/PKG-INFO +2 -1
  2. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/__init__.py +1 -1
  3. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/event/base.py +28 -9
  4. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/misc.py +10 -3
  5. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/regexes.py +3 -0
  6. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/web/web.py +0 -48
  7. bbot-2.1.0.5028rc0/bbot/modules/apkpure.py +53 -0
  8. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/badsecrets.py +3 -2
  9. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/base.py +5 -3
  10. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/dotnetnuke.py +18 -17
  11. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/generic_ssrf.py +2 -2
  12. bbot-2.1.0.5028rc0/bbot/modules/google_playstore.py +93 -0
  13. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/httpx.py +0 -3
  14. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/internal/cloudcheck.py +2 -2
  15. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/internal/dnsresolve.py +2 -8
  16. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/internal/excavate.py +53 -4
  17. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/internal/speculate.py +3 -4
  18. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/internetdb.py +3 -1
  19. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/shodan_dns.py +7 -9
  20. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/templates/subdomain_enum.py +43 -4
  21. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/trickest.py +4 -28
  22. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/trufflehog.py +1 -1
  23. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/virustotal.py +4 -14
  24. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/subdomain-enum.yml +7 -7
  25. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/manager.py +4 -14
  26. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/preset/preset.py +0 -2
  27. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/scanner.py +17 -13
  28. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/bbot_fixtures.py +7 -0
  29. bbot-2.1.0.5028rc0/bbot/test/owasp_mastg.apk +0 -0
  30. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_cli.py +0 -8
  31. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_events.py +36 -7
  32. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_helpers.py +15 -2
  33. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_manager_scope_accuracy.py +9 -7
  34. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_modules_basic.py +15 -13
  35. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_presets.py +21 -3
  36. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_regexes.py +9 -2
  37. bbot-2.1.0.5028rc0/bbot/test/test_step_2/module_tests/test_module_apkpure.py +69 -0
  38. bbot-2.1.0.5028rc0/bbot/test/test_step_2/module_tests/test_module_google_playstore.py +83 -0
  39. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_httpx.py +3 -1
  40. bbot-2.1.0.5028rc0/bbot/test/test_step_2/module_tests/test_module_shodan_dns.py +40 -0
  41. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/pyproject.toml +2 -2
  42. bbot-2.1.0.4959rc0/bbot/test/test_step_2/module_tests/test_module_shodan_dns.py +0 -21
  43. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/LICENSE +0 -0
  44. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/README.md +0 -0
  45. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/cli.py +0 -0
  46. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/__init__.py +0 -0
  47. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/config/__init__.py +0 -0
  48. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/config/files.py +0 -0
  49. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/config/logger.py +0 -0
  50. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/core.py +0 -0
  51. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/engine.py +0 -0
  52. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/event/__init__.py +0 -0
  53. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/event/helpers.py +0 -0
  54. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/flags.py +0 -0
  55. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/__init__.py +0 -0
  56. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/async_helpers.py +0 -0
  57. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/bloom.py +0 -0
  58. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/cache.py +0 -0
  59. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/command.py +0 -0
  60. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/depsinstaller/__init__.py +0 -0
  61. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/depsinstaller/installer.py +0 -0
  62. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/depsinstaller/sudo_askpass.py +0 -0
  63. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/diff.py +0 -0
  64. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/dns/__init__.py +0 -0
  65. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/dns/brute.py +0 -0
  66. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/dns/dns.py +0 -0
  67. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/dns/engine.py +0 -0
  68. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/dns/helpers.py +0 -0
  69. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/dns/mock.py +0 -0
  70. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/files.py +0 -0
  71. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/helper.py +0 -0
  72. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/interactsh.py +0 -0
  73. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/names_generator.py +0 -0
  74. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/ntlm.py +0 -0
  75. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/process.py +0 -0
  76. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/ratelimiter.py +0 -0
  77. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/regex.py +0 -0
  78. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/url.py +0 -0
  79. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/validators.py +0 -0
  80. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/web/__init__.py +0 -0
  81. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/web/client.py +0 -0
  82. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/web/engine.py +0 -0
  83. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/web/ssl_context.py +0 -0
  84. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/wordcloud.py +0 -0
  85. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/modules.py +0 -0
  86. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/shared_deps.py +0 -0
  87. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/defaults.yml +0 -0
  88. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/errors.py +0 -0
  89. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/logger.py +0 -0
  90. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/__init__.py +0 -0
  91. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/ajaxpro.py +0 -0
  92. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/anubisdb.py +0 -0
  93. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/azure_realm.py +0 -0
  94. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/azure_tenant.py +0 -0
  95. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/baddns.py +0 -0
  96. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/baddns_direct.py +0 -0
  97. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/baddns_zone.py +0 -0
  98. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/bevigil.py +0 -0
  99. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/binaryedge.py +0 -0
  100. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/bucket_amazon.py +0 -0
  101. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/bucket_azure.py +0 -0
  102. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/bucket_digitalocean.py +0 -0
  103. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/bucket_file_enum.py +0 -0
  104. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/bucket_firebase.py +0 -0
  105. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/bucket_google.py +0 -0
  106. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/builtwith.py +0 -0
  107. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/bypass403.py +0 -0
  108. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/c99.py +0 -0
  109. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/censys.py +0 -0
  110. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/certspotter.py +0 -0
  111. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/chaos.py +0 -0
  112. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/code_repository.py +0 -0
  113. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/columbus.py +0 -0
  114. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/credshed.py +0 -0
  115. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/crt.py +0 -0
  116. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/deadly/dastardly.py +0 -0
  117. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/deadly/ffuf.py +0 -0
  118. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/deadly/nuclei.py +0 -0
  119. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/deadly/vhost.py +0 -0
  120. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/dehashed.py +0 -0
  121. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/digitorus.py +0 -0
  122. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/dnsbrute.py +0 -0
  123. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/dnsbrute_mutations.py +0 -0
  124. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/dnscaa.py +0 -0
  125. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/dnscommonsrv.py +0 -0
  126. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/dnsdumpster.py +0 -0
  127. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/docker_pull.py +0 -0
  128. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/dockerhub.py +0 -0
  129. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/emailformat.py +0 -0
  130. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/ffuf_shortnames.py +0 -0
  131. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/filedownload.py +0 -0
  132. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/fingerprintx.py +0 -0
  133. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/fullhunt.py +0 -0
  134. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/git.py +0 -0
  135. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/git_clone.py +0 -0
  136. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/github_codesearch.py +0 -0
  137. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/github_org.py +0 -0
  138. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/github_workflows.py +0 -0
  139. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/gitlab.py +0 -0
  140. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/gowitness.py +0 -0
  141. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/hackertarget.py +0 -0
  142. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/host_header.py +0 -0
  143. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/hunt.py +0 -0
  144. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/hunterio.py +0 -0
  145. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/iis_shortnames.py +0 -0
  146. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/internal/__init__.py +0 -0
  147. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/internal/aggregate.py +0 -0
  148. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/internal/base.py +0 -0
  149. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/ip2location.py +0 -0
  150. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/ipneighbor.py +0 -0
  151. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/ipstack.py +0 -0
  152. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/leakix.py +0 -0
  153. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/myssl.py +0 -0
  154. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/newsletters.py +0 -0
  155. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/ntlm.py +0 -0
  156. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/oauth.py +0 -0
  157. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/otx.py +0 -0
  158. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/__init__.py +0 -0
  159. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/asset_inventory.py +0 -0
  160. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/base.py +0 -0
  161. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/csv.py +0 -0
  162. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/discord.py +0 -0
  163. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/emails.py +0 -0
  164. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/http.py +0 -0
  165. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/json.py +0 -0
  166. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/neo4j.py +0 -0
  167. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/python.py +0 -0
  168. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/slack.py +0 -0
  169. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/splunk.py +0 -0
  170. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/stdout.py +0 -0
  171. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/subdomains.py +0 -0
  172. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/teams.py +0 -0
  173. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/txt.py +0 -0
  174. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/web_report.py +0 -0
  175. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/websocket.py +0 -0
  176. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/paramminer_cookies.py +0 -0
  177. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/paramminer_getparams.py +0 -0
  178. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/paramminer_headers.py +0 -0
  179. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/passivetotal.py +0 -0
  180. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/pgp.py +0 -0
  181. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/portscan.py +0 -0
  182. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/postman.py +0 -0
  183. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/postman_download.py +0 -0
  184. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/rapiddns.py +0 -0
  185. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/report/affiliates.py +0 -0
  186. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/report/asn.py +0 -0
  187. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/report/base.py +0 -0
  188. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/robots.py +0 -0
  189. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/secretsdb.py +0 -0
  190. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/securitytrails.py +0 -0
  191. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/securitytxt.py +0 -0
  192. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/sitedossier.py +0 -0
  193. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/skymem.py +0 -0
  194. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/smuggler.py +0 -0
  195. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/social.py +0 -0
  196. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/sslcert.py +0 -0
  197. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/subdomaincenter.py +0 -0
  198. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/subdomainradar.py +0 -0
  199. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/telerik.py +0 -0
  200. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/templates/bucket.py +0 -0
  201. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/templates/github.py +0 -0
  202. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/templates/postman.py +0 -0
  203. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/templates/shodan.py +0 -0
  204. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/templates/webhook.py +0 -0
  205. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/unstructured.py +0 -0
  206. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/url_manipulation.py +0 -0
  207. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/urlscan.py +0 -0
  208. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/viewdns.py +0 -0
  209. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/wafw00f.py +0 -0
  210. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/wappalyzer.py +0 -0
  211. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/wayback.py +0 -0
  212. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/wpscan.py +0 -0
  213. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/zoomeye.py +0 -0
  214. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/baddns-thorough.yml +0 -0
  215. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/cloud-enum.yml +0 -0
  216. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/code-enum.yml +0 -0
  217. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/email-enum.yml +0 -0
  218. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/kitchen-sink.yml +0 -0
  219. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/spider.yml +0 -0
  220. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/web/dirbust-heavy.yml +0 -0
  221. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/web/dirbust-light.yml +0 -0
  222. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/web/dotnet-audit.yml +0 -0
  223. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/web/iis-shortnames.yml +0 -0
  224. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/web/paramminer.yml +0 -0
  225. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/web-basic.yml +0 -0
  226. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/web-screenshots.yml +0 -0
  227. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/web-thorough.yml +0 -0
  228. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/__init__.py +0 -0
  229. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/dispatcher.py +0 -0
  230. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/preset/__init__.py +0 -0
  231. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/preset/args.py +0 -0
  232. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/preset/conditions.py +0 -0
  233. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/preset/environ.py +0 -0
  234. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/preset/path.py +0 -0
  235. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/stats.py +0 -0
  236. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/target.py +0 -0
  237. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/scripts/docs.py +0 -0
  238. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/__init__.py +0 -0
  239. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/conftest.py +0 -0
  240. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/coverage.cfg +0 -0
  241. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/run_tests.sh +0 -0
  242. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test.conf +0 -0
  243. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_output.ndjson +0 -0
  244. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/__init__.py +0 -0
  245. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test__module__tests.py +0 -0
  246. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_bloom_filter.py +0 -0
  247. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_command.py +0 -0
  248. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_config.py +0 -0
  249. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_depsinstaller.py +0 -0
  250. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_dns.py +0 -0
  251. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_docs.py +0 -0
  252. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_engine.py +0 -0
  253. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_files.py +0 -0
  254. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_manager_deduplication.py +0 -0
  255. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_python_api.py +0 -0
  256. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_scan.py +0 -0
  257. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_scope.py +0 -0
  258. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_target.py +0 -0
  259. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_web.py +0 -0
  260. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/__init__.py +0 -0
  261. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/__init__.py +0 -0
  262. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/base.py +0 -0
  263. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_affiliates.py +0 -0
  264. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_aggregate.py +0 -0
  265. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_ajaxpro.py +0 -0
  266. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_anubisdb.py +0 -0
  267. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_asn.py +0 -0
  268. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_asset_inventory.py +0 -0
  269. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_azure_realm.py +0 -0
  270. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_azure_tenant.py +0 -0
  271. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_baddns.py +0 -0
  272. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_baddns_direct.py +0 -0
  273. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_baddns_zone.py +0 -0
  274. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_badsecrets.py +0 -0
  275. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_bevigil.py +0 -0
  276. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_binaryedge.py +0 -0
  277. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_bucket_amazon.py +0 -0
  278. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_bucket_azure.py +0 -0
  279. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_bucket_digitalocean.py +0 -0
  280. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_bucket_file_enum.py +0 -0
  281. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_bucket_firebase.py +0 -0
  282. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_bucket_google.py +0 -0
  283. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_builtwith.py +0 -0
  284. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_bypass403.py +0 -0
  285. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_c99.py +0 -0
  286. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_censys.py +0 -0
  287. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_certspotter.py +0 -0
  288. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_chaos.py +0 -0
  289. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_cloudcheck.py +0 -0
  290. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_code_repository.py +0 -0
  291. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_columbus.py +0 -0
  292. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_credshed.py +0 -0
  293. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_crt.py +0 -0
  294. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_csv.py +0 -0
  295. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dastardly.py +0 -0
  296. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dehashed.py +0 -0
  297. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_digitorus.py +0 -0
  298. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_discord.py +0 -0
  299. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dnsbrute.py +0 -0
  300. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dnsbrute_mutations.py +0 -0
  301. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dnscaa.py +0 -0
  302. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dnscommonsrv.py +0 -0
  303. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dnsdumpster.py +0 -0
  304. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dnsresolve.py +0 -0
  305. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_docker_pull.py +0 -0
  306. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dockerhub.py +0 -0
  307. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dotnetnuke.py +0 -0
  308. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_emailformat.py +0 -0
  309. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_emails.py +0 -0
  310. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_excavate.py +0 -0
  311. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_ffuf.py +0 -0
  312. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_ffuf_shortnames.py +0 -0
  313. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_filedownload.py +0 -0
  314. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_fingerprintx.py +0 -0
  315. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_fullhunt.py +0 -0
  316. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_generic_ssrf.py +0 -0
  317. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_git.py +0 -0
  318. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_git_clone.py +0 -0
  319. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_github_codesearch.py +0 -0
  320. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_github_org.py +0 -0
  321. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_github_workflows.py +0 -0
  322. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_gitlab.py +0 -0
  323. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_gowitness.py +0 -0
  324. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_hackertarget.py +0 -0
  325. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_host_header.py +0 -0
  326. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_http.py +0 -0
  327. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_hunt.py +0 -0
  328. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_hunterio.py +0 -0
  329. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_iis_shortnames.py +0 -0
  330. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_internetdb.py +0 -0
  331. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_ip2location.py +0 -0
  332. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_ipneighbor.py +0 -0
  333. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_ipstack.py +0 -0
  334. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_json.py +0 -0
  335. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_leakix.py +0 -0
  336. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_myssl.py +0 -0
  337. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_neo4j.py +0 -0
  338. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_newsletters.py +0 -0
  339. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_ntlm.py +0 -0
  340. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_nuclei.py +0 -0
  341. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_oauth.py +0 -0
  342. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_otx.py +0 -0
  343. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_paramminer_cookies.py +0 -0
  344. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_paramminer_getparams.py +0 -0
  345. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_paramminer_headers.py +0 -0
  346. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_passivetotal.py +0 -0
  347. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_pgp.py +0 -0
  348. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_portscan.py +0 -0
  349. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_postman.py +0 -0
  350. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_postman_download.py +0 -0
  351. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_python.py +0 -0
  352. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_rapiddns.py +0 -0
  353. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_robots.py +0 -0
  354. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_secretsdb.py +0 -0
  355. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_securitytrails.py +0 -0
  356. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_securitytxt.py +0 -0
  357. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_sitedossier.py +0 -0
  358. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_skymem.py +0 -0
  359. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_slack.py +0 -0
  360. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_smuggler.py +0 -0
  361. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_social.py +0 -0
  362. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_speculate.py +0 -0
  363. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_splunk.py +0 -0
  364. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_sslcert.py +0 -0
  365. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_stdout.py +0 -0
  366. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_subdomaincenter.py +0 -0
  367. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_subdomainradar.py +0 -0
  368. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_subdomains.py +0 -0
  369. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_teams.py +0 -0
  370. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_telerik.py +0 -0
  371. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_trickest.py +0 -0
  372. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_trufflehog.py +0 -0
  373. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_txt.py +0 -0
  374. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_unstructured.py +0 -0
  375. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_url_manipulation.py +0 -0
  376. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_urlscan.py +0 -0
  377. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_vhost.py +0 -0
  378. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_viewdns.py +0 -0
  379. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_virustotal.py +0 -0
  380. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_wafw00f.py +0 -0
  381. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_wappalyzer.py +0 -0
  382. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_wayback.py +0 -0
  383. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_web_report.py +0 -0
  384. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_websocket.py +0 -0
  385. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_wpscan.py +0 -0
  386. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_zoomeye.py +0 -0
  387. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/template_tests/__init__.py +0 -0
  388. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/template_tests/test_template_subdomain_enum.py +0 -0
  389. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/testsslcert.pem +0 -0
  390. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/testsslkey.pem +0 -0
  391. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/wordlists/devops_mutations.txt +0 -0
  392. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/wordlists/ffuf_shortname_candidates.txt +0 -0
  393. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/wordlists/ms_on_prem_subdomains.txt +0 -0
  394. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/wordlists/nameservers.txt +0 -0
  395. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/wordlists/paramminer_headers.txt +0 -0
  396. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/wordlists/paramminer_parameters.txt +0 -0
  397. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/wordlists/raft-small-extensions-lowercase_CLEANED.txt +0 -0
  398. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/wordlists/top_open_ports_nmap.txt +0 -0
  399. {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/wordlists/valid_url_schemes.txt +0 -0
  400. {bbot-2.1.0.4959rc0 → 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.1.0.4959rc0
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)
@@ -1,4 +1,4 @@
1
1
  # version placeholder (replaced by poetry-dynamic-versioning)
2
- __version__ = "v2.1.0.4959rc"
2
+ __version__ = "v2.1.0.5028rc"
3
3
 
4
4
  from .scanner import Scanner, Preset
@@ -25,6 +25,7 @@ from bbot.core.helpers import (
25
25
  is_domain,
26
26
  is_subdomain,
27
27
  is_ip,
28
+ is_ip_type,
28
29
  is_ptr,
29
30
  is_uri,
30
31
  url_depth,
@@ -157,7 +158,7 @@ class BaseEvent:
157
158
  Raises:
158
159
  ValidationError: If either `scan` or `parent` are not specified and `_dummy` is False.
159
160
  """
160
- self.uuid = uuid.uuid4()
161
+ self._uuid = uuid.uuid4()
161
162
  self._id = None
162
163
  self._hash = None
163
164
  self._data = None
@@ -352,6 +353,12 @@ class BaseEvent:
352
353
  return 80
353
354
  return self._port
354
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
+
355
362
  @property
356
363
  def host_stem(self):
357
364
  """
@@ -440,11 +447,6 @@ class BaseEvent:
440
447
  no_host_information = not bool(self.host)
441
448
  return self._always_emit or always_emit_tags or no_host_information
442
449
 
443
- @property
444
- def quick_emit(self):
445
- no_host_information = not bool(self.host)
446
- return self._quick_emit or no_host_information
447
-
448
450
  @property
449
451
  def id(self):
450
452
  """
@@ -454,6 +456,13 @@ class BaseEvent:
454
456
  self._id = f"{self.type}:{self.data_hash.hex()}"
455
457
  return self._id
456
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
+
457
466
  @property
458
467
  def data_hash(self):
459
468
  """
@@ -746,7 +755,7 @@ class BaseEvent:
746
755
  """
747
756
  j = dict()
748
757
  # type, ID, scope description
749
- for i in ("type", "id", "uuid", "scope_description"):
758
+ for i in ("type", "id", "uuid", "scope_description", "netloc"):
750
759
  v = getattr(self, i, "")
751
760
  if v:
752
761
  j.update({i: str(v)})
@@ -765,6 +774,8 @@ class BaseEvent:
765
774
  j["host"] = str(self.host)
766
775
  j["resolved_hosts"] = sorted(str(h) for h in self.resolved_hosts)
767
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
768
779
  # web spider distance
769
780
  web_spider_distance = getattr(self, "web_spider_distance", None)
770
781
  if web_spider_distance is not None:
@@ -1537,6 +1548,13 @@ class RAW_DNS_RECORD(DictHostEvent, DnsEvent):
1537
1548
  _always_emit_tags = ["target"]
1538
1549
 
1539
1550
 
1551
+ class MOBILE_APP(DictEvent):
1552
+ _always_emit = True
1553
+
1554
+ def _pretty_string(self):
1555
+ return self.data["url"]
1556
+
1557
+
1540
1558
  def make_event(
1541
1559
  data,
1542
1560
  event_type=None,
@@ -1707,7 +1725,7 @@ def event_from_json(j, siem_friendly=False):
1707
1725
  event = make_event(**kwargs)
1708
1726
  event_uuid = j.get("uuid", None)
1709
1727
  if event_uuid is not None:
1710
- event.uuid = uuid.UUID(event_uuid)
1728
+ event._uuid = uuid.UUID(event_uuid.split(":")[-1])
1711
1729
 
1712
1730
  resolved_hosts = j.get("resolved_hosts", [])
1713
1731
  event._resolved_hosts = set(resolved_hosts)
@@ -1719,7 +1737,8 @@ def event_from_json(j, siem_friendly=False):
1719
1737
  event._parent_id = parent_id
1720
1738
  parent_uuid = j.get("parent_uuid", None)
1721
1739
  if parent_uuid is not None:
1722
- event._parent_uuid = uuid.UUID(parent_uuid)
1740
+ parent_type, parent_uuid = parent_uuid.split(":", 1)
1741
+ event._parent_uuid = parent_type + ":" + str(uuid.UUID(parent_uuid))
1723
1742
  return event
1724
1743
  except KeyError as e:
1725
1744
  raise ValidationError(f"Event missing required field: {e}")
@@ -621,12 +621,13 @@ def is_ip(d, version=None):
621
621
  return False
622
622
 
623
623
 
624
- def is_ip_type(i):
624
+ def is_ip_type(i, network=None):
625
625
  """
626
626
  Checks if the given object is an instance of an IPv4 or IPv6 type from the ipaddress module.
627
627
 
628
628
  Args:
629
629
  i (ipaddress._BaseV4 or ipaddress._BaseV6): The IP object to check.
630
+ network (bool, optional): Whether to restrict the check to network types (IPv4Network or IPv6Network). Defaults to False.
630
631
 
631
632
  Returns:
632
633
  bool: True if the object is an instance of ipaddress._BaseV4 or ipaddress._BaseV6, False otherwise.
@@ -639,6 +640,12 @@ def is_ip_type(i):
639
640
  >>> is_ip_type("192.168.1.0/24")
640
641
  False
641
642
  """
643
+ if network is not None:
644
+ is_network = ipaddress._BaseNetwork in i.__class__.__mro__
645
+ if network:
646
+ return is_network
647
+ else:
648
+ return not is_network
642
649
  return ipaddress._IPAddressBase in i.__class__.__mro__
643
650
 
644
651
 
@@ -1260,7 +1267,7 @@ def gen_numbers(n, padding=2):
1260
1267
  return results
1261
1268
 
1262
1269
 
1263
- def make_netloc(host, port):
1270
+ def make_netloc(host, port=None):
1264
1271
  """Constructs a network location string from a given host and port.
1265
1272
 
1266
1273
  Args:
@@ -1289,7 +1296,7 @@ def make_netloc(host, port):
1289
1296
  if is_ip(host, version=6):
1290
1297
  host = f"[{host}]"
1291
1298
  if port is None:
1292
- return host
1299
+ return str(host)
1293
1300
  return f"{host}:{port}"
1294
1301
 
1295
1302
 
@@ -54,6 +54,9 @@ ptr_regex = re.compile(_ptr_regex)
54
54
  # uuid regex
55
55
  _uuid_regex = r"[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}"
56
56
  uuid_regex = re.compile(_uuid_regex, re.I)
57
+ # event uuid regex
58
+ _event_uuid_regex = r"[0-9A-Z_]+:[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}"
59
+ event_uuid_regex = re.compile(_event_uuid_regex, re.I)
57
60
 
58
61
  _open_port_regexes = (
59
62
  _dns_name_regex + r":[0-9]{1,5}",
@@ -1,4 +1,3 @@
1
- import re
2
1
  import logging
3
2
  import warnings
4
3
  from pathlib import Path
@@ -464,53 +463,6 @@ class WebHelper(EngineClient):
464
463
  log.debug(f"Error parsing beautifulsoup: {e}")
465
464
  return False
466
465
 
467
- user_keywords = [re.compile(r, re.I) for r in ["user", "login", "email"]]
468
- pass_keywords = [re.compile(r, re.I) for r in ["pass"]]
469
-
470
- def is_login_page(self, html):
471
- """
472
- TODO: convert this into an excavate YARA rule
473
-
474
- Determines if the provided HTML content contains a login page.
475
-
476
- This function parses the HTML to search for forms with input fields typically used for
477
- authentication. If it identifies password fields or a combination of username and password
478
- fields, it returns True.
479
-
480
- Args:
481
- html (str): The HTML content to analyze.
482
-
483
- Returns:
484
- bool: True if the HTML contains a login page, otherwise False.
485
-
486
- Examples:
487
- >>> is_login_page('<form><input type="text" name="username"><input type="password" name="password"></form>')
488
- True
489
-
490
- >>> is_login_page('<form><input type="text" name="search"></form>')
491
- False
492
- """
493
- try:
494
- soup = BeautifulSoup(html, "html.parser")
495
- except Exception as e:
496
- log.debug(f"Error parsing html: {e}")
497
- return False
498
-
499
- forms = soup.find_all("form")
500
-
501
- # first, check for obvious password fields
502
- for form in forms:
503
- if form.find_all("input", {"type": "password"}):
504
- return True
505
-
506
- # next, check for forms that have both a user-like and password-like field
507
- for form in forms:
508
- user_fields = sum(bool(form.find_all("input", {"name": r})) for r in self.user_keywords)
509
- pass_fields = sum(bool(form.find_all("input", {"name": r})) for r in self.pass_keywords)
510
- if user_fields and pass_fields:
511
- return True
512
- return False
513
-
514
466
  def response_to_json(self, response):
515
467
  """
516
468
  Convert web response to JSON object, similar to the output of `httpx -irr -json`
@@ -0,0 +1,53 @@
1
+ from pathlib import Path
2
+ from bbot.modules.base import BaseModule
3
+
4
+
5
+ class apkpure(BaseModule):
6
+ watched_events = ["MOBILE_APP"]
7
+ produced_events = ["FILESYSTEM"]
8
+ flags = ["passive", "safe", "code-enum"]
9
+ meta = {
10
+ "description": "Download android applications from apkpure.com",
11
+ "created_date": "2024-10-11",
12
+ "author": "@domwhewell-sage",
13
+ }
14
+ options = {"output_folder": ""}
15
+ options_desc = {"output_folder": "Folder to download apk's to"}
16
+
17
+ async def setup(self):
18
+ output_folder = self.config.get("output_folder")
19
+ if output_folder:
20
+ self.output_dir = Path(output_folder) / "apk_files"
21
+ else:
22
+ self.output_dir = self.scan.home / "apk_files"
23
+ self.helpers.mkdir(self.output_dir)
24
+ return await super().setup()
25
+
26
+ async def filter_event(self, event):
27
+ if event.type == "MOBILE_APP":
28
+ if "android" not in event.tags:
29
+ return False, "event is not an android app"
30
+ return True
31
+
32
+ async def handle_event(self, event):
33
+ app_id = event.data.get("id", "")
34
+ path = await self.download_apk(app_id)
35
+ if path:
36
+ await self.emit_event(
37
+ {"path": str(path)},
38
+ "FILESYSTEM",
39
+ tags=["apk", "file"],
40
+ parent=event,
41
+ context=f'{{module}} downloaded the apk "{app_id}" to: {path}',
42
+ )
43
+
44
+ async def download_apk(self, app_id):
45
+ path = None
46
+ url = f"https://d.apkpure.com/b/XAPK/{app_id}?version=latest"
47
+ self.helpers.mkdir(self.output_dir / app_id)
48
+ file_destination = self.output_dir / app_id / f"{app_id}.xapk"
49
+ result = await self.helpers.download(url, warn=False, filename=file_destination)
50
+ if result:
51
+ self.info(f'Downloaded "{app_id}" from "{url}", saved to {file_destination}')
52
+ path = file_destination
53
+ return path
@@ -23,12 +23,13 @@ class badsecrets(BaseModule):
23
23
  self.custom_secrets = None
24
24
  custom_secrets = self.config.get("custom_secrets", None)
25
25
  if custom_secrets:
26
- if Path(custom_secrets).is_file():
26
+ secrets_path = Path(custom_secrets).expanduser()
27
+ if secrets_path.is_file():
27
28
  self.custom_secrets = custom_secrets
28
29
  self.info(f"Successfully loaded secrets file [{custom_secrets}]")
29
30
  else:
30
31
  self.warning(f"custom secrets file [{custom_secrets}] is not valid")
31
- return None, "Custom secrets file not valid"
32
+ return False, "Custom secrets file not valid"
32
33
  return True
33
34
 
34
35
  @property
@@ -984,8 +984,11 @@ class BaseModule:
984
984
  def _outgoing_dedup_hash(self, event):
985
985
  """
986
986
  Determines the criteria for what is considered to be a duplicate event if `suppress_dupes` is True.
987
+
988
+ We take into account the `internal` attribute we don't want an internal event (which isn't distributed to output modules)
989
+ to inadvertently suppress a non-internal event.
987
990
  """
988
- return hash((event, self.name))
991
+ return hash((event, self.name, event.internal, event.always_emit))
989
992
 
990
993
  def get_per_host_hash(self, event):
991
994
  """
@@ -1559,7 +1562,7 @@ class BaseModule:
1559
1562
  self.trace()
1560
1563
 
1561
1564
 
1562
- class InterceptModule(BaseModule):
1565
+ class BaseInterceptModule(BaseModule):
1563
1566
  """
1564
1567
  An Intercept Module is a special type of high-priority module that gets early access to events.
1565
1568
 
@@ -1571,7 +1574,6 @@ class InterceptModule(BaseModule):
1571
1574
  """
1572
1575
 
1573
1576
  accept_dupes = True
1574
- suppress_dupes = False
1575
1577
  _intercept = True
1576
1578
 
1577
1579
  async def _worker(self):
@@ -155,24 +155,25 @@ class dotnetnuke(BaseModule):
155
155
 
156
156
  # InstallWizard SuperUser Privilege Escalation
157
157
  result = await self.helpers.request(f'{event.data["url"]}/Install/InstallWizard.aspx')
158
- if result.status_code == 200:
159
- result_confirm = await self.helpers.request(
160
- f'{event.data["url"]}/Install/InstallWizard.aspx?__viewstate=1'
161
- )
162
- if result_confirm.status_code == 500:
163
- description = "DotNetNuke InstallWizard SuperUser Privilege Escalation"
164
- await self.emit_event(
165
- {
166
- "severity": "CRITICAL",
167
- "description": description,
168
- "host": str(event.host),
169
- "url": f'{event.data["url"]}/Install/InstallWizard.aspx',
170
- },
171
- "VULNERABILITY",
172
- event,
173
- context=f'{{module}} scanned {event.data["url"]} and found critical {{event.type}}: {description}',
158
+ if result:
159
+ if result.status_code == 200:
160
+ result_confirm = await self.helpers.request(
161
+ f'{event.data["url"]}/Install/InstallWizard.aspx?__viewstate=1'
174
162
  )
175
- return
163
+ if result_confirm.status_code == 500:
164
+ description = "DotNetNuke InstallWizard SuperUser Privilege Escalation"
165
+ await self.emit_event(
166
+ {
167
+ "severity": "CRITICAL",
168
+ "description": description,
169
+ "host": str(event.host),
170
+ "url": f'{event.data["url"]}/Install/InstallWizard.aspx',
171
+ },
172
+ "VULNERABILITY",
173
+ event,
174
+ context=f'{{module}} scanned {event.data["url"]} and found critical {{event.type}}: {description}',
175
+ )
176
+ return
176
177
 
177
178
  # DNNImageHandler.ashx Blind SSRF
178
179
  self.event_dict[event.data["url"]] = event
@@ -137,10 +137,10 @@ class Generic_XXE(BaseSubmodule):
137
137
  post_body = f"""<?xml version="1.0" encoding="ISO-8859-1"?>
138
138
  <!DOCTYPE foo [
139
139
  <!ELEMENT foo ANY >
140
- <!ENTITY % {rand_entity} SYSTEM "http://{subdomain_tag}.{self.parent_module.interactsh_domain}" >
140
+ <!ENTITY {rand_entity} SYSTEM "http://{subdomain_tag}.{self.parent_module.interactsh_domain}" >
141
141
  ]>
142
142
  <foo>&{rand_entity};</foo>"""
143
- test_url = f"{event.parsed_url.scheme}://{event.parsed_url.netloc}/"
143
+ test_url = event.parsed_url.geturl()
144
144
  r = await self.parent_module.helpers.curl(
145
145
  url=test_url, method="POST", raw_body=post_body, headers={"Content-type": "application/xml"}
146
146
  )
@@ -0,0 +1,93 @@
1
+ from bbot.modules.base import BaseModule
2
+
3
+
4
+ class google_playstore(BaseModule):
5
+ watched_events = ["ORG_STUB", "CODE_REPOSITORY"]
6
+ produced_events = ["MOBILE_APP"]
7
+ flags = ["passive", "safe", "code-enum"]
8
+ meta = {
9
+ "description": "Search for android applications on play.google.com",
10
+ "created_date": "2024-10-08",
11
+ "author": "@domwhewell-sage",
12
+ }
13
+
14
+ base_url = "https://play.google.com"
15
+
16
+ async def setup(self):
17
+ self.app_link_regex = self.helpers.re.compile(r"/store/apps/details\?id=([a-zA-Z0-9._-]+)")
18
+ return True
19
+
20
+ async def filter_event(self, event):
21
+ if event.type == "CODE_REPOSITORY":
22
+ if "android" not in event.tags:
23
+ return False, "event is not an android repository"
24
+ return True
25
+
26
+ async def handle_event(self, event):
27
+ if event.type == "CODE_REPOSITORY":
28
+ await self.handle_url(event)
29
+ elif event.type == "ORG_STUB":
30
+ await self.handle_org_stub(event)
31
+
32
+ async def handle_url(self, event):
33
+ repo_url = event.data.get("url")
34
+ app_id = repo_url.split("id=")[1].split("&")[0]
35
+ await self.emit_event(
36
+ {"id": app_id, "url": repo_url},
37
+ "MOBILE_APP",
38
+ tags="android",
39
+ parent=event,
40
+ context=f'{{module}} extracted the mobile app name "{app_id}" from: {repo_url}',
41
+ )
42
+
43
+ async def handle_org_stub(self, event):
44
+ org_name = event.data
45
+ self.verbose(f"Searching for any android applications for {org_name}")
46
+ for apk_name in await self.query(org_name):
47
+ valid_apk = await self.validate_apk(apk_name)
48
+ if valid_apk:
49
+ self.verbose(f"Got {apk_name} from playstore")
50
+ await self.emit_event(
51
+ {"id": apk_name, "url": f"{self.base_url}/store/apps/details?id={apk_name}"},
52
+ "MOBILE_APP",
53
+ tags="android",
54
+ parent=event,
55
+ context=f'{{module}} searched play.google.com for apps belonging to "{org_name}" and found "{apk_name}" to be in scope',
56
+ )
57
+ else:
58
+ self.debug(f"Got {apk_name} from playstore app details does not contain any in-scope URLs or Emails")
59
+
60
+ async def query(self, query):
61
+ app_links = []
62
+ url = f"{self.base_url}/store/search?q={self.helpers.quote(query)}&c=apps"
63
+ r = await self.helpers.request(url)
64
+ if r is None:
65
+ return app_links
66
+ status_code = getattr(r, "status_code", 0)
67
+ try:
68
+ html_content = r.content.decode("utf-8")
69
+ # Use regex to find all app links
70
+ app_links = await self.helpers.re.findall(self.app_link_regex, html_content)
71
+ except Exception as e:
72
+ self.warning(f"Failed to parse html response from {r.url} (HTTP status: {status_code}): {e}")
73
+ return app_links
74
+ return app_links
75
+
76
+ async def validate_apk(self, apk_name):
77
+ """
78
+ Check the app details page the "App support" section will include URLs or Emails to the app developer
79
+ """
80
+ in_scope = False
81
+ url = f"{self.base_url}/store/apps/details?id={apk_name}"
82
+ r = await self.helpers.request(url)
83
+ if r is None:
84
+ return in_scope
85
+ status_code = getattr(r, "status_code", 0)
86
+ if status_code == 200:
87
+ html = r.text
88
+ in_scope_hosts = await self.scan.extract_in_scope_hostnames(html)
89
+ if in_scope_hosts:
90
+ in_scope = True
91
+ else:
92
+ self.warning(f"Failed to fetch {url} (HTTP status: {status_code})")
93
+ return in_scope
@@ -172,9 +172,6 @@ class httpx(BaseModule):
172
172
  httpx_ip = j.get("host", "")
173
173
  if httpx_ip:
174
174
  tags.append(f"ip-{httpx_ip}")
175
- # detect login pages
176
- if self.helpers.web.is_login_page(j.get("body", "")):
177
- tags.append("login-page")
178
175
  # grab title
179
176
  title = self.helpers.tagify(j.get("title", ""), maxlen=30)
180
177
  if title:
@@ -1,7 +1,7 @@
1
- from bbot.modules.base import InterceptModule
1
+ from bbot.modules.base import BaseInterceptModule
2
2
 
3
3
 
4
- class CloudCheck(InterceptModule):
4
+ class CloudCheck(BaseInterceptModule):
5
5
  watched_events = ["*"]
6
6
  meta = {"description": "Tag events by cloud provider, identify cloud resources like storage buckets"}
7
7
  scope_distance_modifier = 1
@@ -3,11 +3,11 @@ from contextlib import suppress
3
3
 
4
4
  from bbot.errors import ValidationError
5
5
  from bbot.core.helpers.dns.engine import all_rdtypes
6
- from bbot.modules.base import InterceptModule, BaseModule
7
6
  from bbot.core.helpers.dns.helpers import extract_targets
7
+ from bbot.modules.base import BaseInterceptModule, BaseModule
8
8
 
9
9
 
10
- class DNSResolve(InterceptModule):
10
+ class DNSResolve(BaseInterceptModule):
11
11
  watched_events = ["*"]
12
12
  _priority = 1
13
13
  scope_distance_modifier = None
@@ -16,12 +16,6 @@ class DNSResolve(InterceptModule):
16
16
  _name = "host"
17
17
  _type = "internal"
18
18
 
19
- def _outgoing_dedup_hash(self, event):
20
- # this exists to ensure a second, more interesting host isn't passed up
21
- # because its ugly cousin spent its one dedup token before it arrived
22
- # by removing those race conditions, this makes for more consistent results
23
- return hash((event, self.name, event.always_emit))
24
-
25
19
  @property
26
20
  def module_threads(self):
27
21
  return self.dns_config.get("threads", 25)
@@ -6,6 +6,7 @@ import regex as re
6
6
  from pathlib import Path
7
7
  from bbot.errors import ExcavateError
8
8
  import bbot.core.helpers.regexes as bbot_regexes
9
+ from bbot.modules.base import BaseInterceptModule
9
10
  from bbot.modules.internal.base import BaseInternalModule
10
11
  from urllib.parse import urlparse, urljoin, parse_qs, urlunparse
11
12
 
@@ -153,7 +154,9 @@ class ExcavateRule:
153
154
  yara_rule_settings = YaraRuleSettings(description, tags, emit_match)
154
155
  yara_results = {}
155
156
  for h in r.strings:
156
- yara_results[h.identifier.lstrip("$")] = sorted(set([i.matched_data.decode("utf-8") for i in h.instances]))
157
+ yara_results[h.identifier.lstrip("$")] = sorted(
158
+ set([i.matched_data.decode("utf-8", errors="ignore") for i in h.instances])
159
+ )
157
160
  await self.process(yara_results, event, yara_rule_settings, discovery_context)
158
161
 
159
162
  async def process(self, yara_results, event, yara_rule_settings, discovery_context):
@@ -279,7 +282,7 @@ class CustomExtractor(ExcavateRule):
279
282
  await self.report(event_data, event, yara_rule_settings, discovery_context)
280
283
 
281
284
 
282
- class excavate(BaseInternalModule):
285
+ class excavate(BaseInternalModule, BaseInterceptModule):
283
286
  """
284
287
  Example (simple) Excavate Rules:
285
288
 
@@ -310,6 +313,7 @@ class excavate(BaseInternalModule):
310
313
  "custom_yara_rules": "Include custom Yara rules",
311
314
  }
312
315
  scope_distance_modifier = None
316
+ accept_dupes = False
313
317
 
314
318
  _module_threads = 8
315
319
 
@@ -669,8 +673,32 @@ class excavate(BaseInternalModule):
669
673
 
670
674
  class URLExtractor(ExcavateRule):
671
675
  yara_rules = {
672
- "url_full": r'rule url_full { meta: tags = "spider-danger" description = "contains full URL" strings: $url_full = /https?:\/\/([\w\.-]+)(:\d{1,5})?([\/\w\.-]*)/ condition: $url_full }',
673
- "url_attr": r'rule url_attr { meta: tags = "spider-danger" description = "contains tag with src or href attribute" strings: $url_attr = /<[^>]+(href|src)=["\'][^"\']*["\'][^>]*>/ condition: $url_attr }',
676
+ "url_full": (
677
+ r"""
678
+ rule url_full {
679
+ meta:
680
+ tags = "spider-danger"
681
+ description = "contains full URL"
682
+ strings:
683
+ $url_full = /https?:\/\/([\w\.-]+)(:\d{1,5})?([\/\w\.-]*)/
684
+ condition:
685
+ $url_full
686
+ }
687
+ """
688
+ ),
689
+ "url_attr": (
690
+ r"""
691
+ rule url_attr {
692
+ meta:
693
+ tags = "spider-danger"
694
+ description = "contains tag with src or href attribute"
695
+ strings:
696
+ $url_attr = /<[^>]+(href|src)=["\'][^"\']*["\'][^>]*>/
697
+ condition:
698
+ $url_attr
699
+ }
700
+ """
701
+ ),
674
702
  }
675
703
  full_url_regex = re.compile(r"(https?)://((?:\w|\d)(?:[\d\w-]+\.?)+(?::\d{1,5})?(?:/[-\w\.\(\)]*[-\w\.]+)*/?)")
676
704
  full_url_regex_strict = re.compile(r"^(https?):\/\/([\w.-]+)(?::\d{1,5})?(\/[\w\/\.-]*)?(\?[^\s]+)?$")
@@ -749,6 +777,25 @@ class excavate(BaseInternalModule):
749
777
  for domain_str in yara_results[identifier]:
750
778
  await self.report(domain_str, event, yara_rule_settings, discovery_context, event_type="DNS_NAME")
751
779
 
780
+ class LoginPageExtractor(ExcavateRule):
781
+ yara_rules = {
782
+ "login_page": r"""
783
+ rule login_page {
784
+ meta:
785
+ description = "Detects login pages with username and password fields"
786
+ strings:
787
+ $username_field = /<input[^>]+name=["']?(user|login|email)/ nocase
788
+ $password_field = /<input[^>]+name=["']?passw?/ nocase
789
+ condition:
790
+ $username_field and $password_field
791
+ }
792
+ """
793
+ }
794
+
795
+ async def process(self, yara_results, event, yara_rule_settings, discovery_context):
796
+ if yara_results:
797
+ event.add_tag("login-page")
798
+
752
799
  def add_yara_rule(self, rule_name, rule_content, rule_instance):
753
800
  rule_instance.name = rule_name
754
801
  self.yara_rules_dict[rule_name] = rule_content
@@ -829,6 +876,8 @@ class excavate(BaseInternalModule):
829
876
  yara_rules_combined = "\n".join(self.yara_rules_dict.values())
830
877
  try:
831
878
  self.info(f"Compiling {len(self.yara_rules_dict):,} YARA rules")
879
+ for rule_name, rule_content in self.yara_rules_dict.items():
880
+ self.debug(f" - {rule_name}")
832
881
  self.yara_rules = yara.compile(source=yara_rules_combined)
833
882
  except yara.SyntaxError as e:
834
883
  self.debug(yara_rules_combined)