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.
- bbot/__init__.py +1 -1
- bbot/cli.py +3 -7
- bbot/core/config/files.py +0 -1
- bbot/core/config/logger.py +34 -4
- bbot/core/core.py +21 -4
- bbot/core/engine.py +9 -8
- bbot/core/event/base.py +131 -52
- bbot/core/helpers/bloom.py +10 -3
- bbot/core/helpers/command.py +8 -7
- bbot/core/helpers/depsinstaller/installer.py +31 -13
- bbot/core/helpers/diff.py +10 -10
- bbot/core/helpers/dns/brute.py +7 -4
- bbot/core/helpers/dns/dns.py +1 -2
- bbot/core/helpers/dns/engine.py +4 -6
- bbot/core/helpers/dns/helpers.py +2 -2
- bbot/core/helpers/dns/mock.py +0 -1
- bbot/core/helpers/files.py +1 -1
- bbot/core/helpers/helper.py +7 -4
- bbot/core/helpers/interactsh.py +3 -3
- bbot/core/helpers/libmagic.py +65 -0
- bbot/core/helpers/misc.py +65 -22
- bbot/core/helpers/names_generator.py +17 -3
- bbot/core/helpers/process.py +0 -20
- bbot/core/helpers/regex.py +1 -1
- bbot/core/helpers/regexes.py +12 -6
- bbot/core/helpers/validators.py +1 -2
- bbot/core/helpers/web/client.py +1 -1
- bbot/core/helpers/web/engine.py +1 -2
- bbot/core/helpers/web/web.py +4 -114
- bbot/core/helpers/wordcloud.py +5 -5
- bbot/core/modules.py +36 -27
- bbot/core/multiprocess.py +58 -0
- bbot/core/shared_deps.py +46 -3
- bbot/db/sql/models.py +147 -0
- bbot/defaults.yml +12 -10
- bbot/modules/anubisdb.py +2 -2
- bbot/modules/apkpure.py +63 -0
- bbot/modules/azure_tenant.py +2 -2
- bbot/modules/baddns.py +35 -19
- bbot/modules/baddns_direct.py +92 -0
- bbot/modules/baddns_zone.py +3 -8
- bbot/modules/badsecrets.py +4 -3
- bbot/modules/base.py +195 -51
- bbot/modules/bevigil.py +7 -7
- bbot/modules/binaryedge.py +7 -4
- bbot/modules/bufferoverrun.py +47 -0
- bbot/modules/builtwith.py +6 -10
- bbot/modules/bypass403.py +5 -5
- bbot/modules/c99.py +10 -7
- bbot/modules/censys.py +9 -13
- bbot/modules/certspotter.py +5 -3
- bbot/modules/chaos.py +9 -7
- bbot/modules/code_repository.py +1 -0
- bbot/modules/columbus.py +3 -3
- bbot/modules/crt.py +5 -3
- bbot/modules/deadly/dastardly.py +1 -1
- bbot/modules/deadly/ffuf.py +9 -9
- bbot/modules/deadly/nuclei.py +3 -3
- bbot/modules/deadly/vhost.py +4 -3
- bbot/modules/dehashed.py +1 -1
- bbot/modules/digitorus.py +1 -1
- bbot/modules/dnsbimi.py +145 -0
- bbot/modules/dnscaa.py +3 -3
- bbot/modules/dnsdumpster.py +4 -4
- bbot/modules/dnstlsrpt.py +144 -0
- bbot/modules/docker_pull.py +7 -5
- bbot/modules/dockerhub.py +2 -2
- bbot/modules/dotnetnuke.py +20 -21
- bbot/modules/emailformat.py +1 -1
- bbot/modules/extractous.py +122 -0
- bbot/modules/filedownload.py +9 -7
- bbot/modules/fullhunt.py +7 -4
- bbot/modules/generic_ssrf.py +5 -5
- bbot/modules/github_codesearch.py +3 -2
- bbot/modules/github_org.py +4 -4
- bbot/modules/github_workflows.py +4 -4
- bbot/modules/gitlab.py +2 -5
- bbot/modules/google_playstore.py +93 -0
- bbot/modules/gowitness.py +48 -50
- bbot/modules/hackertarget.py +5 -3
- bbot/modules/host_header.py +5 -5
- bbot/modules/httpx.py +1 -4
- bbot/modules/hunterio.py +3 -9
- bbot/modules/iis_shortnames.py +19 -30
- bbot/modules/internal/cloudcheck.py +29 -12
- bbot/modules/internal/dnsresolve.py +22 -22
- bbot/modules/internal/excavate.py +97 -59
- bbot/modules/internal/speculate.py +41 -32
- bbot/modules/internetdb.py +4 -2
- bbot/modules/ip2location.py +3 -5
- bbot/modules/ipneighbor.py +1 -1
- bbot/modules/ipstack.py +3 -8
- bbot/modules/jadx.py +87 -0
- bbot/modules/leakix.py +11 -10
- bbot/modules/myssl.py +2 -2
- bbot/modules/newsletters.py +2 -2
- bbot/modules/otx.py +5 -3
- bbot/modules/output/asset_inventory.py +7 -7
- bbot/modules/output/base.py +1 -1
- bbot/modules/output/csv.py +1 -1
- bbot/modules/output/http.py +20 -14
- bbot/modules/output/mysql.py +51 -0
- bbot/modules/output/neo4j.py +7 -2
- bbot/modules/output/postgres.py +49 -0
- bbot/modules/output/slack.py +0 -1
- bbot/modules/output/sqlite.py +29 -0
- bbot/modules/output/stdout.py +2 -2
- bbot/modules/output/teams.py +107 -6
- bbot/modules/paramminer_headers.py +8 -11
- bbot/modules/passivetotal.py +13 -13
- bbot/modules/portscan.py +32 -6
- bbot/modules/postman.py +50 -126
- bbot/modules/postman_download.py +220 -0
- bbot/modules/rapiddns.py +3 -8
- bbot/modules/report/asn.py +18 -11
- bbot/modules/robots.py +3 -3
- bbot/modules/securitytrails.py +7 -10
- bbot/modules/securitytxt.py +1 -1
- bbot/modules/shodan_dns.py +7 -9
- bbot/modules/sitedossier.py +1 -1
- bbot/modules/skymem.py +2 -2
- bbot/modules/social.py +2 -1
- bbot/modules/subdomaincenter.py +1 -1
- bbot/modules/subdomainradar.py +160 -0
- bbot/modules/telerik.py +8 -8
- bbot/modules/templates/bucket.py +1 -1
- bbot/modules/templates/github.py +22 -14
- bbot/modules/templates/postman.py +21 -0
- bbot/modules/templates/shodan.py +14 -13
- bbot/modules/templates/sql.py +95 -0
- bbot/modules/templates/subdomain_enum.py +51 -16
- bbot/modules/templates/webhook.py +2 -4
- bbot/modules/trickest.py +8 -37
- bbot/modules/trufflehog.py +10 -12
- bbot/modules/url_manipulation.py +3 -3
- bbot/modules/urlscan.py +1 -1
- bbot/modules/viewdns.py +1 -1
- bbot/modules/virustotal.py +8 -30
- bbot/modules/wafw00f.py +1 -1
- bbot/modules/wayback.py +1 -1
- bbot/modules/wpscan.py +17 -11
- bbot/modules/zoomeye.py +11 -6
- bbot/presets/baddns-thorough.yml +12 -0
- bbot/presets/fast.yml +16 -0
- bbot/presets/kitchen-sink.yml +1 -2
- bbot/presets/spider.yml +4 -0
- bbot/presets/subdomain-enum.yml +7 -7
- bbot/presets/web/dotnet-audit.yml +0 -1
- bbot/scanner/manager.py +5 -16
- bbot/scanner/preset/args.py +46 -26
- bbot/scanner/preset/environ.py +7 -2
- bbot/scanner/preset/path.py +7 -4
- bbot/scanner/preset/preset.py +36 -23
- bbot/scanner/scanner.py +172 -62
- bbot/scanner/target.py +236 -434
- bbot/scripts/docs.py +1 -1
- bbot/test/bbot_fixtures.py +13 -3
- bbot/test/conftest.py +132 -100
- bbot/test/fastapi_test.py +17 -0
- bbot/test/owasp_mastg.apk +0 -0
- bbot/test/run_tests.sh +4 -4
- bbot/test/test.conf +2 -0
- bbot/test/test_step_1/test__module__tests.py +0 -1
- bbot/test/test_step_1/test_bbot_fastapi.py +79 -0
- bbot/test/test_step_1/test_bloom_filter.py +2 -1
- bbot/test/test_step_1/test_cli.py +138 -64
- bbot/test/test_step_1/test_dns.py +61 -27
- bbot/test/test_step_1/test_engine.py +17 -19
- bbot/test/test_step_1/test_events.py +183 -30
- bbot/test/test_step_1/test_helpers.py +64 -29
- bbot/test/test_step_1/test_manager_deduplication.py +1 -1
- bbot/test/test_step_1/test_manager_scope_accuracy.py +333 -330
- bbot/test/test_step_1/test_modules_basic.py +68 -70
- bbot/test/test_step_1/test_presets.py +183 -100
- bbot/test/test_step_1/test_python_api.py +7 -2
- bbot/test/test_step_1/test_regexes.py +35 -5
- bbot/test/test_step_1/test_scan.py +39 -5
- bbot/test/test_step_1/test_scope.py +4 -3
- bbot/test/test_step_1/test_target.py +242 -145
- bbot/test/test_step_1/test_web.py +14 -10
- bbot/test/test_step_2/module_tests/base.py +15 -7
- bbot/test/test_step_2/module_tests/test_module_anubisdb.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_apkpure.py +71 -0
- bbot/test/test_step_2/module_tests/test_module_asset_inventory.py +0 -1
- bbot/test/test_step_2/module_tests/test_module_azure_realm.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_baddns.py +6 -6
- bbot/test/test_step_2/module_tests/test_module_baddns_direct.py +62 -0
- bbot/test/test_step_2/module_tests/test_module_bevigil.py +29 -2
- bbot/test/test_step_2/module_tests/test_module_binaryedge.py +4 -2
- bbot/test/test_step_2/module_tests/test_module_bucket_amazon.py +2 -2
- bbot/test/test_step_2/module_tests/test_module_bucket_azure.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_bufferoverrun.py +35 -0
- bbot/test/test_step_2/module_tests/test_module_builtwith.py +2 -2
- bbot/test/test_step_2/module_tests/test_module_bypass403.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_c99.py +126 -0
- bbot/test/test_step_2/module_tests/test_module_censys.py +4 -1
- bbot/test/test_step_2/module_tests/test_module_cloudcheck.py +4 -0
- bbot/test/test_step_2/module_tests/test_module_code_repository.py +11 -1
- bbot/test/test_step_2/module_tests/test_module_columbus.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_credshed.py +3 -3
- bbot/test/test_step_2/module_tests/test_module_dastardly.py +2 -1
- bbot/test/test_step_2/module_tests/test_module_dehashed.py +2 -2
- bbot/test/test_step_2/module_tests/test_module_digitorus.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_discord.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_dnsbimi.py +103 -0
- bbot/test/test_step_2/module_tests/test_module_dnsbrute.py +9 -10
- bbot/test/test_step_2/module_tests/test_module_dnsbrute_mutations.py +1 -2
- bbot/test/test_step_2/module_tests/test_module_dnscommonsrv.py +1 -2
- bbot/test/test_step_2/module_tests/test_module_dnsdumpster.py +4 -4
- bbot/test/test_step_2/module_tests/test_module_dnstlsrpt.py +64 -0
- bbot/test/test_step_2/module_tests/test_module_dotnetnuke.py +0 -8
- bbot/test/test_step_2/module_tests/test_module_excavate.py +28 -48
- bbot/test/test_step_2/module_tests/test_module_extractous.py +54 -0
- bbot/test/test_step_2/module_tests/test_module_ffuf_shortnames.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_filedownload.py +14 -14
- bbot/test/test_step_2/module_tests/test_module_git_clone.py +2 -2
- bbot/test/test_step_2/module_tests/test_module_github_org.py +19 -8
- bbot/test/test_step_2/module_tests/test_module_github_workflows.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_gitlab.py +9 -4
- bbot/test/test_step_2/module_tests/test_module_google_playstore.py +83 -0
- bbot/test/test_step_2/module_tests/test_module_gowitness.py +4 -6
- bbot/test/test_step_2/module_tests/test_module_host_header.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_http.py +4 -4
- bbot/test/test_step_2/module_tests/test_module_httpx.py +10 -8
- bbot/test/test_step_2/module_tests/test_module_hunterio.py +68 -4
- bbot/test/test_step_2/module_tests/test_module_jadx.py +55 -0
- bbot/test/test_step_2/module_tests/test_module_json.py +22 -9
- bbot/test/test_step_2/module_tests/test_module_leakix.py +7 -3
- bbot/test/test_step_2/module_tests/test_module_mysql.py +76 -0
- bbot/test/test_step_2/module_tests/test_module_myssl.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_neo4j.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_newsletters.py +16 -16
- bbot/test/test_step_2/module_tests/test_module_ntlm.py +8 -7
- bbot/test/test_step_2/module_tests/test_module_oauth.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_otx.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_paramminer_cookies.py +1 -2
- bbot/test/test_step_2/module_tests/test_module_paramminer_getparams.py +0 -6
- bbot/test/test_step_2/module_tests/test_module_paramminer_headers.py +2 -9
- bbot/test/test_step_2/module_tests/test_module_passivetotal.py +3 -1
- bbot/test/test_step_2/module_tests/test_module_pgp.py +2 -2
- bbot/test/test_step_2/module_tests/test_module_portscan.py +9 -8
- bbot/test/test_step_2/module_tests/test_module_postgres.py +74 -0
- bbot/test/test_step_2/module_tests/test_module_postman.py +84 -253
- bbot/test/test_step_2/module_tests/test_module_postman_download.py +439 -0
- bbot/test/test_step_2/module_tests/test_module_rapiddns.py +93 -1
- bbot/test/test_step_2/module_tests/test_module_shodan_dns.py +20 -1
- bbot/test/test_step_2/module_tests/test_module_sitedossier.py +2 -2
- bbot/test/test_step_2/module_tests/test_module_smuggler.py +14 -14
- bbot/test/test_step_2/module_tests/test_module_social.py +11 -1
- bbot/test/test_step_2/module_tests/test_module_speculate.py +4 -8
- bbot/test/test_step_2/module_tests/test_module_splunk.py +4 -4
- bbot/test/test_step_2/module_tests/test_module_sqlite.py +18 -0
- bbot/test/test_step_2/module_tests/test_module_sslcert.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_stdout.py +5 -3
- bbot/test/test_step_2/module_tests/test_module_subdomaincenter.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_subdomainradar.py +208 -0
- bbot/test/test_step_2/module_tests/test_module_subdomains.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_teams.py +8 -6
- bbot/test/test_step_2/module_tests/test_module_telerik.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_trufflehog.py +317 -14
- bbot/test/test_step_2/module_tests/test_module_viewdns.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_wayback.py +1 -1
- bbot/test/test_step_2/template_tests/test_template_subdomain_enum.py +2 -2
- bbot/wordlists/devops_mutations.txt +1 -1
- bbot/wordlists/ffuf_shortname_candidates.txt +1 -1
- bbot/wordlists/nameservers.txt +1 -1
- bbot/wordlists/paramminer_headers.txt +1 -1
- bbot/wordlists/paramminer_parameters.txt +1 -1
- bbot/wordlists/raft-small-extensions-lowercase_CLEANED.txt +1 -1
- bbot/wordlists/valid_url_schemes.txt +1 -1
- {bbot-2.0.1.4720rc0.dist-info → bbot-2.3.0.5401rc0.dist-info}/METADATA +48 -18
- bbot-2.3.0.5401rc0.dist-info/RECORD +421 -0
- {bbot-2.0.1.4720rc0.dist-info → bbot-2.3.0.5401rc0.dist-info}/WHEEL +1 -1
- bbot/modules/unstructured.py +0 -163
- bbot/test/test_step_2/module_tests/test_module_unstructured.py +0 -102
- bbot-2.0.1.4720rc0.dist-info/RECORD +0 -387
- {bbot-2.0.1.4720rc0.dist-info → bbot-2.3.0.5401rc0.dist-info}/LICENSE +0 -0
- {bbot-2.0.1.4720rc0.dist-info → bbot-2.3.0.5401rc0.dist-info}/entry_points.txt +0 -0
bbot/modules/virustotal.py
CHANGED
|
@@ -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
|
-
|
|
20
|
-
self.
|
|
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
|
-
|
|
25
|
-
|
|
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
|
-
|
|
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")
|
|
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": "@
|
|
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,
|
|
17
|
+
"enumerate": "vp,vt,cb,dbe",
|
|
18
18
|
"threads": 5,
|
|
19
|
-
"request_timeout":
|
|
20
|
-
"connection_timeout":
|
|
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,
|
|
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
|
|
29
|
-
"connection_timeout": "The connection timeout in seconds (default
|
|
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
|
|
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'] == '
|
|
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,
|
|
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",
|
|
68
|
-
self.connection_timeout = self.config.get("connection_timeout",
|
|
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.
|
|
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.
|
|
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
|
-
|
|
76
|
+
results.add(entry["name"])
|
|
77
|
+
return results
|
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
|
bbot/presets/kitchen-sink.yml
CHANGED
bbot/presets/spider.yml
CHANGED
bbot/presets/subdomain-enum.yml
CHANGED
|
@@ -13,10 +13,10 @@ config:
|
|
|
13
13
|
threads: 25
|
|
14
14
|
brute_threads: 1000
|
|
15
15
|
# put your API keys here
|
|
16
|
-
modules:
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
# modules:
|
|
17
|
+
# github:
|
|
18
|
+
# api_key: ""
|
|
19
|
+
# chaos:
|
|
20
|
+
# api_key: ""
|
|
21
|
+
# securitytrails:
|
|
22
|
+
# api_key: ""
|
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
|
|
4
|
+
from bbot.modules.base import BaseInterceptModule
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
class ScanIngress(
|
|
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(
|
|
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.
|
bbot/scanner/preset/args.py
CHANGED
|
@@ -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
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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
|
-
|
|
170
|
-
description
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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(
|
|
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()
|
bbot/scanner/preset/environ.py
CHANGED
|
@@ -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
|
-
|
|
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
|
|
bbot/scanner/preset/path.py
CHANGED
|
@@ -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(
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
)
|