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
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from ipaddress import ip_network
|
|
2
|
+
|
|
1
3
|
from ..bbot_fixtures import *
|
|
2
4
|
|
|
3
5
|
|
|
@@ -12,6 +14,7 @@ async def test_scan(
|
|
|
12
14
|
"1.1.1.0",
|
|
13
15
|
"1.1.1.1/31",
|
|
14
16
|
"evilcorp.com",
|
|
17
|
+
"test.evilcorp.com",
|
|
15
18
|
blacklist=["1.1.1.1/28", "www.evilcorp.com"],
|
|
16
19
|
modules=["ipneighbor"],
|
|
17
20
|
)
|
|
@@ -31,8 +34,11 @@ async def test_scan(
|
|
|
31
34
|
assert not scan0.in_scope("test.www.evilcorp.com")
|
|
32
35
|
assert not scan0.in_scope("www.evilcorp.co.uk")
|
|
33
36
|
j = scan0.json
|
|
34
|
-
assert set(j["target"]["seeds"]) == {"1.1.1.0", "1.1.1.0/31", "evilcorp.com"}
|
|
35
|
-
|
|
37
|
+
assert set(j["target"]["seeds"]) == {"1.1.1.0", "1.1.1.0/31", "evilcorp.com", "test.evilcorp.com"}
|
|
38
|
+
# we preserve the original whitelist inputs
|
|
39
|
+
assert set(j["target"]["whitelist"]) == {"1.1.1.0", "1.1.1.0/31", "evilcorp.com", "test.evilcorp.com"}
|
|
40
|
+
# but in the background they are collapsed
|
|
41
|
+
assert scan0.target.whitelist.hosts == {ip_network("1.1.1.0/31"), "evilcorp.com"}
|
|
36
42
|
assert set(j["target"]["blacklist"]) == {"1.1.1.0/28", "www.evilcorp.com"}
|
|
37
43
|
assert "ipneighbor" in j["preset"]["modules"]
|
|
38
44
|
|
|
@@ -78,6 +84,9 @@ async def test_scan(
|
|
|
78
84
|
for scan in (scan0, scan1, scan2, scan4, scan5):
|
|
79
85
|
await scan._cleanup()
|
|
80
86
|
|
|
87
|
+
scan6 = bbot_scanner("a.foobar.io", "b.foobar.io", "c.foobar.io", "foobar.io")
|
|
88
|
+
assert len(scan6.dns_strings) == 1
|
|
89
|
+
|
|
81
90
|
|
|
82
91
|
@pytest.mark.asyncio
|
|
83
92
|
async def test_url_extension_handling(bbot_scanner):
|
|
@@ -91,13 +100,13 @@ async def test_url_extension_handling(bbot_scanner):
|
|
|
91
100
|
assert "blacklisted" not in bad_event.tags
|
|
92
101
|
assert "httpx-only" not in httpx_event.tags
|
|
93
102
|
result = await scan.ingress_module.handle_event(good_event)
|
|
94
|
-
assert result
|
|
103
|
+
assert result is None
|
|
95
104
|
result, reason = await scan.ingress_module.handle_event(bad_event)
|
|
96
|
-
assert result
|
|
105
|
+
assert result is False
|
|
97
106
|
assert reason == "event is blacklisted"
|
|
98
107
|
assert "blacklisted" in bad_event.tags
|
|
99
108
|
result = await scan.ingress_module.handle_event(httpx_event)
|
|
100
|
-
assert result
|
|
109
|
+
assert result is None
|
|
101
110
|
assert "httpx-only" in httpx_event.tags
|
|
102
111
|
|
|
103
112
|
await scan._cleanup()
|
|
@@ -115,3 +124,28 @@ async def test_speed_counter():
|
|
|
115
124
|
await asyncio.sleep(0.2)
|
|
116
125
|
# only 5 should show
|
|
117
126
|
assert 4 <= counter.speed <= 5
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
@pytest.mark.asyncio
|
|
130
|
+
async def test_python_output_matches_json(bbot_scanner):
|
|
131
|
+
import json
|
|
132
|
+
|
|
133
|
+
scan = bbot_scanner(
|
|
134
|
+
"blacklanternsecurity.com",
|
|
135
|
+
config={"speculate": True, "dns": {"minimal": False}, "scope": {"report_distance": 10}},
|
|
136
|
+
)
|
|
137
|
+
await scan.helpers.dns._mock_dns({"blacklanternsecurity.com": {"A": ["127.0.0.1"]}})
|
|
138
|
+
events = [e.json() async for e in scan.async_start()]
|
|
139
|
+
output_json = scan.home / "output.json"
|
|
140
|
+
json_events = []
|
|
141
|
+
for line in open(output_json):
|
|
142
|
+
json_events.append(json.loads(line))
|
|
143
|
+
|
|
144
|
+
assert len(events) == 5
|
|
145
|
+
scan_events = [e for e in events if e["type"] == "SCAN"]
|
|
146
|
+
assert len(scan_events) == 2
|
|
147
|
+
assert all(isinstance(e["data"]["status"], str) for e in scan_events)
|
|
148
|
+
assert len([e for e in events if e["type"] == "DNS_NAME"]) == 1
|
|
149
|
+
assert len([e for e in events if e["type"] == "ORG_STUB"]) == 1
|
|
150
|
+
assert len([e for e in events if e["type"] == "IP_ADDRESS"]) == 1
|
|
151
|
+
assert events == json_events
|
|
@@ -12,7 +12,8 @@ class TestScopeBaseline(ModuleTestBase):
|
|
|
12
12
|
module_test.set_expect_requests(expect_args=expect_args, respond_args=respond_args)
|
|
13
13
|
|
|
14
14
|
def check(self, module_test, events):
|
|
15
|
-
assert len(events) ==
|
|
15
|
+
assert len(events) == 7
|
|
16
|
+
assert 2 == len([e for e in events if e.type == "SCAN"])
|
|
16
17
|
assert 1 == len(
|
|
17
18
|
[
|
|
18
19
|
e
|
|
@@ -62,7 +63,7 @@ class TestScopeBlacklist(TestScopeBaseline):
|
|
|
62
63
|
module_test.set_expect_requests(expect_args=expect_args, respond_args=respond_args)
|
|
63
64
|
|
|
64
65
|
def check(self, module_test, events):
|
|
65
|
-
assert len(events) ==
|
|
66
|
+
assert len(events) == 2
|
|
66
67
|
assert not any(e.type == "URL" for e in events)
|
|
67
68
|
assert not any(str(e.host) == "127.0.0.1" for e in events)
|
|
68
69
|
|
|
@@ -72,7 +73,7 @@ class TestScopeWhitelist(TestScopeBlacklist):
|
|
|
72
73
|
whitelist = ["255.255.255.255"]
|
|
73
74
|
|
|
74
75
|
def check(self, module_test, events):
|
|
75
|
-
assert len(events) ==
|
|
76
|
+
assert len(events) == 4
|
|
76
77
|
assert not any(e.type == "URL" for e in events)
|
|
77
78
|
assert 1 == len(
|
|
78
79
|
[
|
|
@@ -3,39 +3,31 @@ from ..bbot_fixtures import * # noqa: F401
|
|
|
3
3
|
|
|
4
4
|
@pytest.mark.asyncio
|
|
5
5
|
async def test_target(bbot_scanner):
|
|
6
|
-
import
|
|
6
|
+
from radixtarget import RadixTarget
|
|
7
7
|
from ipaddress import ip_address, ip_network
|
|
8
|
-
from bbot.scanner.target import
|
|
8
|
+
from bbot.scanner.target import BBOTTarget, ScanSeeds
|
|
9
9
|
|
|
10
10
|
scan1 = bbot_scanner("api.publicapis.org", "8.8.8.8/30", "2001:4860:4860::8888/126")
|
|
11
11
|
scan2 = bbot_scanner("8.8.8.8/29", "publicapis.org", "2001:4860:4860::8888/125")
|
|
12
12
|
scan3 = bbot_scanner("8.8.8.8/29", "publicapis.org", "2001:4860:4860::8888/125")
|
|
13
13
|
scan4 = bbot_scanner("8.8.8.8/29")
|
|
14
14
|
scan5 = bbot_scanner()
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
assert "
|
|
19
|
-
assert "
|
|
20
|
-
assert "
|
|
21
|
-
assert "
|
|
22
|
-
assert "
|
|
23
|
-
assert "
|
|
24
|
-
assert "
|
|
25
|
-
|
|
26
|
-
assert
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
assert scan1.make_event("https://[2001:4860:4860::8888]:80", dummy=True) in scan1.target
|
|
32
|
-
assert scan1.make_event("[2001:4860:4860::8888]:80", "OPEN_TCP_PORT", dummy=True) in scan1.target
|
|
33
|
-
assert scan1.make_event("[2001:4860:4860::888c]:80", "OPEN_TCP_PORT", dummy=True) not in scan1.target
|
|
34
|
-
assert scan1.target in scan2.target
|
|
35
|
-
assert scan2.target not in scan1.target
|
|
36
|
-
assert scan3.target in scan2.target
|
|
37
|
-
assert scan2.target == scan3.target
|
|
38
|
-
assert scan4.target != scan1.target
|
|
15
|
+
|
|
16
|
+
# test different types of inputs
|
|
17
|
+
target = BBOTTarget("evilcorp.com", "1.2.3.4/8")
|
|
18
|
+
assert "www.evilcorp.com" in target.seeds
|
|
19
|
+
assert "www.evilcorp.com:80" in target.seeds
|
|
20
|
+
assert "http://www.evilcorp.com:80" in target.seeds
|
|
21
|
+
assert "1.2.3.4" in target.seeds
|
|
22
|
+
assert "1.2.3.4/24" in target.seeds
|
|
23
|
+
assert ip_address("1.2.3.4") in target.seeds
|
|
24
|
+
assert ip_network("1.2.3.4/24", strict=False) in target.seeds
|
|
25
|
+
event = scan1.make_event("https://www.evilcorp.com:80", dummy=True)
|
|
26
|
+
assert event in target.seeds
|
|
27
|
+
with pytest.raises(ValueError):
|
|
28
|
+
["asdf"] in target.seeds
|
|
29
|
+
with pytest.raises(ValueError):
|
|
30
|
+
target.seeds.get(["asdf"])
|
|
39
31
|
|
|
40
32
|
assert not scan5.target.seeds
|
|
41
33
|
assert len(scan1.target.seeds) == 9
|
|
@@ -56,6 +48,36 @@ async def test_target(bbot_scanner):
|
|
|
56
48
|
assert scan1.make_event("https://[2001:4860:4860::8888]:80", dummy=True) in scan1.target.seeds
|
|
57
49
|
assert scan1.make_event("[2001:4860:4860::8888]:80", "OPEN_TCP_PORT", dummy=True) in scan1.target.seeds
|
|
58
50
|
assert scan1.make_event("[2001:4860:4860::888c]:80", "OPEN_TCP_PORT", dummy=True) not in scan1.target.seeds
|
|
51
|
+
assert scan1.target.seeds in scan2.target.seeds
|
|
52
|
+
assert scan2.target.seeds not in scan1.target.seeds
|
|
53
|
+
assert scan3.target.seeds in scan2.target.seeds
|
|
54
|
+
assert scan2.target.seeds == scan3.target.seeds
|
|
55
|
+
assert scan4.target.seeds != scan1.target.seeds
|
|
56
|
+
|
|
57
|
+
assert not scan5.target.whitelist
|
|
58
|
+
assert len(scan1.target.whitelist) == 9
|
|
59
|
+
assert len(scan4.target.whitelist) == 8
|
|
60
|
+
assert "8.8.8.9" in scan1.target.whitelist
|
|
61
|
+
assert "8.8.8.12" not in scan1.target.whitelist
|
|
62
|
+
assert "8.8.8.8/31" in scan1.target.whitelist
|
|
63
|
+
assert "8.8.8.8/30" in scan1.target.whitelist
|
|
64
|
+
assert "8.8.8.8/29" not in scan1.target.whitelist
|
|
65
|
+
assert "2001:4860:4860::8889" in scan1.target.whitelist
|
|
66
|
+
assert "2001:4860:4860::888c" not in scan1.target.whitelist
|
|
67
|
+
assert "www.api.publicapis.org" in scan1.target.whitelist
|
|
68
|
+
assert "api.publicapis.org" in scan1.target.whitelist
|
|
69
|
+
assert "publicapis.org" not in scan1.target.whitelist
|
|
70
|
+
assert "bob@www.api.publicapis.org" in scan1.target.whitelist
|
|
71
|
+
assert "https://www.api.publicapis.org" in scan1.target.whitelist
|
|
72
|
+
assert "www.api.publicapis.org:80" in scan1.target.whitelist
|
|
73
|
+
assert scan1.make_event("https://[2001:4860:4860::8888]:80", dummy=True) in scan1.target.whitelist
|
|
74
|
+
assert scan1.make_event("[2001:4860:4860::8888]:80", "OPEN_TCP_PORT", dummy=True) in scan1.target.whitelist
|
|
75
|
+
assert scan1.make_event("[2001:4860:4860::888c]:80", "OPEN_TCP_PORT", dummy=True) not in scan1.target.whitelist
|
|
76
|
+
assert scan1.target.whitelist in scan2.target.whitelist
|
|
77
|
+
assert scan2.target.whitelist not in scan1.target.whitelist
|
|
78
|
+
assert scan3.target.whitelist in scan2.target.whitelist
|
|
79
|
+
assert scan2.target.whitelist == scan3.target.whitelist
|
|
80
|
+
assert scan4.target.whitelist != scan1.target.whitelist
|
|
59
81
|
|
|
60
82
|
assert scan1.whitelisted("https://[2001:4860:4860::8888]:80")
|
|
61
83
|
assert scan1.whitelisted("[2001:4860:4860::8888]:80")
|
|
@@ -70,45 +92,58 @@ async def test_target(bbot_scanner):
|
|
|
70
92
|
assert scan2.target.seeds == scan3.target.seeds
|
|
71
93
|
assert scan4.target.seeds != scan1.target.seeds
|
|
72
94
|
|
|
73
|
-
assert str(scan1.target.get("8.8.8.9").host) == "8.8.8.8/30"
|
|
74
|
-
assert scan1.target.get("8.8.8.
|
|
75
|
-
assert
|
|
76
|
-
assert scan1.target.get("
|
|
77
|
-
assert str(scan1.target.get("
|
|
78
|
-
assert scan1.target.get("
|
|
79
|
-
|
|
80
|
-
target
|
|
81
|
-
assert
|
|
95
|
+
assert str(scan1.target.seeds.get("8.8.8.9").host) == "8.8.8.8/30"
|
|
96
|
+
assert str(scan1.target.whitelist.get("8.8.8.9").host) == "8.8.8.8/30"
|
|
97
|
+
assert scan1.target.seeds.get("8.8.8.12") is None
|
|
98
|
+
assert scan1.target.whitelist.get("8.8.8.12") is None
|
|
99
|
+
assert str(scan1.target.seeds.get("2001:4860:4860::8889").host) == "2001:4860:4860::8888/126"
|
|
100
|
+
assert str(scan1.target.whitelist.get("2001:4860:4860::8889").host) == "2001:4860:4860::8888/126"
|
|
101
|
+
assert scan1.target.seeds.get("2001:4860:4860::888c") is None
|
|
102
|
+
assert scan1.target.whitelist.get("2001:4860:4860::888c") is None
|
|
103
|
+
assert str(scan1.target.seeds.get("www.api.publicapis.org").host) == "api.publicapis.org"
|
|
104
|
+
assert str(scan1.target.whitelist.get("www.api.publicapis.org").host) == "api.publicapis.org"
|
|
105
|
+
assert scan1.target.seeds.get("publicapis.org") is None
|
|
106
|
+
assert scan1.target.whitelist.get("publicapis.org") is None
|
|
107
|
+
|
|
108
|
+
target = RadixTarget("evilcorp.com")
|
|
109
|
+
assert "com" not in target
|
|
82
110
|
assert "evilcorp.com" in target
|
|
83
111
|
assert "www.evilcorp.com" in target
|
|
84
|
-
strict_target =
|
|
85
|
-
assert
|
|
112
|
+
strict_target = RadixTarget("evilcorp.com", strict_dns_scope=True)
|
|
113
|
+
assert "com" not in strict_target
|
|
86
114
|
assert "evilcorp.com" in strict_target
|
|
87
|
-
assert
|
|
115
|
+
assert "www.evilcorp.com" not in strict_target
|
|
88
116
|
|
|
89
|
-
target =
|
|
117
|
+
target = RadixTarget()
|
|
90
118
|
target.add("evilcorp.com")
|
|
91
|
-
assert
|
|
119
|
+
assert "com" not in target
|
|
92
120
|
assert "evilcorp.com" in target
|
|
93
121
|
assert "www.evilcorp.com" in target
|
|
94
|
-
strict_target =
|
|
122
|
+
strict_target = RadixTarget(strict_dns_scope=True)
|
|
95
123
|
strict_target.add("evilcorp.com")
|
|
96
|
-
assert
|
|
124
|
+
assert "com" not in strict_target
|
|
97
125
|
assert "evilcorp.com" in strict_target
|
|
98
|
-
assert
|
|
126
|
+
assert "www.evilcorp.com" not in strict_target
|
|
99
127
|
|
|
100
128
|
# test target hashing
|
|
101
129
|
|
|
102
|
-
target1 =
|
|
103
|
-
target1.add("evilcorp.com")
|
|
104
|
-
target1.add("1.2.3.4/24")
|
|
105
|
-
target1.add("https://evilcorp.net:8080")
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
target2
|
|
111
|
-
target2.add("
|
|
130
|
+
target1 = BBOTTarget()
|
|
131
|
+
target1.whitelist.add("evilcorp.com")
|
|
132
|
+
target1.whitelist.add("1.2.3.4/24")
|
|
133
|
+
target1.whitelist.add("https://evilcorp.net:8080")
|
|
134
|
+
target1.seeds.add("evilcorp.com")
|
|
135
|
+
target1.seeds.add("1.2.3.4/24")
|
|
136
|
+
target1.seeds.add("https://evilcorp.net:8080")
|
|
137
|
+
|
|
138
|
+
target2 = BBOTTarget()
|
|
139
|
+
target2.whitelist.add("bob@evilcorp.org")
|
|
140
|
+
target2.whitelist.add("evilcorp.com")
|
|
141
|
+
target2.whitelist.add("1.2.3.4/24")
|
|
142
|
+
target2.whitelist.add("https://evilcorp.net:8080")
|
|
143
|
+
target2.seeds.add("bob@evilcorp.org")
|
|
144
|
+
target2.seeds.add("evilcorp.com")
|
|
145
|
+
target2.seeds.add("1.2.3.4/24")
|
|
146
|
+
target2.seeds.add("https://evilcorp.net:8080")
|
|
112
147
|
|
|
113
148
|
# make sure it's a sha1 hash
|
|
114
149
|
assert isinstance(target1.hash, bytes)
|
|
@@ -116,11 +151,22 @@ async def test_target(bbot_scanner):
|
|
|
116
151
|
|
|
117
152
|
# hashes shouldn't match yet
|
|
118
153
|
assert target1.hash != target2.hash
|
|
154
|
+
assert target1.scope_hash != target2.scope_hash
|
|
119
155
|
# add missing email
|
|
120
|
-
target1.add("bob@evilcorp.org")
|
|
156
|
+
target1.whitelist.add("bob@evilcorp.org")
|
|
157
|
+
assert target1.hash != target2.hash
|
|
158
|
+
assert target1.scope_hash == target2.scope_hash
|
|
159
|
+
target1.seeds.add("bob@evilcorp.org")
|
|
121
160
|
# now they should match
|
|
122
161
|
assert target1.hash == target2.hash
|
|
123
162
|
|
|
163
|
+
# test default whitelist
|
|
164
|
+
bbottarget = BBOTTarget("http://1.2.3.4:8443", "bob@evilcorp.com")
|
|
165
|
+
assert bbottarget.seeds.hosts == {ip_network("1.2.3.4"), "evilcorp.com"}
|
|
166
|
+
assert bbottarget.whitelist.hosts == {ip_network("1.2.3.4"), "evilcorp.com"}
|
|
167
|
+
assert {e.data for e in bbottarget.seeds.events} == {"http://1.2.3.4:8443/", "bob@evilcorp.com"}
|
|
168
|
+
assert {e.data for e in bbottarget.whitelist.events} == {"1.2.3.4", "evilcorp.com"}
|
|
169
|
+
|
|
124
170
|
bbottarget1 = BBOTTarget("evilcorp.com", "evilcorp.net", whitelist=["1.2.3.4/24"], blacklist=["1.2.3.4"])
|
|
125
171
|
bbottarget2 = BBOTTarget("evilcorp.com", "evilcorp.net", whitelist=["1.2.3.0/24"], blacklist=["1.2.3.4"])
|
|
126
172
|
bbottarget3 = BBOTTarget("evilcorp.com", whitelist=["1.2.3.4/24"], blacklist=["1.2.3.4"])
|
|
@@ -137,14 +183,23 @@ async def test_target(bbot_scanner):
|
|
|
137
183
|
|
|
138
184
|
assert bbottarget1 == bbottarget2
|
|
139
185
|
assert bbottarget2 == bbottarget1
|
|
186
|
+
# 1 and 3 have different seeds
|
|
140
187
|
assert bbottarget1 != bbottarget3
|
|
141
188
|
assert bbottarget3 != bbottarget1
|
|
142
|
-
|
|
189
|
+
# until we make them the same
|
|
190
|
+
bbottarget3.seeds.add("evilcorp.net")
|
|
143
191
|
assert bbottarget1 == bbottarget3
|
|
144
192
|
assert bbottarget3 == bbottarget1
|
|
145
193
|
|
|
146
|
-
|
|
147
|
-
|
|
194
|
+
# adding different events (but with same host) to whitelist should not change hash (since only hosts matter)
|
|
195
|
+
bbottarget1.whitelist.add("http://evilcorp.co.nz")
|
|
196
|
+
bbottarget2.whitelist.add("evilcorp.co.nz")
|
|
197
|
+
assert bbottarget1 == bbottarget2
|
|
198
|
+
assert bbottarget2 == bbottarget1
|
|
199
|
+
|
|
200
|
+
# but seeds should change hash
|
|
201
|
+
bbottarget1.seeds.add("http://evilcorp.co.nz")
|
|
202
|
+
bbottarget2.seeds.add("evilcorp.co.nz")
|
|
148
203
|
assert bbottarget1 != bbottarget2
|
|
149
204
|
assert bbottarget2 != bbottarget1
|
|
150
205
|
|
|
@@ -156,15 +211,11 @@ async def test_target(bbot_scanner):
|
|
|
156
211
|
assert bbottarget8 != bbottarget9
|
|
157
212
|
assert bbottarget9 != bbottarget8
|
|
158
213
|
|
|
159
|
-
bbottarget10 = bbottarget9.copy()
|
|
160
|
-
assert bbottarget10 == bbottarget9
|
|
161
|
-
assert bbottarget9 == bbottarget10
|
|
162
|
-
|
|
163
214
|
# make sure duplicate events don't change hash
|
|
164
|
-
target1 =
|
|
165
|
-
target2 =
|
|
215
|
+
target1 = BBOTTarget("https://evilcorp.com")
|
|
216
|
+
target2 = BBOTTarget("https://evilcorp.com")
|
|
166
217
|
assert target1 == target2
|
|
167
|
-
target1.add("https://evilcorp.com:443")
|
|
218
|
+
target1.seeds.add("https://evilcorp.com:443")
|
|
168
219
|
assert target1 == target2
|
|
169
220
|
|
|
170
221
|
# make sure hosts are collapsed in whitelist and blacklist
|
|
@@ -173,24 +224,26 @@ async def test_target(bbot_scanner):
|
|
|
173
224
|
whitelist=["evilcorp.net:443", "http://evilcorp.net:8080"],
|
|
174
225
|
blacklist=["http://evilcorp.org:8080", "evilcorp.org:443"],
|
|
175
226
|
)
|
|
176
|
-
|
|
227
|
+
# base class is not iterable
|
|
228
|
+
with pytest.raises(TypeError):
|
|
229
|
+
assert list(bbottarget) == ["http://evilcorp.com:8080"]
|
|
177
230
|
assert list(bbottarget.seeds) == ["http://evilcorp.com:8080"]
|
|
178
|
-
assert
|
|
179
|
-
assert
|
|
231
|
+
assert {e.data for e in bbottarget.whitelist} == {"evilcorp.net:443", "http://evilcorp.net:8080/"}
|
|
232
|
+
assert {e.data for e in bbottarget.blacklist} == {"http://evilcorp.org:8080/", "evilcorp.org:443"}
|
|
180
233
|
|
|
181
234
|
# test org stub as target
|
|
182
235
|
for org_target in ("ORG:evilcorp", "ORG_STUB:evilcorp"):
|
|
183
236
|
scan = bbot_scanner(org_target)
|
|
184
237
|
events = [e async for e in scan.async_start()]
|
|
185
|
-
assert len(events) ==
|
|
186
|
-
assert
|
|
238
|
+
assert len(events) == 3
|
|
239
|
+
assert {e.type for e in events} == {"SCAN", "ORG_STUB"}
|
|
187
240
|
|
|
188
241
|
# test username as target
|
|
189
242
|
for user_target in ("USER:vancerefrigeration", "USERNAME:vancerefrigeration"):
|
|
190
243
|
scan = bbot_scanner(user_target)
|
|
191
244
|
events = [e async for e in scan.async_start()]
|
|
192
|
-
assert len(events) ==
|
|
193
|
-
assert
|
|
245
|
+
assert len(events) == 3
|
|
246
|
+
assert {e.type for e in events} == {"SCAN", "USERNAME"}
|
|
194
247
|
|
|
195
248
|
# verify hash values
|
|
196
249
|
bbottarget = BBOTTarget(
|
|
@@ -200,21 +253,30 @@ async def test_target(bbot_scanner):
|
|
|
200
253
|
whitelist=["evilcorp.com", "bob@www.evilcorp.com", "evilcorp.net"],
|
|
201
254
|
blacklist=["1.2.3.4", "4.3.2.1/24", "http://1.2.3.4", "bob@asdf.evilcorp.net"],
|
|
202
255
|
)
|
|
203
|
-
assert
|
|
256
|
+
assert {e.data for e in bbottarget.seeds.events} == {
|
|
204
257
|
"1.2.3.0/24",
|
|
205
258
|
"http://www.evilcorp.net/",
|
|
206
259
|
"bob@fdsa.evilcorp.net",
|
|
207
260
|
}
|
|
208
|
-
assert
|
|
209
|
-
|
|
261
|
+
assert {e.data for e in bbottarget.whitelist.events} == {
|
|
262
|
+
"evilcorp.com",
|
|
263
|
+
"evilcorp.net",
|
|
264
|
+
"bob@www.evilcorp.com",
|
|
265
|
+
}
|
|
266
|
+
assert {e.data for e in bbottarget.blacklist.events} == {
|
|
267
|
+
"1.2.3.4",
|
|
268
|
+
"4.3.2.0/24",
|
|
269
|
+
"http://1.2.3.4/",
|
|
270
|
+
"bob@asdf.evilcorp.net",
|
|
271
|
+
}
|
|
210
272
|
assert set(bbottarget.seeds.hosts) == {ip_network("1.2.3.0/24"), "www.evilcorp.net", "fdsa.evilcorp.net"}
|
|
211
273
|
assert set(bbottarget.whitelist.hosts) == {"evilcorp.com", "evilcorp.net"}
|
|
212
|
-
assert set(bbottarget.blacklist.hosts) == {
|
|
213
|
-
assert bbottarget.hash == b"\
|
|
214
|
-
assert bbottarget.scope_hash == b"\
|
|
215
|
-
assert bbottarget.seeds.hash == b"\
|
|
216
|
-
assert bbottarget.whitelist.hash == b"\
|
|
217
|
-
assert bbottarget.blacklist.hash == b
|
|
274
|
+
assert set(bbottarget.blacklist.hosts) == {ip_network("1.2.3.4/32"), ip_network("4.3.2.0/24"), "asdf.evilcorp.net"}
|
|
275
|
+
assert bbottarget.hash == b"\xb3iU\xa8#\x8aq\x84/\xc5\xf2;\x11\x11\x0c&\xea\x07\xd4Q"
|
|
276
|
+
assert bbottarget.scope_hash == b"f\xe1\x01c^3\xf5\xd24B\x87P\xa0Glq0p3J"
|
|
277
|
+
assert bbottarget.seeds.hash == b"V\n\xf5\x1d\x1f=i\xbc\\\x15o\xc2p\xb2\x84\x97\xfeR\xde\xc1"
|
|
278
|
+
assert bbottarget.whitelist.hash == b"\x8e\xd0\xa76\x8em4c\x0e\x1c\xfdA\x9d*sv}\xeb\xc4\xc4"
|
|
279
|
+
assert bbottarget.blacklist.hash == b'\xf7\xaf\xa1\xda4"C:\x13\xf42\xc3,\xc3\xa9\x9f\x15\x15n\\'
|
|
218
280
|
|
|
219
281
|
scan = bbot_scanner(
|
|
220
282
|
"http://www.evilcorp.net",
|
|
@@ -225,85 +287,120 @@ async def test_target(bbot_scanner):
|
|
|
225
287
|
)
|
|
226
288
|
events = [e async for e in scan.async_start()]
|
|
227
289
|
scan_events = [e for e in events if e.type == "SCAN"]
|
|
228
|
-
assert len(scan_events) ==
|
|
290
|
+
assert len(scan_events) == 2
|
|
229
291
|
target_dict = scan_events[0].data["target"]
|
|
230
|
-
|
|
231
|
-
assert target_dict["
|
|
232
|
-
assert target_dict["
|
|
233
|
-
assert target_dict["
|
|
234
|
-
assert target_dict["
|
|
235
|
-
assert target_dict["
|
|
236
|
-
assert target_dict["
|
|
237
|
-
assert target_dict["
|
|
238
|
-
assert target_dict["
|
|
239
|
-
assert target_dict["
|
|
240
|
-
assert target_dict["blacklist_hash"] == "af0e8ae94a5a86beeea9a9db30af27238420552f"
|
|
241
|
-
|
|
242
|
-
# test target sorting
|
|
243
|
-
big_subnet = scan.make_event("1.2.3.4/24", dummy=True)
|
|
244
|
-
medium_subnet = scan.make_event("1.2.3.4/28", dummy=True)
|
|
245
|
-
small_subnet = scan.make_event("1.2.3.4/30", dummy=True)
|
|
246
|
-
ip_event = scan.make_event("1.2.3.4", dummy=True)
|
|
247
|
-
parent_domain = scan.make_event("evilcorp.com", dummy=True)
|
|
248
|
-
grandparent_domain = scan.make_event("www.evilcorp.com", dummy=True)
|
|
249
|
-
greatgrandparent_domain = scan.make_event("api.www.evilcorp.com", dummy=True)
|
|
250
|
-
target = Target()
|
|
251
|
-
assert big_subnet._host_size == -256
|
|
252
|
-
assert medium_subnet._host_size == -16
|
|
253
|
-
assert small_subnet._host_size == -4
|
|
254
|
-
assert ip_event._host_size == 1
|
|
255
|
-
assert parent_domain._host_size == 12
|
|
256
|
-
assert grandparent_domain._host_size == 16
|
|
257
|
-
assert greatgrandparent_domain._host_size == 20
|
|
258
|
-
events = [
|
|
259
|
-
big_subnet,
|
|
260
|
-
medium_subnet,
|
|
261
|
-
small_subnet,
|
|
262
|
-
ip_event,
|
|
263
|
-
parent_domain,
|
|
264
|
-
grandparent_domain,
|
|
265
|
-
greatgrandparent_domain,
|
|
266
|
-
]
|
|
267
|
-
random.shuffle(events)
|
|
268
|
-
assert target._sort_events(events) == [
|
|
269
|
-
big_subnet,
|
|
270
|
-
medium_subnet,
|
|
271
|
-
small_subnet,
|
|
272
|
-
ip_event,
|
|
273
|
-
parent_domain,
|
|
274
|
-
grandparent_domain,
|
|
275
|
-
greatgrandparent_domain,
|
|
276
|
-
]
|
|
292
|
+
|
|
293
|
+
assert target_dict["seeds"] == ["1.2.3.0/24", "bob@fdsa.evilcorp.net", "http://www.evilcorp.net/"]
|
|
294
|
+
assert target_dict["whitelist"] == ["bob@www.evilcorp.com", "evilcorp.com", "evilcorp.net"]
|
|
295
|
+
assert target_dict["blacklist"] == ["1.2.3.4", "4.3.2.0/24", "bob@asdf.evilcorp.net", "http://1.2.3.4/"]
|
|
296
|
+
assert target_dict["strict_scope"] is False
|
|
297
|
+
assert target_dict["hash"] == "b36955a8238a71842fc5f23b11110c26ea07d451"
|
|
298
|
+
assert target_dict["seed_hash"] == "560af51d1f3d69bc5c156fc270b28497fe52dec1"
|
|
299
|
+
assert target_dict["whitelist_hash"] == "8ed0a7368e6d34630e1cfd419d2a73767debc4c4"
|
|
300
|
+
assert target_dict["blacklist_hash"] == "f7afa1da3422433a13f432c32cc3a99f15156e5c"
|
|
301
|
+
assert target_dict["scope_hash"] == "66e101635e33f5d234428750a0476c713070334a"
|
|
277
302
|
|
|
278
303
|
# make sure child subnets/IPs don't get added to whitelist/blacklist
|
|
279
|
-
target =
|
|
280
|
-
assert set(
|
|
281
|
-
target =
|
|
282
|
-
assert set(
|
|
283
|
-
target =
|
|
284
|
-
assert set(
|
|
285
|
-
target =
|
|
286
|
-
assert set(
|
|
304
|
+
target = RadixTarget("1.2.3.4/24", "1.2.3.4/28", acl_mode=True)
|
|
305
|
+
assert set(target) == {ip_network("1.2.3.0/24")}
|
|
306
|
+
target = RadixTarget("1.2.3.4/28", "1.2.3.4/24", acl_mode=True)
|
|
307
|
+
assert set(target) == {ip_network("1.2.3.0/24")}
|
|
308
|
+
target = RadixTarget("1.2.3.4/28", "1.2.3.4", acl_mode=True)
|
|
309
|
+
assert set(target) == {ip_network("1.2.3.0/28")}
|
|
310
|
+
target = RadixTarget("1.2.3.4", "1.2.3.4/28", acl_mode=True)
|
|
311
|
+
assert set(target) == {ip_network("1.2.3.0/28")}
|
|
287
312
|
|
|
288
313
|
# same but for domains
|
|
289
|
-
target =
|
|
290
|
-
assert set(
|
|
291
|
-
target =
|
|
292
|
-
assert set(
|
|
314
|
+
target = RadixTarget("evilcorp.com", "www.evilcorp.com", acl_mode=True)
|
|
315
|
+
assert set(target) == {"evilcorp.com"}
|
|
316
|
+
target = RadixTarget("www.evilcorp.com", "evilcorp.com", acl_mode=True)
|
|
317
|
+
assert set(target) == {"evilcorp.com"}
|
|
293
318
|
|
|
294
319
|
# make sure strict_scope doesn't mess us up
|
|
295
|
-
target =
|
|
320
|
+
target = RadixTarget("evilcorp.co.uk", "www.evilcorp.co.uk", acl_mode=True, strict_dns_scope=True)
|
|
296
321
|
assert set(target.hosts) == {"evilcorp.co.uk", "www.evilcorp.co.uk"}
|
|
297
322
|
assert "evilcorp.co.uk" in target
|
|
298
323
|
assert "www.evilcorp.co.uk" in target
|
|
299
|
-
assert
|
|
300
|
-
assert
|
|
324
|
+
assert "api.evilcorp.co.uk" not in target
|
|
325
|
+
assert "api.www.evilcorp.co.uk" not in target
|
|
301
326
|
|
|
302
327
|
# test 'single' boolean argument
|
|
303
|
-
target =
|
|
328
|
+
target = ScanSeeds("http://evilcorp.com", "evilcorp.com:443")
|
|
304
329
|
assert "www.evilcorp.com" in target
|
|
330
|
+
assert "bob@evilcorp.com" in target
|
|
305
331
|
event = target.get("www.evilcorp.com")
|
|
306
332
|
assert event.host == "evilcorp.com"
|
|
307
333
|
events = target.get("www.evilcorp.com", single=False)
|
|
308
334
|
assert len(events) == 2
|
|
309
|
-
assert
|
|
335
|
+
assert {e.data for e in events} == {"http://evilcorp.com/", "evilcorp.com:443"}
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
@pytest.mark.asyncio
|
|
339
|
+
async def test_blacklist_regex(bbot_scanner, bbot_httpserver):
|
|
340
|
+
from bbot.scanner.target import ScanBlacklist
|
|
341
|
+
|
|
342
|
+
blacklist = ScanBlacklist("evilcorp.com")
|
|
343
|
+
assert blacklist.inputs == {"evilcorp.com"}
|
|
344
|
+
assert "www.evilcorp.com" in blacklist
|
|
345
|
+
assert "http://www.evilcorp.com" in blacklist
|
|
346
|
+
blacklist.add("RE:test")
|
|
347
|
+
assert "RE:test" in blacklist.inputs
|
|
348
|
+
assert set(blacklist.inputs) == {"evilcorp.com", "RE:test"}
|
|
349
|
+
assert blacklist.blacklist_regexes
|
|
350
|
+
assert next(iter(blacklist.blacklist_regexes)).pattern == "test"
|
|
351
|
+
result1 = blacklist.get("test.com")
|
|
352
|
+
assert result1.type == "DNS_NAME"
|
|
353
|
+
assert result1.data == "test.com"
|
|
354
|
+
result2 = blacklist.get("www.evilcorp.com")
|
|
355
|
+
assert result2.type == "DNS_NAME"
|
|
356
|
+
assert result2.data == "evilcorp.com"
|
|
357
|
+
result2 = blacklist.get("www.evil.com")
|
|
358
|
+
assert result2 is None
|
|
359
|
+
with pytest.raises(KeyError):
|
|
360
|
+
blacklist.get("www.evil.com", raise_error=True)
|
|
361
|
+
assert "test.com" in blacklist
|
|
362
|
+
assert "http://evilcorp.com/test.aspx" in blacklist
|
|
363
|
+
assert "http://tes.com" not in blacklist
|
|
364
|
+
|
|
365
|
+
blacklist = ScanBlacklist("evilcorp.com", r"RE:[0-9]{6}\.aspx$")
|
|
366
|
+
assert "http://evilcorp.com" in blacklist
|
|
367
|
+
assert "http://test.com/123456" not in blacklist
|
|
368
|
+
assert "http://test.com/12345.aspx?a=asdf" not in blacklist
|
|
369
|
+
assert "http://test.com/asdf/123456.aspx/asdf" not in blacklist
|
|
370
|
+
assert "http://test.com/asdf/123456.aspx?a=asdf" in blacklist
|
|
371
|
+
assert "http://test.com/asdf/123456.aspx" in blacklist
|
|
372
|
+
|
|
373
|
+
bbot_httpserver.expect_request(uri="/").respond_with_data(
|
|
374
|
+
"""
|
|
375
|
+
<a href='http://127.0.0.1:8888/asdfevil333asdf'/>
|
|
376
|
+
<a href='http://127.0.0.1:8888/logout.aspx'/>
|
|
377
|
+
"""
|
|
378
|
+
)
|
|
379
|
+
bbot_httpserver.expect_request(uri="/asdfevilasdf").respond_with_data("")
|
|
380
|
+
bbot_httpserver.expect_request(uri="/logout.aspx").respond_with_data("")
|
|
381
|
+
|
|
382
|
+
# make sure URL is detected normally
|
|
383
|
+
scan = bbot_scanner("http://127.0.0.1:8888/", presets=["spider"], config={"excavate": True}, debug=True)
|
|
384
|
+
assert {r.pattern for r in scan.target.blacklist.blacklist_regexes} == {r"/.*(sign|log)[_-]?out"}
|
|
385
|
+
events = [e async for e in scan.async_start()]
|
|
386
|
+
urls = [e.data for e in events if e.type == "URL"]
|
|
387
|
+
assert len(urls) == 2
|
|
388
|
+
assert set(urls) == {"http://127.0.0.1:8888/", "http://127.0.0.1:8888/asdfevil333asdf"}
|
|
389
|
+
|
|
390
|
+
# same scan again but with blacklist regex
|
|
391
|
+
scan = bbot_scanner(
|
|
392
|
+
"http://127.0.0.1:8888/",
|
|
393
|
+
blacklist=[r"RE:evil[0-9]{3}"],
|
|
394
|
+
presets=["spider"],
|
|
395
|
+
config={"excavate": True},
|
|
396
|
+
debug=True,
|
|
397
|
+
)
|
|
398
|
+
assert scan.target.blacklist.blacklist_regexes
|
|
399
|
+
assert {r.pattern for r in scan.target.blacklist.blacklist_regexes} == {
|
|
400
|
+
r"evil[0-9]{3}",
|
|
401
|
+
r"/.*(sign|log)[_-]?out",
|
|
402
|
+
}
|
|
403
|
+
events = [e async for e in scan.async_start()]
|
|
404
|
+
urls = [e.data for e in events if e.type == "URL"]
|
|
405
|
+
assert len(urls) == 1
|
|
406
|
+
assert set(urls) == {"http://127.0.0.1:8888/"}
|