bbot 2.0.1.4720rc0__py3-none-any.whl → 2.3.0.5401rc0__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 (278) 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 -4
  6. bbot/core/engine.py +9 -8
  7. bbot/core/event/base.py +131 -52
  8. bbot/core/helpers/bloom.py +10 -3
  9. bbot/core/helpers/command.py +8 -7
  10. bbot/core/helpers/depsinstaller/installer.py +31 -13
  11. bbot/core/helpers/diff.py +10 -10
  12. bbot/core/helpers/dns/brute.py +7 -4
  13. bbot/core/helpers/dns/dns.py +1 -2
  14. bbot/core/helpers/dns/engine.py +4 -6
  15. bbot/core/helpers/dns/helpers.py +2 -2
  16. bbot/core/helpers/dns/mock.py +0 -1
  17. bbot/core/helpers/files.py +1 -1
  18. bbot/core/helpers/helper.py +7 -4
  19. bbot/core/helpers/interactsh.py +3 -3
  20. bbot/core/helpers/libmagic.py +65 -0
  21. bbot/core/helpers/misc.py +65 -22
  22. bbot/core/helpers/names_generator.py +17 -3
  23. bbot/core/helpers/process.py +0 -20
  24. bbot/core/helpers/regex.py +1 -1
  25. bbot/core/helpers/regexes.py +12 -6
  26. bbot/core/helpers/validators.py +1 -2
  27. bbot/core/helpers/web/client.py +1 -1
  28. bbot/core/helpers/web/engine.py +1 -2
  29. bbot/core/helpers/web/web.py +4 -114
  30. bbot/core/helpers/wordcloud.py +5 -5
  31. bbot/core/modules.py +36 -27
  32. bbot/core/multiprocess.py +58 -0
  33. bbot/core/shared_deps.py +46 -3
  34. bbot/db/sql/models.py +147 -0
  35. bbot/defaults.yml +12 -10
  36. bbot/modules/anubisdb.py +2 -2
  37. bbot/modules/apkpure.py +63 -0
  38. bbot/modules/azure_tenant.py +2 -2
  39. bbot/modules/baddns.py +35 -19
  40. bbot/modules/baddns_direct.py +92 -0
  41. bbot/modules/baddns_zone.py +3 -8
  42. bbot/modules/badsecrets.py +4 -3
  43. bbot/modules/base.py +195 -51
  44. bbot/modules/bevigil.py +7 -7
  45. bbot/modules/binaryedge.py +7 -4
  46. bbot/modules/bufferoverrun.py +47 -0
  47. bbot/modules/builtwith.py +6 -10
  48. bbot/modules/bypass403.py +5 -5
  49. bbot/modules/c99.py +10 -7
  50. bbot/modules/censys.py +9 -13
  51. bbot/modules/certspotter.py +5 -3
  52. bbot/modules/chaos.py +9 -7
  53. bbot/modules/code_repository.py +1 -0
  54. bbot/modules/columbus.py +3 -3
  55. bbot/modules/crt.py +5 -3
  56. bbot/modules/deadly/dastardly.py +1 -1
  57. bbot/modules/deadly/ffuf.py +9 -9
  58. bbot/modules/deadly/nuclei.py +3 -3
  59. bbot/modules/deadly/vhost.py +4 -3
  60. bbot/modules/dehashed.py +1 -1
  61. bbot/modules/digitorus.py +1 -1
  62. bbot/modules/dnsbimi.py +145 -0
  63. bbot/modules/dnscaa.py +3 -3
  64. bbot/modules/dnsdumpster.py +4 -4
  65. bbot/modules/dnstlsrpt.py +144 -0
  66. bbot/modules/docker_pull.py +7 -5
  67. bbot/modules/dockerhub.py +2 -2
  68. bbot/modules/dotnetnuke.py +20 -21
  69. bbot/modules/emailformat.py +1 -1
  70. bbot/modules/extractous.py +122 -0
  71. bbot/modules/filedownload.py +9 -7
  72. bbot/modules/fullhunt.py +7 -4
  73. bbot/modules/generic_ssrf.py +5 -5
  74. bbot/modules/github_codesearch.py +3 -2
  75. bbot/modules/github_org.py +4 -4
  76. bbot/modules/github_workflows.py +4 -4
  77. bbot/modules/gitlab.py +2 -5
  78. bbot/modules/google_playstore.py +93 -0
  79. bbot/modules/gowitness.py +48 -50
  80. bbot/modules/hackertarget.py +5 -3
  81. bbot/modules/host_header.py +5 -5
  82. bbot/modules/httpx.py +1 -4
  83. bbot/modules/hunterio.py +3 -9
  84. bbot/modules/iis_shortnames.py +19 -30
  85. bbot/modules/internal/cloudcheck.py +29 -12
  86. bbot/modules/internal/dnsresolve.py +22 -22
  87. bbot/modules/internal/excavate.py +97 -59
  88. bbot/modules/internal/speculate.py +41 -32
  89. bbot/modules/internetdb.py +4 -2
  90. bbot/modules/ip2location.py +3 -5
  91. bbot/modules/ipneighbor.py +1 -1
  92. bbot/modules/ipstack.py +3 -8
  93. bbot/modules/jadx.py +87 -0
  94. bbot/modules/leakix.py +11 -10
  95. bbot/modules/myssl.py +2 -2
  96. bbot/modules/newsletters.py +2 -2
  97. bbot/modules/otx.py +5 -3
  98. bbot/modules/output/asset_inventory.py +7 -7
  99. bbot/modules/output/base.py +1 -1
  100. bbot/modules/output/csv.py +1 -1
  101. bbot/modules/output/http.py +20 -14
  102. bbot/modules/output/mysql.py +51 -0
  103. bbot/modules/output/neo4j.py +7 -2
  104. bbot/modules/output/postgres.py +49 -0
  105. bbot/modules/output/slack.py +0 -1
  106. bbot/modules/output/sqlite.py +29 -0
  107. bbot/modules/output/stdout.py +2 -2
  108. bbot/modules/output/teams.py +107 -6
  109. bbot/modules/paramminer_headers.py +8 -11
  110. bbot/modules/passivetotal.py +13 -13
  111. bbot/modules/portscan.py +32 -6
  112. bbot/modules/postman.py +50 -126
  113. bbot/modules/postman_download.py +220 -0
  114. bbot/modules/rapiddns.py +3 -8
  115. bbot/modules/report/asn.py +18 -11
  116. bbot/modules/robots.py +3 -3
  117. bbot/modules/securitytrails.py +7 -10
  118. bbot/modules/securitytxt.py +1 -1
  119. bbot/modules/shodan_dns.py +7 -9
  120. bbot/modules/sitedossier.py +1 -1
  121. bbot/modules/skymem.py +2 -2
  122. bbot/modules/social.py +2 -1
  123. bbot/modules/subdomaincenter.py +1 -1
  124. bbot/modules/subdomainradar.py +160 -0
  125. bbot/modules/telerik.py +8 -8
  126. bbot/modules/templates/bucket.py +1 -1
  127. bbot/modules/templates/github.py +22 -14
  128. bbot/modules/templates/postman.py +21 -0
  129. bbot/modules/templates/shodan.py +14 -13
  130. bbot/modules/templates/sql.py +95 -0
  131. bbot/modules/templates/subdomain_enum.py +51 -16
  132. bbot/modules/templates/webhook.py +2 -4
  133. bbot/modules/trickest.py +8 -37
  134. bbot/modules/trufflehog.py +10 -12
  135. bbot/modules/url_manipulation.py +3 -3
  136. bbot/modules/urlscan.py +1 -1
  137. bbot/modules/viewdns.py +1 -1
  138. bbot/modules/virustotal.py +8 -30
  139. bbot/modules/wafw00f.py +1 -1
  140. bbot/modules/wayback.py +1 -1
  141. bbot/modules/wpscan.py +17 -11
  142. bbot/modules/zoomeye.py +11 -6
  143. bbot/presets/baddns-thorough.yml +12 -0
  144. bbot/presets/fast.yml +16 -0
  145. bbot/presets/kitchen-sink.yml +1 -2
  146. bbot/presets/spider.yml +4 -0
  147. bbot/presets/subdomain-enum.yml +7 -7
  148. bbot/presets/web/dotnet-audit.yml +0 -1
  149. bbot/scanner/manager.py +5 -16
  150. bbot/scanner/preset/args.py +46 -26
  151. bbot/scanner/preset/environ.py +7 -2
  152. bbot/scanner/preset/path.py +7 -4
  153. bbot/scanner/preset/preset.py +36 -23
  154. bbot/scanner/scanner.py +172 -62
  155. bbot/scanner/target.py +236 -434
  156. bbot/scripts/docs.py +1 -1
  157. bbot/test/bbot_fixtures.py +13 -3
  158. bbot/test/conftest.py +132 -100
  159. bbot/test/fastapi_test.py +17 -0
  160. bbot/test/owasp_mastg.apk +0 -0
  161. bbot/test/run_tests.sh +4 -4
  162. bbot/test/test.conf +2 -0
  163. bbot/test/test_step_1/test__module__tests.py +0 -1
  164. bbot/test/test_step_1/test_bbot_fastapi.py +79 -0
  165. bbot/test/test_step_1/test_bloom_filter.py +2 -1
  166. bbot/test/test_step_1/test_cli.py +138 -64
  167. bbot/test/test_step_1/test_dns.py +61 -27
  168. bbot/test/test_step_1/test_engine.py +17 -19
  169. bbot/test/test_step_1/test_events.py +183 -30
  170. bbot/test/test_step_1/test_helpers.py +64 -29
  171. bbot/test/test_step_1/test_manager_deduplication.py +1 -1
  172. bbot/test/test_step_1/test_manager_scope_accuracy.py +333 -330
  173. bbot/test/test_step_1/test_modules_basic.py +68 -70
  174. bbot/test/test_step_1/test_presets.py +183 -100
  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 +4 -3
  179. bbot/test/test_step_1/test_target.py +242 -145
  180. bbot/test/test_step_1/test_web.py +14 -10
  181. bbot/test/test_step_2/module_tests/base.py +15 -7
  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 +28 -48
  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 -6
  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 +22 -9
  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 +16 -16
  233. bbot/test/test_step_2/module_tests/test_module_ntlm.py +8 -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_pgp.py +2 -2
  241. bbot/test/test_step_2/module_tests/test_module_portscan.py +9 -8
  242. bbot/test/test_step_2/module_tests/test_module_postgres.py +74 -0
  243. bbot/test/test_step_2/module_tests/test_module_postman.py +84 -253
  244. bbot/test/test_step_2/module_tests/test_module_postman_download.py +439 -0
  245. bbot/test/test_step_2/module_tests/test_module_rapiddns.py +93 -1
  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 +14 -14
  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 +4 -8
  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 -14
  261. bbot/test/test_step_2/module_tests/test_module_viewdns.py +1 -1
  262. bbot/test/test_step_2/module_tests/test_module_wayback.py +1 -1
  263. bbot/test/test_step_2/template_tests/test_template_subdomain_enum.py +2 -2
  264. bbot/wordlists/devops_mutations.txt +1 -1
  265. bbot/wordlists/ffuf_shortname_candidates.txt +1 -1
  266. bbot/wordlists/nameservers.txt +1 -1
  267. bbot/wordlists/paramminer_headers.txt +1 -1
  268. bbot/wordlists/paramminer_parameters.txt +1 -1
  269. bbot/wordlists/raft-small-extensions-lowercase_CLEANED.txt +1 -1
  270. bbot/wordlists/valid_url_schemes.txt +1 -1
  271. {bbot-2.0.1.4720rc0.dist-info → bbot-2.3.0.5401rc0.dist-info}/METADATA +48 -18
  272. bbot-2.3.0.5401rc0.dist-info/RECORD +421 -0
  273. {bbot-2.0.1.4720rc0.dist-info → bbot-2.3.0.5401rc0.dist-info}/WHEEL +1 -1
  274. bbot/modules/unstructured.py +0 -163
  275. bbot/test/test_step_2/module_tests/test_module_unstructured.py +0 -102
  276. bbot-2.0.1.4720rc0.dist-info/RECORD +0 -387
  277. {bbot-2.0.1.4720rc0.dist-info → bbot-2.3.0.5401rc0.dist-info}/LICENSE +0 -0
  278. {bbot-2.0.1.4720rc0.dist-info → bbot-2.3.0.5401rc0.dist-info}/entry_points.txt +0 -0
@@ -15,37 +15,15 @@ class virustotal(subdomain_enum_apikey):
15
15
  options_desc = {"api_key": "VirusTotal API Key"}
16
16
 
17
17
  base_url = "https://www.virustotal.com/api/v3"
18
+ api_page_iter_kwargs = {"json": False, "next_key": lambda r: r.json().get("links", {}).get("next", "")}
18
19
 
19
- async def setup(self):
20
- self.api_key = self.config.get("api_key", "")
21
- self.headers = {"x-apikey": self.api_key}
22
- return await super().setup()
20
+ def make_url(self, query):
21
+ return f"{self.base_url}/domains/{self.helpers.quote(query)}/subdomains"
23
22
 
24
- async def ping(self):
25
- # virustotal does not have a ping function
26
- return
23
+ def prepare_api_request(self, url, kwargs):
24
+ kwargs["headers"]["x-apikey"] = self.api_key
25
+ return url, kwargs
27
26
 
28
- def parse_results(self, r, query):
29
- results = set()
27
+ async def parse_results(self, r, query):
30
28
  text = getattr(r, "text", "")
31
- for match in self.helpers.regexes.dns_name_regex.findall(text):
32
- match = match.lower()
33
- if match.endswith(query):
34
- results.add(match)
35
- return results
36
-
37
- async def query(self, query):
38
- results = set()
39
- url = f"{self.base_url}/domains/{self.helpers.quote(query)}/subdomains"
40
- agen = self.helpers.api_page_iter(
41
- url, json=False, headers=self.headers, next_key=lambda r: r.json().get("links", {}).get("next", "")
42
- )
43
- try:
44
- async for response in agen:
45
- r = self.parse_results(response, query)
46
- if not r:
47
- break
48
- results.update(r)
49
- finally:
50
- agen.aclose()
51
- return results
29
+ return await self.scan.extract_in_scope_hostnames(text)
bbot/modules/wafw00f.py CHANGED
@@ -52,7 +52,7 @@ class wafw00f(BaseModule):
52
52
  context=f"{{module}} scanned {url} and identified {{event.type}}: {waf}",
53
53
  )
54
54
  else:
55
- if self.config.get("generic_detect") == True:
55
+ if self.config.get("generic_detect") is True:
56
56
  generic = await self.helpers.run_in_executor(WW.genericdetect)
57
57
  if generic:
58
58
  waf = "generic detection"
bbot/modules/wayback.py CHANGED
@@ -10,7 +10,7 @@ class wayback(subdomain_enum):
10
10
  meta = {
11
11
  "description": "Query archive.org's API for subdomains",
12
12
  "created_date": "2022-04-01",
13
- "author": "@pmueller",
13
+ "author": "@liquidsec",
14
14
  }
15
15
  options = {"urls": False, "garbage_threshold": 10}
16
16
  options_desc = {
bbot/modules/wpscan.py CHANGED
@@ -14,26 +14,26 @@ class wpscan(BaseModule):
14
14
 
15
15
  options = {
16
16
  "api_key": "",
17
- "enumerate": "vp,vt,tt,cb,dbe,u,m",
17
+ "enumerate": "vp,vt,cb,dbe",
18
18
  "threads": 5,
19
- "request_timeout": 60,
20
- "connection_timeout": 30,
19
+ "request_timeout": 5,
20
+ "connection_timeout": 2,
21
21
  "disable_tls_checks": True,
22
22
  "force": False,
23
23
  }
24
24
  options_desc = {
25
25
  "api_key": "WPScan API Key",
26
- "enumerate": "Enumeration Process see wpscan help documentation (default: vp,vt,tt,cb,dbe,u,m)",
26
+ "enumerate": "Enumeration Process see wpscan help documentation (default: vp,vt,cb,dbe)",
27
27
  "threads": "How many wpscan threads to spawn (default is 5)",
28
- "request_timeout": "The request timeout in seconds (default 60)",
29
- "connection_timeout": "The connection timeout in seconds (default 30)",
28
+ "request_timeout": "The request timeout in seconds (default 5)",
29
+ "connection_timeout": "The connection timeout in seconds (default 2)",
30
30
  "disable_tls_checks": "Disables the SSL/TLS certificate verification (Default True)",
31
31
  "force": "Do not check if the target is running WordPress or returns a 403",
32
32
  }
33
33
  deps_apt = ["curl", "make", "gcc"]
34
34
  deps_ansible = [
35
35
  {
36
- "name": "Install Ruby Deps (Debian/Ubuntu)",
36
+ "name": "Install Ruby Deps (Debian)",
37
37
  "package": {"name": ["ruby-rubygems", "ruby-dev"], "state": "present"},
38
38
  "become": True,
39
39
  "when": "ansible_facts['os_family'] == 'Debian'",
@@ -48,7 +48,13 @@ class wpscan(BaseModule):
48
48
  "name": "Install Ruby Deps (Fedora)",
49
49
  "package": {"name": ["rubygems", "ruby-devel"], "state": "present"},
50
50
  "become": True,
51
- "when": "ansible_facts['os_family'] == 'Fedora'",
51
+ "when": "ansible_facts['os_family'] == 'RedHat'",
52
+ },
53
+ {
54
+ "name": "Install Ruby Deps (Alpine)",
55
+ "package": {"name": ["ruby-dev", "ruby-bundler"], "state": "present"},
56
+ "become": True,
57
+ "when": "ansible_facts['os_family'] == 'Alpine'",
52
58
  },
53
59
  {
54
60
  "name": "Install wpscan gem",
@@ -61,11 +67,11 @@ class wpscan(BaseModule):
61
67
  self.processed = set()
62
68
  self.ignore_events = ["xmlrpc", "readme"]
63
69
  self.api_key = self.config.get("api_key", "")
64
- self.enumerate = self.config.get("enumerate", "vp,vt,tt,cb,dbe,u,m")
70
+ self.enumerate = self.config.get("enumerate", "vp,vt,cb,dbe")
65
71
  self.proxy = self.scan.web_config.get("http_proxy", "")
66
72
  self.threads = self.config.get("threads", 5)
67
- self.request_timeout = self.config.get("request_timeout", 60)
68
- self.connection_timeout = self.config.get("connection_timeout", 30)
73
+ self.request_timeout = self.config.get("request_timeout", 5)
74
+ self.connection_timeout = self.config.get("connection_timeout", 2)
69
75
  self.disable_tls_checks = self.config.get("disable_tls_checks", True)
70
76
  self.force = self.config.get("force", False)
71
77
  return True
bbot/modules/zoomeye.py CHANGED
@@ -22,13 +22,16 @@ class zoomeye(subdomain_enum_apikey):
22
22
 
23
23
  async def setup(self):
24
24
  self.max_pages = self.config.get("max_pages", 20)
25
- self.headers = {"API-KEY": self.config.get("api_key", "")}
26
25
  self.include_related = self.config.get("include_related", False)
27
26
  return await super().setup()
28
27
 
28
+ def prepare_api_request(self, url, kwargs):
29
+ kwargs["headers"]["API-KEY"] = self.api_key
30
+ return url, kwargs
31
+
29
32
  async def ping(self):
30
33
  url = f"{self.base_url}/resources-info"
31
- r = await self.helpers.request(url, headers=self.headers)
34
+ r = await self.api_request(url)
32
35
  assert int(r.json()["quota_info"]["remain_total_quota"]) > 0, "No quota remaining"
33
36
 
34
37
  async def handle_event(self, event):
@@ -54,10 +57,10 @@ class zoomeye(subdomain_enum_apikey):
54
57
  query_type = 0 if self.include_related else 1
55
58
  url = f"{self.base_url}/domain/search?q={self.helpers.quote(query)}&type={query_type}&page=" + "{page}"
56
59
  i = 0
57
- agen = self.helpers.api_page_iter(url, headers=self.headers)
60
+ agen = self.api_page_iter(url)
58
61
  try:
59
62
  async for j in agen:
60
- r = list(self.parse_results(j))
63
+ r = list(await self.parse_results(j))
61
64
  if r:
62
65
  results.update(set(r))
63
66
  if not r or i >= (self.max_pages - 1):
@@ -67,6 +70,8 @@ class zoomeye(subdomain_enum_apikey):
67
70
  agen.aclose()
68
71
  return results
69
72
 
70
- def parse_results(self, r):
73
+ async def parse_results(self, r):
74
+ results = set()
71
75
  for entry in r.get("list", []):
72
- yield entry["name"]
76
+ results.add(entry["name"])
77
+ return results
@@ -0,0 +1,12 @@
1
+ description: Run all baddns modules and submodules.
2
+
3
+
4
+ modules:
5
+ - baddns
6
+ - baddns_zone
7
+ - baddns_direct
8
+
9
+ config:
10
+ modules:
11
+ baddns:
12
+ enabled_submodules: [CNAME,references,MX,NS,TXT]
bbot/presets/fast.yml ADDED
@@ -0,0 +1,16 @@
1
+ description: Scan only the provided targets as fast as possible - no extra discovery
2
+
3
+ exclude_modules:
4
+ - excavate
5
+
6
+ config:
7
+ # only scan the exact targets specified
8
+ scope:
9
+ strict: true
10
+ # speed up dns resolution by doing A/AAAA only - not MX/NS/SRV/etc
11
+ dns:
12
+ minimal: true
13
+ # essential speculation only
14
+ modules:
15
+ speculate:
16
+ essential_only: true
@@ -10,10 +10,9 @@ include:
10
10
  - paramminer
11
11
  - dirbust-light
12
12
  - web-screenshots
13
+ - baddns-thorough
13
14
 
14
15
  config:
15
16
  modules:
16
17
  baddns:
17
18
  enable_references: True
18
-
19
-
bbot/presets/spider.yml CHANGED
@@ -3,6 +3,10 @@ description: Recursive web spider
3
3
  modules:
4
4
  - httpx
5
5
 
6
+ blacklist:
7
+ # Prevent spider from invalidating sessions by logging out
8
+ - "RE:/.*(sign|log)[_-]?out"
9
+
6
10
  config:
7
11
  web:
8
12
  # how many links to follow in a row
@@ -13,10 +13,10 @@ config:
13
13
  threads: 25
14
14
  brute_threads: 1000
15
15
  # put your API keys here
16
- modules:
17
- github:
18
- api_key: ""
19
- chaos:
20
- api_key: ""
21
- securitytrails:
22
- api_key: ""
16
+ # modules:
17
+ # github:
18
+ # api_key: ""
19
+ # chaos:
20
+ # api_key: ""
21
+ # securitytrails:
22
+ # api_key: ""
@@ -19,4 +19,3 @@ config:
19
19
  extensions: asp,aspx,ashx,asmx,ascx
20
20
  telerik:
21
21
  exploit_RAU_crypto: True
22
-
bbot/scanner/manager.py CHANGED
@@ -1,10 +1,10 @@
1
1
  import asyncio
2
2
  from contextlib import suppress
3
3
 
4
- from bbot.modules.base import InterceptModule
4
+ from bbot.modules.base import BaseInterceptModule
5
5
 
6
6
 
7
- class ScanIngress(InterceptModule):
7
+ class ScanIngress(BaseInterceptModule):
8
8
  """
9
9
  This is always the first intercept module in the chain, responsible for basic scope checks
10
10
 
@@ -15,9 +15,7 @@ class ScanIngress(InterceptModule):
15
15
  # accept all events regardless of scope distance
16
16
  scope_distance_modifier = None
17
17
  _name = "_scan_ingress"
18
-
19
- # small queue size so we don't drain modules' outgoing queues
20
- _qsize = 10
18
+ _qsize = -1
21
19
 
22
20
  @property
23
21
  def priority(self):
@@ -40,7 +38,7 @@ class ScanIngress(InterceptModule):
40
38
  - It also marks the Scan object as finished with initialization by setting `_finished_init` to True.
41
39
  """
42
40
  if events is None:
43
- events = self.scan.target.events
41
+ events = self.scan.target.seeds.events
44
42
  async with self.scan._acatch(self.init_events), self._task_counter.count(self.init_events):
45
43
  sorted_events = sorted(events, key=lambda e: len(e.data))
46
44
  for event in [self.scan.root_event] + sorted_events:
@@ -51,7 +49,6 @@ class ScanIngress(InterceptModule):
51
49
  event.parent = self.scan.root_event
52
50
  if event.module is None:
53
51
  event.module = self.scan._make_dummy_module(name="TARGET", _type="TARGET")
54
- event.add_tag("target")
55
52
  if event != self.scan.root_event:
56
53
  event.discovery_context = f"Scan {self.scan.name} seeded with " + "{event.type}: {event.data}"
57
54
  self.verbose(f"Target: {event}")
@@ -115,14 +112,6 @@ class ScanIngress(InterceptModule):
115
112
  # nerf event's priority if it's not in scope
116
113
  event.module_priority += event.scope_distance
117
114
 
118
- async def forward_event(self, event, kwargs):
119
- # if a module qualifies for "quick-emit", we skip all the intermediate modules like dns and cloud
120
- # and forward it straight to the egress module
121
- if event.quick_emit:
122
- await self.scan.egress_module.queue_event(event, kwargs)
123
- else:
124
- await super().forward_event(event, kwargs)
125
-
126
115
  @property
127
116
  def non_intercept_modules(self):
128
117
  if self._non_intercept_modules is None:
@@ -169,7 +158,7 @@ class ScanIngress(InterceptModule):
169
158
  return False
170
159
 
171
160
 
172
- class ScanEgress(InterceptModule):
161
+ class ScanEgress(BaseInterceptModule):
173
162
  """
174
163
  This is always the last intercept module in the chain, responsible for executing and acting on the
175
164
  `abort_if` and `on_success_callback` functions.
@@ -10,7 +10,6 @@ log = logging.getLogger("bbot.presets.args")
10
10
 
11
11
 
12
12
  class BBOTArgs:
13
-
14
13
  # module config options to exclude from validation
15
14
  exclude_from_validation = re.compile(r".*modules\.[a-z0-9_]+\.(?:batch_size|module_threads)$")
16
15
 
@@ -91,18 +90,9 @@ class BBOTArgs:
91
90
  *self.parsed.targets,
92
91
  whitelist=self.parsed.whitelist,
93
92
  blacklist=self.parsed.blacklist,
94
- strict_scope=self.parsed.strict_scope,
95
93
  name="args_preset",
96
94
  )
97
95
 
98
- # then we set verbosity levels (so if the user enables -d they can see debug output)
99
- if self.parsed.silent:
100
- args_preset.silent = True
101
- if self.parsed.verbose:
102
- args_preset.verbose = True
103
- if self.parsed.debug:
104
- args_preset.debug = True
105
-
106
96
  # then we load requested preset
107
97
  # this is important so we can load custom module directories, pull in custom flags, module config options, etc.
108
98
  for preset_arg in self.parsed.preset:
@@ -113,6 +103,14 @@ class BBOTArgs:
113
103
  except Exception as e:
114
104
  raise BBOTArgumentError(f'Error parsing preset "{preset_arg}": {e}')
115
105
 
106
+ # then we set verbosity levels (so if the user enables -d they can see debug output)
107
+ if self.parsed.silent:
108
+ args_preset.silent = True
109
+ if self.parsed.verbose:
110
+ args_preset.verbose = True
111
+ if self.parsed.debug:
112
+ args_preset.debug = True
113
+
116
114
  # modules + flags
117
115
  args_preset.exclude_modules.update(set(self.parsed.exclude_modules))
118
116
  args_preset.exclude_flags.update(set(self.parsed.exclude_flags))
@@ -142,9 +140,15 @@ class BBOTArgs:
142
140
  args_preset.core.custom_config["deps_behavior"] = "ignore_failed"
143
141
 
144
142
  # other scan options
145
- args_preset.scan_name = self.parsed.name
146
- args_preset.output_dir = self.parsed.output_dir
147
- args_preset.force_start = self.parsed.force
143
+ if self.parsed.name is not None:
144
+ args_preset.scan_name = self.parsed.name
145
+ if self.parsed.output_dir is not None:
146
+ args_preset.output_dir = self.parsed.output_dir
147
+ if self.parsed.force:
148
+ args_preset.force_start = self.parsed.force
149
+
150
+ if self.parsed.proxy:
151
+ args_preset.core.merge_custom({"web": {"http_proxy": self.parsed.proxy}})
148
152
 
149
153
  if self.parsed.custom_headers:
150
154
  args_preset.core.merge_custom({"web": {"http_headers": self.parsed.custom_headers}})
@@ -162,13 +166,19 @@ class BBOTArgs:
162
166
  except Exception as e:
163
167
  raise BBOTArgumentError(f'Error parsing command-line config option: "{config_arg}": {e}')
164
168
 
169
+ # strict scope
170
+ if self.parsed.strict_scope:
171
+ args_preset.core.merge_custom({"scope": {"strict": True}})
172
+
165
173
  return args_preset
166
174
 
167
175
  def create_parser(self, *args, **kwargs):
168
176
  kwargs.update(
169
- dict(
170
- description="Bighuge BLS OSINT Tool", formatter_class=argparse.RawTextHelpFormatter, epilog=self.epilog
171
- )
177
+ {
178
+ "description": "Bighuge BLS OSINT Tool",
179
+ "formatter_class": argparse.RawTextHelpFormatter,
180
+ "epilog": self.epilog,
181
+ }
172
182
  )
173
183
  p = argparse.ArgumentParser(*args, **kwargs)
174
184
 
@@ -206,7 +216,7 @@ class BBOTArgs:
206
216
  metavar="CONFIG",
207
217
  default=[],
208
218
  )
209
- presets.add_argument("-lp", "--list-presets", action="store_true", help=f"List available presets.")
219
+ presets.add_argument("-lp", "--list-presets", action="store_true", help="List available presets.")
210
220
 
211
221
  modules = p.add_argument_group(title="Modules")
212
222
  modules.add_argument(
@@ -214,31 +224,31 @@ class BBOTArgs:
214
224
  "--modules",
215
225
  nargs="+",
216
226
  default=[],
217
- help=f'Modules to enable. Choices: {",".join(self.preset.module_loader.scan_module_choices)}',
227
+ help=f'Modules to enable. Choices: {",".join(sorted(self.preset.module_loader.scan_module_choices))}',
218
228
  metavar="MODULE",
219
229
  )
220
- modules.add_argument("-l", "--list-modules", action="store_true", help=f"List available modules.")
230
+ modules.add_argument("-l", "--list-modules", action="store_true", help="List available modules.")
221
231
  modules.add_argument(
222
232
  "-lmo", "--list-module-options", action="store_true", help="Show all module config options"
223
233
  )
224
234
  modules.add_argument(
225
- "-em", "--exclude-modules", nargs="+", default=[], help=f"Exclude these modules.", metavar="MODULE"
235
+ "-em", "--exclude-modules", nargs="+", default=[], help="Exclude these modules.", metavar="MODULE"
226
236
  )
227
237
  modules.add_argument(
228
238
  "-f",
229
239
  "--flags",
230
240
  nargs="+",
231
241
  default=[],
232
- help=f'Enable modules by flag. Choices: {",".join(self.preset.module_loader.flag_choices)}',
242
+ help=f'Enable modules by flag. Choices: {",".join(sorted(self.preset.module_loader.flag_choices))}',
233
243
  metavar="FLAG",
234
244
  )
235
- modules.add_argument("-lf", "--list-flags", action="store_true", help=f"List available flags.")
245
+ modules.add_argument("-lf", "--list-flags", action="store_true", help="List available flags.")
236
246
  modules.add_argument(
237
247
  "-rf",
238
248
  "--require-flags",
239
249
  nargs="+",
240
250
  default=[],
241
- help=f"Only enable modules with these flags (e.g. -rf passive)",
251
+ help="Only enable modules with these flags (e.g. -rf passive)",
242
252
  metavar="FLAG",
243
253
  )
244
254
  modules.add_argument(
@@ -246,7 +256,7 @@ class BBOTArgs:
246
256
  "--exclude-flags",
247
257
  nargs="+",
248
258
  default=[],
249
- help=f"Disable modules with these flags. (e.g. -ef aggressive)",
259
+ help="Disable modules with these flags. (e.g. -ef aggressive)",
250
260
  metavar="FLAG",
251
261
  )
252
262
  modules.add_argument("--allow-deadly", action="store_true", help="Enable the use of highly aggressive modules")
@@ -262,7 +272,12 @@ class BBOTArgs:
262
272
  help="Run scan even in the case of condition violations or failed module setups",
263
273
  )
264
274
  scan.add_argument("-y", "--yes", action="store_true", help="Skip scan confirmation prompt")
265
- scan.add_argument("--dry-run", action="store_true", help=f"Abort before executing scan")
275
+ scan.add_argument(
276
+ "--fast-mode",
277
+ action="store_true",
278
+ help="Scan only the provided targets as fast as possible, with no extra discovery",
279
+ )
280
+ scan.add_argument("--dry-run", action="store_true", help="Abort before executing scan")
266
281
  scan.add_argument(
267
282
  "--current-preset",
268
283
  action="store_true",
@@ -286,7 +301,7 @@ class BBOTArgs:
286
301
  "--output-modules",
287
302
  nargs="+",
288
303
  default=[],
289
- help=f'Output module(s). Choices: {",".join(self.preset.module_loader.output_module_choices)}',
304
+ help=f'Output module(s). Choices: {",".join(sorted(self.preset.module_loader.output_module_choices))}',
290
305
  metavar="MODULE",
291
306
  )
292
307
  output.add_argument("--json", "-j", action="store_true", help="Output scan data in JSON format")
@@ -307,6 +322,7 @@ class BBOTArgs:
307
322
 
308
323
  misc = p.add_argument_group(title="Misc")
309
324
  misc.add_argument("--version", action="store_true", help="show BBOT version and exit")
325
+ misc.add_argument("--proxy", help="Use this proxy for all HTTP requests", metavar="HTTP_PROXY")
310
326
  misc.add_argument(
311
327
  "-H",
312
328
  "--custom-headers",
@@ -356,6 +372,10 @@ class BBOTArgs:
356
372
  custom_headers_dict[k] = v
357
373
  self.parsed.custom_headers = custom_headers_dict
358
374
 
375
+ # --fast-mode
376
+ if self.parsed.fast_mode:
377
+ self.parsed.preset += ["fast"]
378
+
359
379
  def validate(self):
360
380
  # validate config options
361
381
  sentinel = object()
@@ -6,6 +6,9 @@ from pathlib import Path
6
6
  from bbot.core.helpers.misc import cpu_architecture, os_platform, os_platform_friendly
7
7
 
8
8
 
9
+ REQUESTS_PATCHED = False
10
+
11
+
9
12
  def increase_limit(new_limit):
10
13
  try:
11
14
  import resource
@@ -62,7 +65,6 @@ omegaconf.OmegaConf.register_new_resolver("env", env_resolver)
62
65
 
63
66
 
64
67
  class BBOTEnviron:
65
-
66
68
  def __init__(self, preset):
67
69
  self.preset = preset
68
70
 
@@ -120,7 +122,10 @@ class BBOTEnviron:
120
122
 
121
123
  urllib3.disable_warnings()
122
124
  ssl_verify = self.preset.config.get("ssl_verify", False)
123
- if not ssl_verify:
125
+
126
+ global REQUESTS_PATCHED
127
+ if not ssl_verify and not REQUESTS_PATCHED:
128
+ REQUESTS_PATCHED = True
124
129
  import requests
125
130
  import functools
126
131
 
@@ -33,13 +33,16 @@ class PresetPath:
33
33
  if "/" in str(filename):
34
34
  if filename_path.parent not in paths_to_search:
35
35
  paths_to_search.append(filename_path.parent)
36
- log.debug(f"Searching for preset in {paths_to_search}, file candidates: {file_candidates_str}")
36
+ log.debug(
37
+ f"Searching for preset in {[str(p) for p in paths_to_search]}, file candidates: {file_candidates_str}"
38
+ )
37
39
  for path in paths_to_search:
38
40
  for candidate in file_candidates:
39
41
  for file in path.rglob(candidate):
40
- log.verbose(f'Found preset matching "{filename}" at {file}')
41
- self.add_path(file.parent)
42
- return file.resolve()
42
+ if file.is_file():
43
+ log.verbose(f'Found preset matching "{filename}" at {file}')
44
+ self.add_path(file.parent)
45
+ return file.resolve()
43
46
  raise ValidationError(
44
47
  f'Could not find preset at "{filename}" - file does not exist. Use -lp to list available presets'
45
48
  )