bbot 2.0.1.4654rc0__py3-none-any.whl → 2.3.0.5397rc0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (270) hide show
  1. bbot/__init__.py +1 -1
  2. bbot/cli.py +3 -7
  3. bbot/core/config/files.py +0 -1
  4. bbot/core/config/logger.py +34 -4
  5. bbot/core/core.py +21 -6
  6. bbot/core/engine.py +9 -8
  7. bbot/core/event/base.py +162 -63
  8. bbot/core/helpers/bloom.py +10 -3
  9. bbot/core/helpers/command.py +9 -8
  10. bbot/core/helpers/depsinstaller/installer.py +89 -32
  11. bbot/core/helpers/depsinstaller/sudo_askpass.py +38 -2
  12. bbot/core/helpers/diff.py +10 -10
  13. bbot/core/helpers/dns/brute.py +18 -14
  14. bbot/core/helpers/dns/dns.py +16 -15
  15. bbot/core/helpers/dns/engine.py +159 -132
  16. bbot/core/helpers/dns/helpers.py +2 -2
  17. bbot/core/helpers/dns/mock.py +26 -8
  18. bbot/core/helpers/files.py +1 -1
  19. bbot/core/helpers/helper.py +7 -4
  20. bbot/core/helpers/interactsh.py +3 -3
  21. bbot/core/helpers/libmagic.py +65 -0
  22. bbot/core/helpers/misc.py +65 -22
  23. bbot/core/helpers/names_generator.py +17 -3
  24. bbot/core/helpers/process.py +0 -20
  25. bbot/core/helpers/regex.py +1 -1
  26. bbot/core/helpers/regexes.py +12 -6
  27. bbot/core/helpers/validators.py +1 -2
  28. bbot/core/helpers/web/client.py +1 -1
  29. bbot/core/helpers/web/engine.py +18 -13
  30. bbot/core/helpers/web/web.py +25 -116
  31. bbot/core/helpers/wordcloud.py +5 -5
  32. bbot/core/modules.py +36 -27
  33. bbot/core/multiprocess.py +58 -0
  34. bbot/core/shared_deps.py +46 -3
  35. bbot/db/sql/models.py +147 -0
  36. bbot/defaults.yml +15 -10
  37. bbot/errors.py +0 -8
  38. bbot/modules/anubisdb.py +2 -2
  39. bbot/modules/apkpure.py +63 -0
  40. bbot/modules/azure_tenant.py +2 -2
  41. bbot/modules/baddns.py +35 -19
  42. bbot/modules/baddns_direct.py +92 -0
  43. bbot/modules/baddns_zone.py +3 -8
  44. bbot/modules/badsecrets.py +4 -3
  45. bbot/modules/base.py +195 -51
  46. bbot/modules/bevigil.py +7 -7
  47. bbot/modules/binaryedge.py +7 -4
  48. bbot/modules/bufferoverrun.py +47 -0
  49. bbot/modules/builtwith.py +6 -10
  50. bbot/modules/bypass403.py +5 -5
  51. bbot/modules/c99.py +10 -7
  52. bbot/modules/censys.py +9 -13
  53. bbot/modules/certspotter.py +5 -3
  54. bbot/modules/chaos.py +9 -7
  55. bbot/modules/code_repository.py +1 -0
  56. bbot/modules/columbus.py +3 -3
  57. bbot/modules/crt.py +5 -3
  58. bbot/modules/deadly/dastardly.py +1 -1
  59. bbot/modules/deadly/ffuf.py +9 -9
  60. bbot/modules/deadly/nuclei.py +3 -3
  61. bbot/modules/deadly/vhost.py +4 -3
  62. bbot/modules/dehashed.py +1 -1
  63. bbot/modules/digitorus.py +1 -1
  64. bbot/modules/dnsbimi.py +145 -0
  65. bbot/modules/dnscaa.py +3 -3
  66. bbot/modules/dnsdumpster.py +4 -4
  67. bbot/modules/dnstlsrpt.py +144 -0
  68. bbot/modules/docker_pull.py +7 -5
  69. bbot/modules/dockerhub.py +2 -2
  70. bbot/modules/dotnetnuke.py +18 -19
  71. bbot/modules/emailformat.py +1 -1
  72. bbot/modules/extractous.py +122 -0
  73. bbot/modules/filedownload.py +9 -7
  74. bbot/modules/fullhunt.py +7 -4
  75. bbot/modules/generic_ssrf.py +5 -5
  76. bbot/modules/github_codesearch.py +3 -2
  77. bbot/modules/github_org.py +4 -4
  78. bbot/modules/github_workflows.py +4 -4
  79. bbot/modules/gitlab.py +2 -5
  80. bbot/modules/google_playstore.py +93 -0
  81. bbot/modules/gowitness.py +48 -50
  82. bbot/modules/hackertarget.py +5 -3
  83. bbot/modules/host_header.py +5 -5
  84. bbot/modules/httpx.py +1 -4
  85. bbot/modules/hunterio.py +3 -9
  86. bbot/modules/iis_shortnames.py +19 -30
  87. bbot/modules/internal/cloudcheck.py +27 -12
  88. bbot/modules/internal/dnsresolve.py +250 -276
  89. bbot/modules/internal/excavate.py +100 -64
  90. bbot/modules/internal/speculate.py +42 -33
  91. bbot/modules/internetdb.py +4 -2
  92. bbot/modules/ip2location.py +3 -5
  93. bbot/modules/ipneighbor.py +1 -1
  94. bbot/modules/ipstack.py +3 -8
  95. bbot/modules/jadx.py +87 -0
  96. bbot/modules/leakix.py +11 -10
  97. bbot/modules/myssl.py +2 -2
  98. bbot/modules/newsletters.py +2 -2
  99. bbot/modules/otx.py +5 -3
  100. bbot/modules/output/asset_inventory.py +7 -7
  101. bbot/modules/output/base.py +1 -1
  102. bbot/modules/output/csv.py +1 -2
  103. bbot/modules/output/http.py +20 -14
  104. bbot/modules/output/mysql.py +51 -0
  105. bbot/modules/output/neo4j.py +7 -2
  106. bbot/modules/output/postgres.py +49 -0
  107. bbot/modules/output/slack.py +0 -1
  108. bbot/modules/output/sqlite.py +29 -0
  109. bbot/modules/output/stdout.py +2 -2
  110. bbot/modules/output/teams.py +107 -6
  111. bbot/modules/paramminer_headers.py +5 -8
  112. bbot/modules/passivetotal.py +13 -13
  113. bbot/modules/portscan.py +32 -6
  114. bbot/modules/postman.py +50 -126
  115. bbot/modules/postman_download.py +220 -0
  116. bbot/modules/rapiddns.py +3 -8
  117. bbot/modules/report/asn.py +11 -11
  118. bbot/modules/robots.py +3 -3
  119. bbot/modules/securitytrails.py +7 -10
  120. bbot/modules/securitytxt.py +128 -0
  121. bbot/modules/shodan_dns.py +7 -9
  122. bbot/modules/sitedossier.py +1 -1
  123. bbot/modules/skymem.py +2 -2
  124. bbot/modules/social.py +2 -1
  125. bbot/modules/subdomaincenter.py +1 -1
  126. bbot/modules/subdomainradar.py +160 -0
  127. bbot/modules/telerik.py +8 -8
  128. bbot/modules/templates/bucket.py +1 -1
  129. bbot/modules/templates/github.py +22 -14
  130. bbot/modules/templates/postman.py +21 -0
  131. bbot/modules/templates/shodan.py +14 -13
  132. bbot/modules/templates/sql.py +95 -0
  133. bbot/modules/templates/subdomain_enum.py +53 -17
  134. bbot/modules/templates/webhook.py +2 -4
  135. bbot/modules/trickest.py +8 -37
  136. bbot/modules/trufflehog.py +18 -3
  137. bbot/modules/url_manipulation.py +3 -3
  138. bbot/modules/urlscan.py +1 -1
  139. bbot/modules/viewdns.py +1 -1
  140. bbot/modules/virustotal.py +8 -30
  141. bbot/modules/wafw00f.py +1 -1
  142. bbot/modules/wayback.py +1 -1
  143. bbot/modules/wpscan.py +17 -11
  144. bbot/modules/zoomeye.py +11 -6
  145. bbot/presets/baddns-thorough.yml +12 -0
  146. bbot/presets/fast.yml +16 -0
  147. bbot/presets/kitchen-sink.yml +1 -0
  148. bbot/presets/spider.yml +4 -0
  149. bbot/presets/subdomain-enum.yml +7 -7
  150. bbot/scanner/manager.py +5 -16
  151. bbot/scanner/preset/args.py +44 -26
  152. bbot/scanner/preset/environ.py +7 -2
  153. bbot/scanner/preset/path.py +7 -4
  154. bbot/scanner/preset/preset.py +36 -23
  155. bbot/scanner/scanner.py +176 -63
  156. bbot/scanner/target.py +236 -434
  157. bbot/scripts/docs.py +1 -1
  158. bbot/test/bbot_fixtures.py +22 -3
  159. bbot/test/conftest.py +132 -100
  160. bbot/test/fastapi_test.py +17 -0
  161. bbot/test/owasp_mastg.apk +0 -0
  162. bbot/test/run_tests.sh +4 -4
  163. bbot/test/test.conf +2 -0
  164. bbot/test/test_step_1/test_bbot_fastapi.py +82 -0
  165. bbot/test/test_step_1/test_bloom_filter.py +2 -0
  166. bbot/test/test_step_1/test_cli.py +138 -64
  167. bbot/test/test_step_1/test_dns.py +392 -70
  168. bbot/test/test_step_1/test_engine.py +17 -17
  169. bbot/test/test_step_1/test_events.py +203 -37
  170. bbot/test/test_step_1/test_helpers.py +64 -28
  171. bbot/test/test_step_1/test_manager_deduplication.py +1 -1
  172. bbot/test/test_step_1/test_manager_scope_accuracy.py +336 -338
  173. bbot/test/test_step_1/test_modules_basic.py +69 -71
  174. bbot/test/test_step_1/test_presets.py +184 -96
  175. bbot/test/test_step_1/test_python_api.py +7 -2
  176. bbot/test/test_step_1/test_regexes.py +35 -5
  177. bbot/test/test_step_1/test_scan.py +39 -5
  178. bbot/test/test_step_1/test_scope.py +5 -4
  179. bbot/test/test_step_1/test_target.py +243 -145
  180. bbot/test/test_step_1/test_web.py +48 -10
  181. bbot/test/test_step_2/module_tests/base.py +17 -20
  182. bbot/test/test_step_2/module_tests/test_module_anubisdb.py +1 -1
  183. bbot/test/test_step_2/module_tests/test_module_apkpure.py +71 -0
  184. bbot/test/test_step_2/module_tests/test_module_asset_inventory.py +0 -1
  185. bbot/test/test_step_2/module_tests/test_module_azure_realm.py +1 -1
  186. bbot/test/test_step_2/module_tests/test_module_baddns.py +6 -6
  187. bbot/test/test_step_2/module_tests/test_module_baddns_direct.py +62 -0
  188. bbot/test/test_step_2/module_tests/test_module_bevigil.py +29 -2
  189. bbot/test/test_step_2/module_tests/test_module_binaryedge.py +4 -2
  190. bbot/test/test_step_2/module_tests/test_module_bucket_amazon.py +2 -2
  191. bbot/test/test_step_2/module_tests/test_module_bucket_azure.py +1 -1
  192. bbot/test/test_step_2/module_tests/test_module_bufferoverrun.py +35 -0
  193. bbot/test/test_step_2/module_tests/test_module_builtwith.py +2 -2
  194. bbot/test/test_step_2/module_tests/test_module_bypass403.py +1 -1
  195. bbot/test/test_step_2/module_tests/test_module_c99.py +126 -0
  196. bbot/test/test_step_2/module_tests/test_module_censys.py +4 -1
  197. bbot/test/test_step_2/module_tests/test_module_cloudcheck.py +4 -0
  198. bbot/test/test_step_2/module_tests/test_module_code_repository.py +11 -1
  199. bbot/test/test_step_2/module_tests/test_module_columbus.py +1 -1
  200. bbot/test/test_step_2/module_tests/test_module_credshed.py +3 -3
  201. bbot/test/test_step_2/module_tests/test_module_dastardly.py +2 -1
  202. bbot/test/test_step_2/module_tests/test_module_dehashed.py +2 -2
  203. bbot/test/test_step_2/module_tests/test_module_digitorus.py +1 -1
  204. bbot/test/test_step_2/module_tests/test_module_discord.py +1 -1
  205. bbot/test/test_step_2/module_tests/test_module_dnsbimi.py +103 -0
  206. bbot/test/test_step_2/module_tests/test_module_dnsbrute.py +9 -10
  207. bbot/test/test_step_2/module_tests/test_module_dnsbrute_mutations.py +1 -2
  208. bbot/test/test_step_2/module_tests/test_module_dnscommonsrv.py +1 -2
  209. bbot/test/test_step_2/module_tests/test_module_dnsdumpster.py +4 -4
  210. bbot/test/test_step_2/module_tests/test_module_dnstlsrpt.py +64 -0
  211. bbot/test/test_step_2/module_tests/test_module_dotnetnuke.py +0 -8
  212. bbot/test/test_step_2/module_tests/test_module_excavate.py +17 -37
  213. bbot/test/test_step_2/module_tests/test_module_extractous.py +54 -0
  214. bbot/test/test_step_2/module_tests/test_module_ffuf_shortnames.py +1 -1
  215. bbot/test/test_step_2/module_tests/test_module_filedownload.py +14 -14
  216. bbot/test/test_step_2/module_tests/test_module_git_clone.py +2 -2
  217. bbot/test/test_step_2/module_tests/test_module_github_org.py +19 -8
  218. bbot/test/test_step_2/module_tests/test_module_github_workflows.py +1 -1
  219. bbot/test/test_step_2/module_tests/test_module_gitlab.py +9 -4
  220. bbot/test/test_step_2/module_tests/test_module_google_playstore.py +83 -0
  221. bbot/test/test_step_2/module_tests/test_module_gowitness.py +4 -4
  222. bbot/test/test_step_2/module_tests/test_module_host_header.py +1 -1
  223. bbot/test/test_step_2/module_tests/test_module_http.py +4 -4
  224. bbot/test/test_step_2/module_tests/test_module_httpx.py +10 -8
  225. bbot/test/test_step_2/module_tests/test_module_hunterio.py +68 -4
  226. bbot/test/test_step_2/module_tests/test_module_jadx.py +55 -0
  227. bbot/test/test_step_2/module_tests/test_module_json.py +24 -11
  228. bbot/test/test_step_2/module_tests/test_module_leakix.py +7 -3
  229. bbot/test/test_step_2/module_tests/test_module_mysql.py +76 -0
  230. bbot/test/test_step_2/module_tests/test_module_myssl.py +1 -1
  231. bbot/test/test_step_2/module_tests/test_module_neo4j.py +1 -1
  232. bbot/test/test_step_2/module_tests/test_module_newsletters.py +6 -6
  233. bbot/test/test_step_2/module_tests/test_module_ntlm.py +7 -7
  234. bbot/test/test_step_2/module_tests/test_module_oauth.py +1 -1
  235. bbot/test/test_step_2/module_tests/test_module_otx.py +1 -1
  236. bbot/test/test_step_2/module_tests/test_module_paramminer_cookies.py +1 -2
  237. bbot/test/test_step_2/module_tests/test_module_paramminer_getparams.py +0 -6
  238. bbot/test/test_step_2/module_tests/test_module_paramminer_headers.py +2 -9
  239. bbot/test/test_step_2/module_tests/test_module_passivetotal.py +3 -1
  240. bbot/test/test_step_2/module_tests/test_module_portscan.py +9 -8
  241. bbot/test/test_step_2/module_tests/test_module_postgres.py +74 -0
  242. bbot/test/test_step_2/module_tests/test_module_postman.py +84 -253
  243. bbot/test/test_step_2/module_tests/test_module_postman_download.py +439 -0
  244. bbot/test/test_step_2/module_tests/test_module_rapiddns.py +93 -1
  245. bbot/test/test_step_2/module_tests/test_module_securitytxt.py +50 -0
  246. bbot/test/test_step_2/module_tests/test_module_shodan_dns.py +20 -1
  247. bbot/test/test_step_2/module_tests/test_module_sitedossier.py +2 -2
  248. bbot/test/test_step_2/module_tests/test_module_smuggler.py +1 -1
  249. bbot/test/test_step_2/module_tests/test_module_social.py +11 -1
  250. bbot/test/test_step_2/module_tests/test_module_speculate.py +2 -6
  251. bbot/test/test_step_2/module_tests/test_module_splunk.py +4 -4
  252. bbot/test/test_step_2/module_tests/test_module_sqlite.py +18 -0
  253. bbot/test/test_step_2/module_tests/test_module_sslcert.py +1 -1
  254. bbot/test/test_step_2/module_tests/test_module_stdout.py +5 -3
  255. bbot/test/test_step_2/module_tests/test_module_subdomaincenter.py +1 -1
  256. bbot/test/test_step_2/module_tests/test_module_subdomainradar.py +208 -0
  257. bbot/test/test_step_2/module_tests/test_module_subdomains.py +1 -1
  258. bbot/test/test_step_2/module_tests/test_module_teams.py +8 -6
  259. bbot/test/test_step_2/module_tests/test_module_telerik.py +1 -1
  260. bbot/test/test_step_2/module_tests/test_module_trufflehog.py +317 -11
  261. bbot/test/test_step_2/module_tests/test_module_wayback.py +1 -1
  262. bbot/test/test_step_2/template_tests/test_template_subdomain_enum.py +135 -0
  263. {bbot-2.0.1.4654rc0.dist-info → bbot-2.3.0.5397rc0.dist-info}/METADATA +48 -18
  264. bbot-2.3.0.5397rc0.dist-info/RECORD +421 -0
  265. {bbot-2.0.1.4654rc0.dist-info → bbot-2.3.0.5397rc0.dist-info}/WHEEL +1 -1
  266. bbot/modules/unstructured.py +0 -163
  267. bbot/test/test_step_2/module_tests/test_module_unstructured.py +0 -102
  268. bbot-2.0.1.4654rc0.dist-info/RECORD +0 -385
  269. {bbot-2.0.1.4654rc0.dist-info → bbot-2.3.0.5397rc0.dist-info}/LICENSE +0 -0
  270. {bbot-2.0.1.4654rc0.dist-info → bbot-2.3.0.5397rc0.dist-info}/entry_points.txt +0 -0
@@ -9,6 +9,7 @@ from .base import ModuleTestBase
9
9
 
10
10
 
11
11
  class TestTrufflehog(ModuleTestBase):
12
+ config_overrides = {"modules": {"postman_download": {"api_key": "asdf"}}}
12
13
  modules_overrides = [
13
14
  "github_org",
14
15
  "speculate",
@@ -16,6 +17,8 @@ class TestTrufflehog(ModuleTestBase):
16
17
  "github_workflows",
17
18
  "dockerhub",
18
19
  "docker_pull",
20
+ "postman",
21
+ "postman_download",
19
22
  "trufflehog",
20
23
  ]
21
24
 
@@ -23,6 +26,37 @@ class TestTrufflehog(ModuleTestBase):
23
26
 
24
27
  async def setup_before_prep(self, module_test):
25
28
  module_test.httpx_mock.add_response(url="https://api.github.com/zen")
29
+ module_test.httpx_mock.add_response(
30
+ url="https://api.getpostman.com/me",
31
+ json={
32
+ "user": {
33
+ "id": 000000,
34
+ "username": "test_key",
35
+ "email": "blacklanternsecurity@test.com",
36
+ "fullName": "Test Key",
37
+ "avatar": "",
38
+ "isPublic": True,
39
+ "teamId": 0,
40
+ "teamDomain": "",
41
+ "roles": ["user"],
42
+ },
43
+ "operations": [
44
+ {"name": "api_object_usage", "limit": 3, "usage": 0, "overage": 0},
45
+ {"name": "collection_run_limit", "limit": 25, "usage": 0, "overage": 0},
46
+ {"name": "file_storage_limit", "limit": 20, "usage": 0, "overage": 0},
47
+ {"name": "flow_count", "limit": 5, "usage": 0, "overage": 0},
48
+ {"name": "flow_requests", "limit": 5000, "usage": 0, "overage": 0},
49
+ {"name": "performance_test_limit", "limit": 25, "usage": 0, "overage": 0},
50
+ {"name": "postbot_calls", "limit": 50, "usage": 0, "overage": 0},
51
+ {"name": "reusable_packages", "limit": 3, "usage": 0, "overage": 0},
52
+ {"name": "test_data_retrieval", "limit": 1000, "usage": 0, "overage": 0},
53
+ {"name": "test_data_storage", "limit": 10, "usage": 0, "overage": 0},
54
+ {"name": "mock_usage", "limit": 1000, "usage": 0, "overage": 0},
55
+ {"name": "monitor_request_runs", "limit": 1000, "usage": 0, "overage": 0},
56
+ {"name": "api_usage", "limit": 1000, "usage": 0, "overage": 0},
57
+ ],
58
+ },
59
+ )
26
60
  module_test.httpx_mock.add_response(
27
61
  url="https://api.github.com/orgs/blacklanternsecurity",
28
62
  json={
@@ -812,6 +846,248 @@ class TestTrufflehog(ModuleTestBase):
812
846
  )
813
847
 
814
848
  async def setup_after_prep(self, module_test):
849
+ module_test.httpx_mock.add_response(
850
+ url="https://www.postman.com/_api/ws/proxy",
851
+ match_content=b'{"service": "search", "method": "POST", "path": "/search-all", "body": {"queryIndices": ["collaboration.workspace"], "queryText": "blacklanternsecurity", "size": 100, "from": 0, "clientTraceId": "", "requestOrigin": "srp", "mergeEntities": "true", "nonNestedRequests": "true", "domain": "public"}}',
852
+ json={
853
+ "data": [
854
+ {
855
+ "score": 611.41156,
856
+ "normalizedScore": 23,
857
+ "document": {
858
+ "watcherCount": 6,
859
+ "apiCount": 0,
860
+ "forkCount": 0,
861
+ "isblacklisted": "false",
862
+ "createdAt": "2021-06-15T14:03:51",
863
+ "publishertype": "team",
864
+ "publisherHandle": "blacklanternsecurity",
865
+ "id": "11498add-357d-4bc5-a008-0a2d44fb8829",
866
+ "slug": "bbot-public",
867
+ "updatedAt": "2024-07-30T11:00:35",
868
+ "entityType": "workspace",
869
+ "visibilityStatus": "public",
870
+ "forkcount": "0",
871
+ "tags": [],
872
+ "createdat": "2021-06-15T14:03:51",
873
+ "forkLabel": "",
874
+ "publisherName": "blacklanternsecurity",
875
+ "name": "BlackLanternSecurity BBOT [Public]",
876
+ "dependencyCount": 7,
877
+ "collectionCount": 6,
878
+ "warehouse__updated_at": "2024-07-30 11:00:00",
879
+ "privateNetworkFolders": [],
880
+ "isPublisherVerified": False,
881
+ "publisherType": "team",
882
+ "curatedInList": [],
883
+ "creatorId": "6900157",
884
+ "description": "",
885
+ "forklabel": "",
886
+ "publisherId": "299401",
887
+ "publisherLogo": "",
888
+ "popularity": 5,
889
+ "isPublic": True,
890
+ "categories": [],
891
+ "universaltags": "",
892
+ "views": 5788,
893
+ "summary": "BLS public workspaces.",
894
+ "memberCount": 2,
895
+ "isBlacklisted": False,
896
+ "publisherid": "299401",
897
+ "isPrivateNetworkEntity": False,
898
+ "isDomainNonTrivial": True,
899
+ "privateNetworkMeta": "",
900
+ "updatedat": "2021-10-20T16:19:29",
901
+ "documentType": "workspace",
902
+ },
903
+ "highlight": {"summary": "<b>BLS</b> BBOT api test."},
904
+ },
905
+ ],
906
+ "meta": {
907
+ "queryText": "blacklanternsecurity",
908
+ "total": {
909
+ "collection": 0,
910
+ "request": 0,
911
+ "workspace": 1,
912
+ "api": 0,
913
+ "team": 0,
914
+ "user": 0,
915
+ "flow": 0,
916
+ "apiDefinition": 0,
917
+ "privateNetworkFolder": 0,
918
+ },
919
+ "state": "AQ4",
920
+ "spellCorrection": {"count": {"all": 1, "workspace": 1}, "correctedQueryText": None},
921
+ "featureFlags": {
922
+ "enabledPublicResultCuration": True,
923
+ "boostByPopularity": True,
924
+ "reRankPostNormalization": True,
925
+ "enableUrlBarHostNameSearch": True,
926
+ },
927
+ },
928
+ },
929
+ )
930
+ module_test.httpx_mock.add_response(
931
+ url="https://www.postman.com/_api/ws/proxy",
932
+ match_content=b'{"service": "workspaces", "method": "GET", "path": "/workspaces?handle=blacklanternsecurity&slug=bbot-public"}',
933
+ json={
934
+ "meta": {"model": "workspace", "action": "find", "nextCursor": ""},
935
+ "data": [
936
+ {
937
+ "id": "3a7e4bdc-7ff7-4dd4-8eaa-61ddce1c3d1b",
938
+ "name": "BlackLanternSecurity BBOT [Public]",
939
+ "description": None,
940
+ "summary": "BLS public workspaces.",
941
+ "createdBy": "299401",
942
+ "updatedBy": "299401",
943
+ "team": None,
944
+ "createdAt": "2021-10-20T16:19:29",
945
+ "updatedAt": "2021-10-20T16:19:29",
946
+ "visibilityStatus": "public",
947
+ "profileInfo": {
948
+ "slug": "bbot-public",
949
+ "profileType": "team",
950
+ "profileId": "000000",
951
+ "publicHandle": "https://www.postman.com/blacklanternsecurity",
952
+ "publicImageURL": "",
953
+ "publicName": "BlackLanternSecurity",
954
+ "isVerified": False,
955
+ },
956
+ }
957
+ ],
958
+ },
959
+ )
960
+ module_test.httpx_mock.add_response(
961
+ url="https://api.getpostman.com/workspaces/3a7e4bdc-7ff7-4dd4-8eaa-61ddce1c3d1b",
962
+ json={
963
+ "workspace": {
964
+ "id": "3a7e4bdc-7ff7-4dd4-8eaa-61ddce1c3d1b",
965
+ "name": "BlackLanternSecurity BBOT [Public]",
966
+ "type": "personal",
967
+ "description": None,
968
+ "visibility": "public",
969
+ "createdBy": "00000000",
970
+ "updatedBy": "00000000",
971
+ "createdAt": "2021-11-17T06:09:01.000Z",
972
+ "updatedAt": "2021-11-17T08:57:16.000Z",
973
+ "collections": [
974
+ {
975
+ "id": "2aab9fd0-3715-4abe-8bb0-8cb0264d023f",
976
+ "name": "BBOT Public",
977
+ "uid": "10197090-2aab9fd0-3715-4abe-8bb0-8cb0264d023f",
978
+ },
979
+ ],
980
+ "environments": [
981
+ {
982
+ "id": "f770f816-9c6a-40f7-bde3-c0855d2a1089",
983
+ "name": "BBOT Test",
984
+ "uid": "10197090-f770f816-9c6a-40f7-bde3-c0855d2a1089",
985
+ }
986
+ ],
987
+ "apis": [],
988
+ }
989
+ },
990
+ )
991
+ module_test.httpx_mock.add_response(
992
+ url="https://www.postman.com/_api/workspace/3a7e4bdc-7ff7-4dd4-8eaa-61ddce1c3d1b/globals",
993
+ json={
994
+ "model_id": "8be7574b-219f-49e0-8d25-da447a882e4e",
995
+ "meta": {"model": "globals", "action": "find"},
996
+ "data": {
997
+ "workspace": "3a7e4bdc-7ff7-4dd4-8eaa-61ddce1c3d1b",
998
+ "lastUpdatedBy": "00000000",
999
+ "lastRevision": 1637239113000,
1000
+ "id": "8be7574b-219f-49e0-8d25-da447a882e4e",
1001
+ "values": [
1002
+ {
1003
+ "key": "endpoint_url",
1004
+ "value": "https://api.blacklanternsecurity.com/",
1005
+ "enabled": True,
1006
+ },
1007
+ ],
1008
+ "createdAt": "2021-11-17T06:09:01.000Z",
1009
+ "updatedAt": "2021-11-18T12:38:33.000Z",
1010
+ },
1011
+ },
1012
+ )
1013
+ module_test.httpx_mock.add_response(
1014
+ url="https://api.getpostman.com/environments/10197090-f770f816-9c6a-40f7-bde3-c0855d2a1089",
1015
+ json={
1016
+ "environment": {
1017
+ "id": "f770f816-9c6a-40f7-bde3-c0855d2a1089",
1018
+ "name": "BBOT Test",
1019
+ "owner": "00000000",
1020
+ "createdAt": "2021-11-17T06:29:54.000Z",
1021
+ "updatedAt": "2021-11-23T07:06:53.000Z",
1022
+ "values": [
1023
+ {
1024
+ "key": "temp_session_endpoint",
1025
+ "value": "https://api.blacklanternsecurity.com/",
1026
+ "enabled": True,
1027
+ },
1028
+ ],
1029
+ "isPublic": True,
1030
+ }
1031
+ },
1032
+ )
1033
+ module_test.httpx_mock.add_response(
1034
+ url="https://api.getpostman.com/collections/10197090-2aab9fd0-3715-4abe-8bb0-8cb0264d023f",
1035
+ json={
1036
+ "collection": {
1037
+ "info": {
1038
+ "_postman_id": "62b91565-d2e2-4bcd-8248-4dba2e3452f0",
1039
+ "name": "BBOT Public",
1040
+ "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
1041
+ "updatedAt": "2021-11-17T07:13:16.000Z",
1042
+ "createdAt": "2021-11-17T07:13:15.000Z",
1043
+ "lastUpdatedBy": "00000000",
1044
+ "uid": "172983-62b91565-d2e2-4bcd-8248-4dba2e3452f0",
1045
+ },
1046
+ "item": [
1047
+ {
1048
+ "name": "Generate API Session",
1049
+ "id": "c1bac38c-dfc9-4cc0-9c19-828cbc8543b1",
1050
+ "protocolProfileBehavior": {"disableBodyPruning": True},
1051
+ "request": {
1052
+ "method": "POST",
1053
+ "header": [{"key": "Content-Type", "value": "application/json"}],
1054
+ "body": {
1055
+ "mode": "raw",
1056
+ "raw": '{"username": "test", "password": "Test"}',
1057
+ },
1058
+ "url": {
1059
+ "raw": "https://admin:admin@the-internet.herokuapp.com/basic_auth",
1060
+ "host": ["https://admin:admin@the-internet.herokuapp.com/basic_auth"],
1061
+ },
1062
+ "description": "",
1063
+ },
1064
+ "response": [],
1065
+ "uid": "10197090-c1bac38c-dfc9-4cc0-9c19-828cbc8543b1",
1066
+ },
1067
+ {
1068
+ "name": "Generate API Session",
1069
+ "id": "c1bac38c-dfc9-4cc0-9c19-828cbc8543b1",
1070
+ "protocolProfileBehavior": {"disableBodyPruning": True},
1071
+ "request": {
1072
+ "method": "POST",
1073
+ "header": [{"key": "Content-Type", "value": "application/json"}],
1074
+ "body": {
1075
+ "mode": "raw",
1076
+ "raw": '{"username": "test", "password": "Test"}',
1077
+ },
1078
+ "url": {
1079
+ "raw": "https://admin:admin@internal.host.com",
1080
+ "host": ["https://admin:admin@internal.host.com"],
1081
+ },
1082
+ "description": "",
1083
+ },
1084
+ "response": [],
1085
+ "uid": "10197090-c1bac38c-dfc9-4cc0-9c19-828cbc8543b1",
1086
+ },
1087
+ ],
1088
+ }
1089
+ },
1090
+ )
815
1091
  temp_path = Path("/tmp/.bbot_test")
816
1092
  temp_repo_path = temp_path / "test_keys"
817
1093
  shutil.rmtree(temp_repo_path, ignore_errors=True)
@@ -849,21 +1125,26 @@ class TestTrufflehog(ModuleTestBase):
849
1125
  e
850
1126
  for e in events
851
1127
  if e.type == "VULNERABILITY"
852
- and (e.data["host"] == "hub.docker.com" or e.data["host"] == "github.com")
1128
+ and (
1129
+ e.data["host"] == "hub.docker.com"
1130
+ or e.data["host"] == "github.com"
1131
+ or e.data["host"] == "www.postman.com"
1132
+ )
853
1133
  and "Verified Secret Found." in e.data["description"]
854
1134
  and "Raw result: [https://admin:admin@the-internet.herokuapp.com]" in e.data["description"]
855
1135
  and "RawV2 result: [https://admin:admin@the-internet.herokuapp.com/basic_auth]" in e.data["description"]
856
1136
  ]
857
- assert 3 == len(vuln_events), "Failed to find secret in events"
1137
+ # Trufflehog should find 4 verifiable secrets, 1 from the github, 1 from the workflow log, 1 from the docker image and 1 from the postman.
1138
+ assert 4 == len(vuln_events), "Failed to find secret in events"
858
1139
  github_repo_event = [e for e in vuln_events if "test_keys" in e.data["description"]][0].parent
859
1140
  folder = Path(github_repo_event.data["path"])
860
1141
  assert folder.is_dir(), "Destination folder doesn't exist"
861
1142
  with open(folder / "keys.txt") as f:
862
1143
  content = f.read()
863
1144
  assert content == self.file_content, "File content doesn't match"
864
- filesystem_events = [e.parent for e in vuln_events if "bbot" in e.data["description"]]
865
- assert len(filesystem_events) == 3
866
- assert all([e.type == "FILESYSTEM" for e in filesystem_events])
1145
+ filesystem_events = [e.parent for e in vuln_events]
1146
+ assert len(filesystem_events) == 4
1147
+ assert all(e.type == "FILESYSTEM" for e in filesystem_events)
867
1148
  assert 1 == len(
868
1149
  [
869
1150
  e
@@ -887,30 +1168,45 @@ class TestTrufflehog(ModuleTestBase):
887
1168
  and Path(e.data["path"]).is_file()
888
1169
  ]
889
1170
  ), "Docker image file does not exist"
1171
+ assert 1 == len(
1172
+ [
1173
+ e
1174
+ for e in filesystem_events
1175
+ if e.data["path"].endswith(
1176
+ "/postman_workspaces/BlackLanternSecurity BBOT [Public]/3a7e4bdc-7ff7-4dd4-8eaa-61ddce1c3d1b.zip"
1177
+ )
1178
+ and Path(e.data["path"]).is_file()
1179
+ ]
1180
+ ), "Failed to find blacklanternsecurity postman workspace"
890
1181
 
891
1182
 
892
1183
  class TestTrufflehog_NonVerified(TestTrufflehog):
893
- config_overrides = {"modules": {"trufflehog": {"only_verified": False}}}
1184
+ config_overrides = {"modules": {"trufflehog": {"only_verified": False}, "postman_download": {"api_key": "asdf"}}}
894
1185
 
895
1186
  def check(self, module_test, events):
896
1187
  finding_events = [
897
1188
  e
898
1189
  for e in events
899
1190
  if e.type == e.type == "FINDING"
900
- and (e.data["host"] == "hub.docker.com" or e.data["host"] == "github.com")
1191
+ and (
1192
+ e.data["host"] == "hub.docker.com"
1193
+ or e.data["host"] == "github.com"
1194
+ or e.data["host"] == "www.postman.com"
1195
+ )
901
1196
  and "Potential Secret Found." in e.data["description"]
902
1197
  and "Raw result: [https://admin:admin@internal.host.com]" in e.data["description"]
903
1198
  ]
904
- assert 3 == len(finding_events), "Failed to find secret in events"
1199
+ # Trufflehog should find 4 unverifiable secrets, 1 from the github, 1 from the workflow log, 1 from the docker image and 1 from the postman.
1200
+ assert 4 == len(finding_events), "Failed to find secret in events"
905
1201
  github_repo_event = [e for e in finding_events if "test_keys" in e.data["description"]][0].parent
906
1202
  folder = Path(github_repo_event.data["path"])
907
1203
  assert folder.is_dir(), "Destination folder doesn't exist"
908
1204
  with open(folder / "keys.txt") as f:
909
1205
  content = f.read()
910
1206
  assert content == self.file_content, "File content doesn't match"
911
- filesystem_events = [e.parent for e in finding_events if "bbot" in e.data["description"]]
912
- assert len(filesystem_events) == 3
913
- assert all([e.type == "FILESYSTEM" for e in filesystem_events])
1207
+ filesystem_events = [e.parent for e in finding_events]
1208
+ assert len(filesystem_events) == 4
1209
+ assert all(e.type == "FILESYSTEM" for e in filesystem_events)
914
1210
  assert 1 == len(
915
1211
  [
916
1212
  e
@@ -934,3 +1230,13 @@ class TestTrufflehog_NonVerified(TestTrufflehog):
934
1230
  and Path(e.data["path"]).is_file()
935
1231
  ]
936
1232
  ), "Docker image file does not exist"
1233
+ assert 1 == len(
1234
+ [
1235
+ e
1236
+ for e in filesystem_events
1237
+ if e.data["path"].endswith(
1238
+ "/postman_workspaces/BlackLanternSecurity BBOT [Public]/3a7e4bdc-7ff7-4dd4-8eaa-61ddce1c3d1b.zip"
1239
+ )
1240
+ and Path(e.data["path"]).is_file()
1241
+ ]
1242
+ ), "Failed to find blacklanternsecurity postman workspace"
@@ -4,7 +4,7 @@ from .base import ModuleTestBase
4
4
  class TestWayback(ModuleTestBase):
5
5
  async def setup_after_prep(self, module_test):
6
6
  module_test.httpx_mock.add_response(
7
- url=f"http://web.archive.org/cdx/search/cdx?url=blacklanternsecurity.com&matchType=domain&output=json&fl=original&collapse=original",
7
+ url="http://web.archive.org/cdx/search/cdx?url=blacklanternsecurity.com&matchType=domain&output=json&fl=original&collapse=original",
8
8
  json=[["original"], ["http://asdf.blacklanternsecurity.com"]],
9
9
  )
10
10
 
@@ -84,3 +84,138 @@ class TestSubdomainEnumLowestParent(TestSubdomainEnumHighestParent):
84
84
  "asdf.www.blacklanternsecurity.com",
85
85
  "www.blacklanternsecurity.com",
86
86
  }
87
+
88
+
89
+ class TestSubdomainEnumWildcardBaseline(ModuleTestBase):
90
+ # oh walmart.cn why are you like this
91
+ targets = ["www.walmart.cn"]
92
+ whitelist = ["walmart.cn"]
93
+ modules_overrides = []
94
+ config_overrides = {"dns": {"minimal": False}, "scope": {"report_distance": 10}, "omit_event_types": []}
95
+ dedup_strategy = "highest_parent"
96
+
97
+ dns_mock_data = {
98
+ "walmart.cn": {"A": ["127.0.0.1"]},
99
+ "www.walmart.cn": {"A": ["127.0.0.1"]},
100
+ "test.walmart.cn": {"A": ["127.0.0.1"]},
101
+ }
102
+
103
+ async def setup_before_prep(self, module_test):
104
+ await module_test.mock_dns(self.dns_mock_data)
105
+ self.queries = []
106
+
107
+ async def mock_query(query):
108
+ self.queries.append(query)
109
+ return ["walmart.cn", "www.walmart.cn", "test.walmart.cn", "asdf.walmart.cn"]
110
+
111
+ # load subdomain enum template as module
112
+ from bbot.modules.templates.subdomain_enum import subdomain_enum
113
+
114
+ subdomain_enum_module = subdomain_enum(module_test.scan)
115
+
116
+ subdomain_enum_module.query = mock_query
117
+ subdomain_enum_module._name = "subdomain_enum"
118
+ subdomain_enum_module.dedup_strategy = self.dedup_strategy
119
+ module_test.scan.modules["subdomain_enum"] = subdomain_enum_module
120
+
121
+ def check(self, module_test, events):
122
+ assert self.queries == ["walmart.cn"]
123
+ assert len(events) == 7
124
+ assert 2 == len(
125
+ [
126
+ e
127
+ for e in events
128
+ if e.type == "IP_ADDRESS" and e.data == "127.0.0.1" and str(e.module) == "A" and e.scope_distance == 1
129
+ ]
130
+ )
131
+ assert 1 == len(
132
+ [
133
+ e
134
+ for e in events
135
+ if e.type == "DNS_NAME"
136
+ and e.data == "www.walmart.cn"
137
+ and str(e.module) == "TARGET"
138
+ and e.scope_distance == 0
139
+ ]
140
+ )
141
+ assert 1 == len(
142
+ [
143
+ e
144
+ for e in events
145
+ if e.type == "DNS_NAME"
146
+ and e.data == "test.walmart.cn"
147
+ and str(e.module) == "subdomain_enum"
148
+ and e.scope_distance == 0
149
+ ]
150
+ )
151
+ assert 1 == len(
152
+ [
153
+ e
154
+ for e in events
155
+ if e.type == "DNS_NAME_UNRESOLVED"
156
+ and e.data == "asdf.walmart.cn"
157
+ and str(e.module) == "subdomain_enum"
158
+ and e.scope_distance == 0
159
+ ]
160
+ )
161
+
162
+
163
+ class TestSubdomainEnumWildcardDefense(TestSubdomainEnumWildcardBaseline):
164
+ # oh walmart.cn why are you like this
165
+ targets = ["walmart.cn"]
166
+ modules_overrides = []
167
+ config_overrides = {"dns": {"minimal": False}, "scope": {"report_distance": 10}}
168
+ dedup_strategy = "highest_parent"
169
+
170
+ dns_mock_data = {
171
+ "walmart.cn": {"A": ["127.0.0.2"], "TXT": ["asdf.walmart.cn"]},
172
+ }
173
+
174
+ async def setup_after_prep(self, module_test):
175
+ # simulate wildcard
176
+ custom_lookup = """
177
+ def custom_lookup(query, rdtype):
178
+ import random
179
+ if rdtype == "A" and query.endswith(".walmart.cn"):
180
+ ip = ".".join([str(random.randint(0,256)) for _ in range(4)])
181
+ return {ip}
182
+ """
183
+ await module_test.mock_dns(self.dns_mock_data, custom_lookup_fn=custom_lookup)
184
+
185
+ def check(self, module_test, events):
186
+ # no subdomain enum should happen on this domain!
187
+ assert self.queries == []
188
+ assert len(events) == 7
189
+ assert 2 == len(
190
+ [e for e in events if e.type == "IP_ADDRESS" and str(e.module) == "A" and e.scope_distance == 1]
191
+ )
192
+ assert 1 == len(
193
+ [
194
+ e
195
+ for e in events
196
+ if e.type == "DNS_NAME"
197
+ and e.data == "walmart.cn"
198
+ and str(e.module) == "TARGET"
199
+ and e.scope_distance == 0
200
+ ]
201
+ )
202
+ assert 1 == len(
203
+ [
204
+ e
205
+ for e in events
206
+ if e.type == "DNS_NAME"
207
+ and e.data == "asdf.walmart.cn"
208
+ and str(e.module) == "TXT"
209
+ and e.scope_distance == 0
210
+ and "wildcard-possible" in e.tags
211
+ and "a-wildcard-possible" in e.tags
212
+ ]
213
+ )
214
+ assert 1 == len(
215
+ [
216
+ e
217
+ for e in events
218
+ if e.type == "RAW_DNS_RECORD"
219
+ and e.data == {"host": "walmart.cn", "type": "TXT", "answer": '"asdf.walmart.cn"'}
220
+ ]
221
+ )