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
|
@@ -4,19 +4,28 @@ import ipaddress
|
|
|
4
4
|
|
|
5
5
|
from ..bbot_fixtures import *
|
|
6
6
|
from bbot.scanner import Scanner
|
|
7
|
+
from bbot.core.helpers.regexes import event_uuid_regex
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
@pytest.mark.asyncio
|
|
10
11
|
async def test_events(events, helpers):
|
|
11
|
-
|
|
12
12
|
scan = Scanner()
|
|
13
13
|
await scan._prep()
|
|
14
14
|
|
|
15
15
|
assert events.ipv4.type == "IP_ADDRESS"
|
|
16
|
+
assert events.ipv4.netloc == "8.8.8.8"
|
|
17
|
+
assert events.ipv4.port is None
|
|
16
18
|
assert events.ipv6.type == "IP_ADDRESS"
|
|
19
|
+
assert events.ipv6.netloc == "[2001:4860:4860::8888]"
|
|
20
|
+
assert events.ipv6.port is None
|
|
21
|
+
assert events.ipv6_open_port.netloc == "[2001:4860:4860::8888]:443"
|
|
17
22
|
assert events.netv4.type == "IP_RANGE"
|
|
23
|
+
assert events.netv4.netloc is None
|
|
24
|
+
assert "netloc" not in events.netv4.json()
|
|
18
25
|
assert events.netv6.type == "IP_RANGE"
|
|
19
26
|
assert events.domain.type == "DNS_NAME"
|
|
27
|
+
assert events.domain.netloc == "publicapis.org"
|
|
28
|
+
assert events.domain.port is None
|
|
20
29
|
assert "domain" in events.domain.tags
|
|
21
30
|
assert events.subdomain.type == "DNS_NAME"
|
|
22
31
|
assert "subdomain" in events.subdomain.tags
|
|
@@ -32,6 +41,7 @@ async def test_events(events, helpers):
|
|
|
32
41
|
# ip tests
|
|
33
42
|
assert events.ipv4 == scan.make_event("8.8.8.8", dummy=True)
|
|
34
43
|
assert "8.8.8.8" in events.ipv4
|
|
44
|
+
assert events.ipv4.host_filterable == "8.8.8.8"
|
|
35
45
|
assert "8.8.8.8" == events.ipv4
|
|
36
46
|
assert "8.8.8.8" in events.netv4
|
|
37
47
|
assert "8.8.8.9" not in events.ipv4
|
|
@@ -49,11 +59,19 @@ async def test_events(events, helpers):
|
|
|
49
59
|
assert events.emoji not in events.ipv4
|
|
50
60
|
assert events.emoji not in events.netv6
|
|
51
61
|
assert events.netv6 not in events.emoji
|
|
52
|
-
|
|
62
|
+
ipv6_event = scan.make_event(" [DEaD::c0De]:88", "DNS_NAME", dummy=True)
|
|
63
|
+
assert "dead::c0de" == ipv6_event
|
|
64
|
+
assert ipv6_event.host_filterable == "dead::c0de"
|
|
65
|
+
range_to_ip = scan.make_event("1.2.3.4/32", dummy=True)
|
|
66
|
+
assert range_to_ip.type == "IP_ADDRESS"
|
|
67
|
+
range_to_ip = scan.make_event("dead::beef/128", dummy=True)
|
|
68
|
+
assert range_to_ip.type == "IP_ADDRESS"
|
|
53
69
|
|
|
54
70
|
# hostname tests
|
|
55
71
|
assert events.domain.host == "publicapis.org"
|
|
72
|
+
assert events.domain.host_filterable == "publicapis.org"
|
|
56
73
|
assert events.subdomain.host == "api.publicapis.org"
|
|
74
|
+
assert events.subdomain.host_filterable == "api.publicapis.org"
|
|
57
75
|
assert events.domain.host_stem == "publicapis"
|
|
58
76
|
assert events.subdomain.host_stem == "api.publicapis"
|
|
59
77
|
assert "api.publicapis.org" in events.domain
|
|
@@ -62,23 +80,39 @@ async def test_events(events, helpers):
|
|
|
62
80
|
assert "fsocie.ty" not in events.subdomain
|
|
63
81
|
assert events.subdomain in events.domain
|
|
64
82
|
assert events.domain not in events.subdomain
|
|
65
|
-
assert
|
|
66
|
-
assert
|
|
83
|
+
assert events.ipv4 not in events.domain
|
|
84
|
+
assert events.netv6 not in events.domain
|
|
67
85
|
assert events.emoji not in events.domain
|
|
68
86
|
assert events.domain not in events.emoji
|
|
69
|
-
|
|
70
|
-
|
|
87
|
+
open_port_event = scan.make_event(" eViLcorp.COM.:88", "DNS_NAME", dummy=True)
|
|
88
|
+
dns_event = scan.make_event("evilcorp.com.", "DNS_NAME", dummy=True)
|
|
89
|
+
for e in (open_port_event, dns_event):
|
|
90
|
+
assert "evilcorp.com" == e
|
|
91
|
+
assert e.netloc == "evilcorp.com"
|
|
92
|
+
assert e.json()["netloc"] == "evilcorp.com"
|
|
93
|
+
assert e.port is None
|
|
94
|
+
assert "port" not in e.json()
|
|
71
95
|
|
|
72
96
|
# url tests
|
|
73
|
-
|
|
97
|
+
url_no_trailing_slash = scan.make_event("http://evilcorp.com", dummy=True)
|
|
98
|
+
url_trailing_slash = scan.make_event("http://evilcorp.com/", dummy=True)
|
|
99
|
+
assert url_no_trailing_slash == url_trailing_slash
|
|
100
|
+
assert url_no_trailing_slash.host_filterable == "http://evilcorp.com/"
|
|
101
|
+
assert url_trailing_slash.host_filterable == "http://evilcorp.com/"
|
|
74
102
|
assert events.url_unverified.host == "api.publicapis.org"
|
|
75
103
|
assert events.url_unverified in events.domain
|
|
76
104
|
assert events.url_unverified in events.subdomain
|
|
77
105
|
assert "api.publicapis.org:443" in events.url_unverified
|
|
78
106
|
assert "publicapis.org" not in events.url_unverified
|
|
79
107
|
assert events.ipv4_url_unverified in events.ipv4
|
|
108
|
+
assert events.ipv4_url_unverified.netloc == "8.8.8.8:443"
|
|
109
|
+
assert events.ipv4_url_unverified.port == 443
|
|
110
|
+
assert events.ipv4_url_unverified.json()["port"] == 443
|
|
80
111
|
assert events.ipv4_url_unverified in events.netv4
|
|
81
112
|
assert events.ipv6_url_unverified in events.ipv6
|
|
113
|
+
assert events.ipv6_url_unverified.netloc == "[2001:4860:4860::8888]:443"
|
|
114
|
+
assert events.ipv6_url_unverified.port == 443
|
|
115
|
+
assert events.ipv6_url_unverified.json()["port"] == 443
|
|
82
116
|
assert events.ipv6_url_unverified in events.netv6
|
|
83
117
|
assert events.emoji not in events.url_unverified
|
|
84
118
|
assert events.emoji not in events.ipv6_url_unverified
|
|
@@ -107,6 +141,7 @@ async def test_events(events, helpers):
|
|
|
107
141
|
assert events.http_response.port == 80
|
|
108
142
|
assert events.http_response.parsed_url.scheme == "http"
|
|
109
143
|
assert events.http_response.with_port().geturl() == "http://example.com:80/"
|
|
144
|
+
assert events.http_response.host_filterable == "http://example.com/"
|
|
110
145
|
|
|
111
146
|
http_response = scan.make_event(
|
|
112
147
|
{
|
|
@@ -171,7 +206,7 @@ async def test_events(events, helpers):
|
|
|
171
206
|
|
|
172
207
|
# scope distance
|
|
173
208
|
event1 = scan.make_event("1.2.3.4", dummy=True)
|
|
174
|
-
assert event1._scope_distance
|
|
209
|
+
assert event1._scope_distance is None
|
|
175
210
|
event1.scope_distance = 0
|
|
176
211
|
assert event1._scope_distance == 0
|
|
177
212
|
event2 = scan.make_event("2.3.4.5", parent=event1)
|
|
@@ -192,6 +227,8 @@ async def test_events(events, helpers):
|
|
|
192
227
|
|
|
193
228
|
org_stub_1 = scan.make_event("STUB1", "ORG_STUB", parent=scan.root_event)
|
|
194
229
|
org_stub_1.scope_distance == 1
|
|
230
|
+
assert org_stub_1.netloc is None
|
|
231
|
+
assert "netloc" not in org_stub_1.json()
|
|
195
232
|
org_stub_2 = scan.make_event("STUB2", "ORG_STUB", parent=org_stub_1)
|
|
196
233
|
org_stub_2.scope_distance == 2
|
|
197
234
|
|
|
@@ -199,7 +236,7 @@ async def test_events(events, helpers):
|
|
|
199
236
|
root_event = scan.make_event("0.0.0.0", dummy=True)
|
|
200
237
|
root_event.scope_distance = 0
|
|
201
238
|
internal_event1 = scan.make_event("1.2.3.4", parent=root_event, internal=True)
|
|
202
|
-
assert internal_event1._internal
|
|
239
|
+
assert internal_event1._internal is True
|
|
203
240
|
assert "internal" in internal_event1.tags
|
|
204
241
|
|
|
205
242
|
# tag inheritance
|
|
@@ -231,8 +268,8 @@ async def test_events(events, helpers):
|
|
|
231
268
|
# updating module
|
|
232
269
|
event3 = scan.make_event("127.0.0.1", parent=scan.root_event)
|
|
233
270
|
updated_event = scan.make_event(event3, internal=True)
|
|
234
|
-
assert event3.internal
|
|
235
|
-
assert updated_event.internal
|
|
271
|
+
assert event3.internal is False
|
|
272
|
+
assert updated_event.internal is True
|
|
236
273
|
|
|
237
274
|
# event sorting
|
|
238
275
|
parent1 = scan.make_event("127.0.0.1", parent=scan.root_event)
|
|
@@ -412,17 +449,55 @@ async def test_events(events, helpers):
|
|
|
412
449
|
== "http://xn--12c1bik6bbd8ab6hd1b5jc6jta.com/ทดสอบ"
|
|
413
450
|
)
|
|
414
451
|
|
|
452
|
+
# test event uuid
|
|
453
|
+
import uuid
|
|
454
|
+
|
|
455
|
+
parent_event1 = scan.make_event("evilcorp.com", parent=scan.root_event, context="test context")
|
|
456
|
+
parent_event2 = scan.make_event("evilcorp.com", parent=scan.root_event, context="test context")
|
|
457
|
+
|
|
458
|
+
event1 = scan.make_event("evilcorp.com:80", parent=parent_event1, context="test context")
|
|
459
|
+
assert hasattr(event1, "_uuid")
|
|
460
|
+
assert hasattr(event1, "uuid")
|
|
461
|
+
assert isinstance(event1._uuid, uuid.UUID)
|
|
462
|
+
assert isinstance(event1.uuid, str)
|
|
463
|
+
assert event1.uuid == f"{event1.type}:{event1._uuid}"
|
|
464
|
+
event2 = scan.make_event("evilcorp.com:80", parent=parent_event2, context="test context")
|
|
465
|
+
assert hasattr(event2, "_uuid")
|
|
466
|
+
assert hasattr(event2, "uuid")
|
|
467
|
+
assert isinstance(event2._uuid, uuid.UUID)
|
|
468
|
+
assert isinstance(event2.uuid, str)
|
|
469
|
+
assert event2.uuid == f"{event2.type}:{event2._uuid}"
|
|
470
|
+
# ids should match because the event type + data is the same
|
|
471
|
+
assert event1.id == event2.id
|
|
472
|
+
# but uuids should be unique!
|
|
473
|
+
assert event1.uuid != event2.uuid
|
|
474
|
+
# parent ids should match
|
|
475
|
+
assert event1.parent_id == event2.parent_id == parent_event1.id == parent_event2.id
|
|
476
|
+
# uuids should not
|
|
477
|
+
assert event1.parent_uuid == parent_event1.uuid
|
|
478
|
+
assert event2.parent_uuid == parent_event2.uuid
|
|
479
|
+
assert event1.parent_uuid != event2.parent_uuid
|
|
480
|
+
|
|
415
481
|
# test event serialization
|
|
416
482
|
from bbot.core.event import event_from_json
|
|
417
483
|
|
|
418
484
|
db_event = scan.make_event("evilcorp.com:80", parent=scan.root_event, context="test context")
|
|
485
|
+
assert db_event.parent == scan.root_event
|
|
486
|
+
assert db_event.parent is scan.root_event
|
|
419
487
|
db_event._resolved_hosts = {"127.0.0.1"}
|
|
420
488
|
db_event.scope_distance = 1
|
|
421
489
|
assert db_event.discovery_context == "test context"
|
|
422
490
|
assert db_event.discovery_path == ["test context"]
|
|
423
|
-
assert db_event.parent_chain ==
|
|
491
|
+
assert len(db_event.parent_chain) == 1
|
|
492
|
+
assert all(event_uuid_regex.match(u) for u in db_event.parent_chain)
|
|
493
|
+
assert db_event.parent_chain[0] == str(db_event.uuid)
|
|
494
|
+
assert db_event.parent.uuid == scan.root_event.uuid
|
|
495
|
+
assert db_event.parent_uuid == scan.root_event.uuid
|
|
424
496
|
timestamp = db_event.timestamp.isoformat()
|
|
425
497
|
json_event = db_event.json()
|
|
498
|
+
assert isinstance(json_event["uuid"], str)
|
|
499
|
+
assert json_event["uuid"] == str(db_event.uuid)
|
|
500
|
+
assert json_event["parent_uuid"] == str(scan.root_event.uuid)
|
|
426
501
|
assert json_event["scope_distance"] == 1
|
|
427
502
|
assert json_event["data"] == "evilcorp.com:80"
|
|
428
503
|
assert json_event["type"] == "OPEN_TCP_PORT"
|
|
@@ -430,8 +505,14 @@ async def test_events(events, helpers):
|
|
|
430
505
|
assert json_event["timestamp"] == timestamp
|
|
431
506
|
assert json_event["discovery_context"] == "test context"
|
|
432
507
|
assert json_event["discovery_path"] == ["test context"]
|
|
433
|
-
assert json_event["parent_chain"] ==
|
|
508
|
+
assert json_event["parent_chain"] == db_event.parent_chain
|
|
509
|
+
assert json_event["parent_chain"][0] == str(db_event.uuid)
|
|
434
510
|
reconstituted_event = event_from_json(json_event)
|
|
511
|
+
assert isinstance(reconstituted_event._uuid, uuid.UUID)
|
|
512
|
+
assert str(reconstituted_event.uuid) == json_event["uuid"]
|
|
513
|
+
assert str(reconstituted_event.parent_uuid) == json_event["parent_uuid"]
|
|
514
|
+
assert reconstituted_event.uuid == db_event.uuid
|
|
515
|
+
assert reconstituted_event.parent_uuid == scan.root_event.uuid
|
|
435
516
|
assert reconstituted_event.scope_distance == 1
|
|
436
517
|
assert reconstituted_event.timestamp.isoformat() == timestamp
|
|
437
518
|
assert reconstituted_event.data == "evilcorp.com:80"
|
|
@@ -439,13 +520,13 @@ async def test_events(events, helpers):
|
|
|
439
520
|
assert reconstituted_event.host == "evilcorp.com"
|
|
440
521
|
assert reconstituted_event.discovery_context == "test context"
|
|
441
522
|
assert reconstituted_event.discovery_path == ["test context"]
|
|
442
|
-
assert reconstituted_event.parent_chain ==
|
|
523
|
+
assert reconstituted_event.parent_chain == db_event.parent_chain
|
|
443
524
|
assert "127.0.0.1" in reconstituted_event.resolved_hosts
|
|
444
525
|
hostless_event = scan.make_event("asdf", "ASDF", dummy=True)
|
|
445
526
|
hostless_event_json = hostless_event.json()
|
|
446
527
|
assert hostless_event_json["type"] == "ASDF"
|
|
447
528
|
assert hostless_event_json["data"] == "asdf"
|
|
448
|
-
assert
|
|
529
|
+
assert "host" not in hostless_event_json
|
|
449
530
|
|
|
450
531
|
# SIEM-friendly serialize/deserialize
|
|
451
532
|
json_event_siemfriendly = db_event.json(siem_friendly=True)
|
|
@@ -535,7 +616,6 @@ async def test_events(events, helpers):
|
|
|
535
616
|
|
|
536
617
|
@pytest.mark.asyncio
|
|
537
618
|
async def test_event_discovery_context():
|
|
538
|
-
|
|
539
619
|
from bbot.modules.base import BaseModule
|
|
540
620
|
|
|
541
621
|
scan = Scanner("evilcorp.com")
|
|
@@ -616,7 +696,7 @@ async def test_event_discovery_context():
|
|
|
616
696
|
)
|
|
617
697
|
|
|
618
698
|
events = [e async for e in scan.async_start()]
|
|
619
|
-
assert len(events) ==
|
|
699
|
+
assert len(events) == 7
|
|
620
700
|
|
|
621
701
|
assert 1 == len(
|
|
622
702
|
[
|
|
@@ -723,7 +803,7 @@ async def test_event_web_spider_distance(bbot_scanner):
|
|
|
723
803
|
)
|
|
724
804
|
assert url_event_3.web_spider_distance == 1
|
|
725
805
|
assert "spider-danger" in url_event_3.tags
|
|
726
|
-
assert
|
|
806
|
+
assert "spider-max" not in url_event_3.tags
|
|
727
807
|
social_event = scan.make_event(
|
|
728
808
|
{"platform": "github", "url": "http://www.evilcorp.com/test4"}, "SOCIAL", parent=url_event_3
|
|
729
809
|
)
|
|
@@ -746,42 +826,42 @@ async def test_event_web_spider_distance(bbot_scanner):
|
|
|
746
826
|
|
|
747
827
|
url_event = scan.make_event("http://www.evilcorp.com", "URL_UNVERIFIED", parent=scan.root_event)
|
|
748
828
|
assert url_event.web_spider_distance == 0
|
|
749
|
-
assert
|
|
750
|
-
assert
|
|
829
|
+
assert "spider-danger" not in url_event.tags
|
|
830
|
+
assert "spider-max" not in url_event.tags
|
|
751
831
|
url_event_2 = scan.make_event(
|
|
752
832
|
"http://www.evilcorp.com", "URL_UNVERIFIED", parent=scan.root_event, tags="spider-danger"
|
|
753
833
|
)
|
|
754
834
|
# spider distance shouldn't increment because it's not the same host
|
|
755
835
|
assert url_event_2.web_spider_distance == 0
|
|
756
836
|
assert "spider-danger" in url_event_2.tags
|
|
757
|
-
assert
|
|
837
|
+
assert "spider-max" not in url_event_2.tags
|
|
758
838
|
url_event_3 = scan.make_event(
|
|
759
839
|
"http://www.evilcorp.com/3", "URL_UNVERIFIED", parent=url_event_2, tags="spider-danger"
|
|
760
840
|
)
|
|
761
841
|
assert url_event_3.web_spider_distance == 1
|
|
762
842
|
assert "spider-danger" in url_event_3.tags
|
|
763
|
-
assert
|
|
843
|
+
assert "spider-max" not in url_event_3.tags
|
|
764
844
|
url_event_4 = scan.make_event("http://evilcorp.com", "URL_UNVERIFIED", parent=url_event_3)
|
|
765
845
|
assert url_event_4.web_spider_distance == 0
|
|
766
|
-
assert
|
|
767
|
-
assert
|
|
846
|
+
assert "spider-danger" not in url_event_4.tags
|
|
847
|
+
assert "spider-max" not in url_event_4.tags
|
|
768
848
|
url_event_4.add_tag("spider-danger")
|
|
769
849
|
assert url_event_4.web_spider_distance == 0
|
|
770
850
|
assert "spider-danger" in url_event_4.tags
|
|
771
|
-
assert
|
|
851
|
+
assert "spider-max" not in url_event_4.tags
|
|
772
852
|
url_event_4.remove_tag("spider-danger")
|
|
773
853
|
assert url_event_4.web_spider_distance == 0
|
|
774
|
-
assert
|
|
775
|
-
assert
|
|
854
|
+
assert "spider-danger" not in url_event_4.tags
|
|
855
|
+
assert "spider-max" not in url_event_4.tags
|
|
776
856
|
url_event_5 = scan.make_event("http://evilcorp.com/5", "URL_UNVERIFIED", parent=url_event_4)
|
|
777
857
|
assert url_event_5.web_spider_distance == 0
|
|
778
|
-
assert
|
|
779
|
-
assert
|
|
858
|
+
assert "spider-danger" not in url_event_5.tags
|
|
859
|
+
assert "spider-max" not in url_event_5.tags
|
|
780
860
|
url_event_5.add_tag("spider-danger")
|
|
781
861
|
# if host is the same as parent, web spider distance should auto-increment after adding spider-danger tag
|
|
782
862
|
assert url_event_5.web_spider_distance == 1
|
|
783
863
|
assert "spider-danger" in url_event_5.tags
|
|
784
|
-
assert
|
|
864
|
+
assert "spider-max" not in url_event_5.tags
|
|
785
865
|
|
|
786
866
|
|
|
787
867
|
def test_event_confidence():
|
|
@@ -856,3 +936,76 @@ def test_event_closest_host():
|
|
|
856
936
|
vuln = scan.make_event(
|
|
857
937
|
{"path": "/tmp/asdf.txt", "description": "test", "severity": "HIGH"}, "VULNERABILITY", parent=event3
|
|
858
938
|
)
|
|
939
|
+
|
|
940
|
+
|
|
941
|
+
def test_event_magic():
|
|
942
|
+
from bbot.core.helpers.libmagic import get_magic_info, get_compression
|
|
943
|
+
|
|
944
|
+
import base64
|
|
945
|
+
|
|
946
|
+
zip_base64 = "UEsDBAoDAAAAAOMmZ1lR4FaHBQAAAAUAAAAIAAAAYXNkZi50eHRhc2RmClBLAQI/AwoDAAAAAOMmZ1lR4FaHBQAAAAUAAAAIACQAAAAAAAAAIICkgQAAAABhc2RmLnR4dAoAIAAAAAAAAQAYAICi2B77MNsBgKLYHvsw2wGAotge+zDbAVBLBQYAAAAAAQABAFoAAAArAAAAAAA="
|
|
947
|
+
zip_bytes = base64.b64decode(zip_base64)
|
|
948
|
+
zip_file = Path("/tmp/.bbottestzipasdkfjalsdf.zip")
|
|
949
|
+
with open(zip_file, "wb") as f:
|
|
950
|
+
f.write(zip_bytes)
|
|
951
|
+
|
|
952
|
+
# test magic helpers
|
|
953
|
+
extension, mime_type, description, confidence = get_magic_info(zip_file)
|
|
954
|
+
assert extension == ".zip"
|
|
955
|
+
assert mime_type == "application/zip"
|
|
956
|
+
assert description == "PKZIP Archive file"
|
|
957
|
+
assert confidence > 0
|
|
958
|
+
assert get_compression(mime_type) == "zip"
|
|
959
|
+
|
|
960
|
+
# test filesystem event - file
|
|
961
|
+
scan = Scanner()
|
|
962
|
+
event = scan.make_event({"path": zip_file}, "FILESYSTEM", parent=scan.root_event)
|
|
963
|
+
assert event.data == {
|
|
964
|
+
"path": "/tmp/.bbottestzipasdkfjalsdf.zip",
|
|
965
|
+
"magic_extension": ".zip",
|
|
966
|
+
"magic_mime_type": "application/zip",
|
|
967
|
+
"magic_description": "PKZIP Archive file",
|
|
968
|
+
"magic_confidence": 0.9,
|
|
969
|
+
"compression": "zip",
|
|
970
|
+
}
|
|
971
|
+
assert event.tags == {"file", "zip-archive", "compressed"}
|
|
972
|
+
|
|
973
|
+
# test filesystem event - folder
|
|
974
|
+
scan = Scanner()
|
|
975
|
+
event = scan.make_event({"path": "/tmp"}, "FILESYSTEM", parent=scan.root_event)
|
|
976
|
+
assert event.data == {"path": "/tmp"}
|
|
977
|
+
assert event.tags == {"folder"}
|
|
978
|
+
|
|
979
|
+
zip_file.unlink()
|
|
980
|
+
|
|
981
|
+
|
|
982
|
+
def test_event_hashing():
|
|
983
|
+
scan = Scanner("example.com")
|
|
984
|
+
url_event = scan.make_event("https://api.example.com/", "URL_UNVERIFIED", parent=scan.root_event)
|
|
985
|
+
host_event_1 = scan.make_event("www.example.com", "DNS_NAME", parent=url_event)
|
|
986
|
+
host_event_2 = scan.make_event("test.example.com", "DNS_NAME", parent=url_event)
|
|
987
|
+
finding_data = {"description": "Custom Yara Rule [find_string] Matched via identifier [str1]"}
|
|
988
|
+
finding1 = scan.make_event(finding_data, "FINDING", parent=host_event_1)
|
|
989
|
+
finding2 = scan.make_event(finding_data, "FINDING", parent=host_event_2)
|
|
990
|
+
finding3 = scan.make_event(finding_data, "FINDING", parent=host_event_2)
|
|
991
|
+
|
|
992
|
+
assert finding1.data == {
|
|
993
|
+
"description": "Custom Yara Rule [find_string] Matched via identifier [str1]",
|
|
994
|
+
"host": "www.example.com",
|
|
995
|
+
}
|
|
996
|
+
assert finding2.data == {
|
|
997
|
+
"description": "Custom Yara Rule [find_string] Matched via identifier [str1]",
|
|
998
|
+
"host": "test.example.com",
|
|
999
|
+
}
|
|
1000
|
+
assert finding3.data == {
|
|
1001
|
+
"description": "Custom Yara Rule [find_string] Matched via identifier [str1]",
|
|
1002
|
+
"host": "test.example.com",
|
|
1003
|
+
}
|
|
1004
|
+
assert finding1.id != finding2.id
|
|
1005
|
+
assert finding2.id == finding3.id
|
|
1006
|
+
assert finding1.data_id != finding2.data_id
|
|
1007
|
+
assert finding2.data_id == finding3.data_id
|
|
1008
|
+
assert finding1.data_hash != finding2.data_hash
|
|
1009
|
+
assert finding2.data_hash == finding3.data_hash
|
|
1010
|
+
assert hash(finding1) != hash(finding2)
|
|
1011
|
+
assert hash(finding2) == hash(finding3)
|
|
@@ -49,6 +49,8 @@ async def test_helpers_misc(helpers, scan, bbot_scanner, bbot_httpserver):
|
|
|
49
49
|
assert helpers.url_depth("http://evilcorp.com/") == 0
|
|
50
50
|
assert helpers.url_depth("http://evilcorp.com") == 0
|
|
51
51
|
|
|
52
|
+
assert helpers.parent_url("http://evilcorp.com/subdir1/subdir2?foo=bar") == "http://evilcorp.com/subdir1"
|
|
53
|
+
|
|
52
54
|
### MISC ###
|
|
53
55
|
assert helpers.is_domain("evilcorp.co.uk")
|
|
54
56
|
assert not helpers.is_domain("www.evilcorp.co.uk")
|
|
@@ -62,8 +64,8 @@ async def test_helpers_misc(helpers, scan, bbot_scanner, bbot_httpserver):
|
|
|
62
64
|
assert not helpers.is_subdomain("notreal")
|
|
63
65
|
assert helpers.is_url("http://evilcorp.co.uk/asdf?a=b&c=d#asdf")
|
|
64
66
|
assert helpers.is_url("https://evilcorp.co.uk/asdf?a=b&c=d#asdf")
|
|
65
|
-
assert helpers.is_uri("ftp://evilcorp.co.uk")
|
|
66
|
-
assert helpers.is_uri("http://evilcorp.co.uk")
|
|
67
|
+
assert helpers.is_uri("ftp://evilcorp.co.uk") is True
|
|
68
|
+
assert helpers.is_uri("http://evilcorp.co.uk") is True
|
|
67
69
|
assert helpers.is_uri("evilcorp.co.uk", return_scheme=True) == ""
|
|
68
70
|
assert helpers.is_uri("ftp://evilcorp.co.uk", return_scheme=True) == "ftp"
|
|
69
71
|
assert helpers.is_uri("FTP://evilcorp.co.uk", return_scheme=True) == "ftp"
|
|
@@ -91,8 +93,34 @@ async def test_helpers_misc(helpers, scan, bbot_scanner, bbot_httpserver):
|
|
|
91
93
|
ipaddress.ip_network("0.0.0.0/0"),
|
|
92
94
|
]
|
|
93
95
|
assert helpers.is_ip("127.0.0.1")
|
|
96
|
+
assert helpers.is_ip("127.0.0.1", include_network=True)
|
|
97
|
+
assert helpers.is_ip("127.0.0.1", version=4)
|
|
98
|
+
assert not helpers.is_ip("127.0.0.1", version=6)
|
|
94
99
|
assert not helpers.is_ip("127.0.0.0.1")
|
|
100
|
+
|
|
101
|
+
assert helpers.is_ip("dead::beef")
|
|
102
|
+
assert helpers.is_ip("dead::beef", include_network=True)
|
|
103
|
+
assert not helpers.is_ip("dead::beef", version=4)
|
|
104
|
+
assert helpers.is_ip("dead::beef", version=6)
|
|
105
|
+
assert not helpers.is_ip("dead:::beef")
|
|
106
|
+
|
|
107
|
+
assert not helpers.is_ip("1.2.3.4/24")
|
|
108
|
+
assert helpers.is_ip("1.2.3.4/24", include_network=True)
|
|
109
|
+
assert not helpers.is_ip("1.2.3.4/24", version=4)
|
|
110
|
+
assert helpers.is_ip("1.2.3.4/24", include_network=True, version=4)
|
|
111
|
+
assert not helpers.is_ip("1.2.3.4/24", include_network=True, version=6)
|
|
112
|
+
|
|
113
|
+
assert not helpers.is_ip_type("127.0.0.1")
|
|
114
|
+
assert helpers.is_ip_type(ipaddress.ip_address("127.0.0.1"))
|
|
115
|
+
assert not helpers.is_ip_type(ipaddress.ip_address("127.0.0.1"), network=True)
|
|
116
|
+
assert helpers.is_ip_type(ipaddress.ip_address("127.0.0.1"), network=False)
|
|
117
|
+
assert helpers.is_ip_type(ipaddress.ip_network("127.0.0.0/8"))
|
|
118
|
+
assert helpers.is_ip_type(ipaddress.ip_network("127.0.0.0/8"), network=True)
|
|
119
|
+
assert not helpers.is_ip_type(ipaddress.ip_network("127.0.0.0/8"), network=False)
|
|
120
|
+
|
|
95
121
|
assert helpers.is_dns_name("evilcorp.com")
|
|
122
|
+
assert not helpers.is_dns_name("evilcorp.com:80")
|
|
123
|
+
assert not helpers.is_dns_name("http://evilcorp.com:80")
|
|
96
124
|
assert helpers.is_dns_name("evilcorp")
|
|
97
125
|
assert not helpers.is_dns_name("evilcorp", include_local=False)
|
|
98
126
|
assert helpers.is_dns_name("ドメイン.テスト")
|
|
@@ -210,8 +238,12 @@ async def test_helpers_misc(helpers, scan, bbot_scanner, bbot_httpserver):
|
|
|
210
238
|
|
|
211
239
|
ipv4_netloc = helpers.make_netloc("192.168.1.1", 80)
|
|
212
240
|
assert ipv4_netloc == "192.168.1.1:80"
|
|
213
|
-
|
|
214
|
-
assert
|
|
241
|
+
assert helpers.make_netloc("192.168.1.1") == "192.168.1.1"
|
|
242
|
+
assert helpers.make_netloc(ipaddress.ip_address("192.168.1.1"), None) == "192.168.1.1"
|
|
243
|
+
assert helpers.make_netloc("dead::beef", "443") == "[dead::beef]:443"
|
|
244
|
+
assert helpers.make_netloc(ipaddress.ip_address("dead::beef"), 443) == "[dead::beef]:443"
|
|
245
|
+
assert helpers.make_netloc("dead::beef", None) == "[dead::beef]"
|
|
246
|
+
assert helpers.make_netloc(ipaddress.ip_address("dead::beef"), None) == "[dead::beef]"
|
|
215
247
|
|
|
216
248
|
assert helpers.get_file_extension("https://evilcorp.com/evilcorp.com/test/asdf.TXT") == "txt"
|
|
217
249
|
assert helpers.get_file_extension("/etc/conf/test.tar.gz") == "gz"
|
|
@@ -251,7 +283,7 @@ async def test_helpers_misc(helpers, scan, bbot_scanner, bbot_httpserver):
|
|
|
251
283
|
replaced = helpers.search_format_dict(
|
|
252
284
|
{"asdf": [{"wat": {"here": "#{replaceme}!"}}, {500: True}]}, replaceme="asdf"
|
|
253
285
|
)
|
|
254
|
-
assert replaced["asdf"][1][500]
|
|
286
|
+
assert replaced["asdf"][1][500] is True
|
|
255
287
|
assert replaced["asdf"][0]["wat"]["here"] == "asdf!"
|
|
256
288
|
|
|
257
289
|
filtered_dict = helpers.filter_dict(
|
|
@@ -283,7 +315,7 @@ async def test_helpers_misc(helpers, scan, bbot_scanner, bbot_httpserver):
|
|
|
283
315
|
fuzzy=True,
|
|
284
316
|
exclude_keys="modules",
|
|
285
317
|
)
|
|
286
|
-
assert
|
|
318
|
+
assert "secrets_db" not in filtered_dict4["modules"]
|
|
287
319
|
assert "ipneighbor" in filtered_dict4["modules"]
|
|
288
320
|
assert "secret" in filtered_dict4["modules"]["ipneighbor"]
|
|
289
321
|
assert "asdf" not in filtered_dict4["modules"]["ipneighbor"]
|
|
@@ -376,15 +408,15 @@ async def test_helpers_misc(helpers, scan, bbot_scanner, bbot_httpserver):
|
|
|
376
408
|
assert helpers.validators.validate_host("LOCALHOST ") == "localhost"
|
|
377
409
|
assert helpers.validators.validate_host(" 192.168.1.1") == "192.168.1.1"
|
|
378
410
|
assert helpers.validators.validate_host(" Dead::c0dE ") == "dead::c0de"
|
|
379
|
-
assert helpers.validators.soft_validate(" evilCorp.COM", "host")
|
|
380
|
-
assert helpers.validators.soft_validate("!@#$", "host")
|
|
411
|
+
assert helpers.validators.soft_validate(" evilCorp.COM", "host") is True
|
|
412
|
+
assert helpers.validators.soft_validate("!@#$", "host") is False
|
|
381
413
|
with pytest.raises(ValueError):
|
|
382
414
|
assert helpers.validators.validate_host("!@#$")
|
|
383
415
|
# ports
|
|
384
416
|
assert helpers.validators.validate_port(666) == 666
|
|
385
417
|
assert helpers.validators.validate_port(666666) == 65535
|
|
386
|
-
assert helpers.validators.soft_validate(666, "port")
|
|
387
|
-
assert helpers.validators.soft_validate("!@#$", "port")
|
|
418
|
+
assert helpers.validators.soft_validate(666, "port") is True
|
|
419
|
+
assert helpers.validators.soft_validate("!@#$", "port") is False
|
|
388
420
|
with pytest.raises(ValueError):
|
|
389
421
|
helpers.validators.validate_port("asdf")
|
|
390
422
|
# top tcp ports
|
|
@@ -396,7 +428,7 @@ async def test_helpers_misc(helpers, scan, bbot_scanner, bbot_httpserver):
|
|
|
396
428
|
assert top_tcp_ports[-10:] == [65526, 65527, 65528, 65529, 65530, 65531, 65532, 65533, 65534, 65535]
|
|
397
429
|
assert len(top_tcp_ports) == 65535
|
|
398
430
|
assert len(set(top_tcp_ports)) == 65535
|
|
399
|
-
assert all(
|
|
431
|
+
assert all(isinstance(i, int) for i in top_tcp_ports)
|
|
400
432
|
top_tcp_ports = helpers.top_tcp_ports(10, as_string=True)
|
|
401
433
|
assert top_tcp_ports == "80,23,443,21,22,25,3389,110,445,139"
|
|
402
434
|
# urls
|
|
@@ -405,25 +437,29 @@ async def test_helpers_misc(helpers, scan, bbot_scanner, bbot_httpserver):
|
|
|
405
437
|
helpers.validators.validate_url_parsed(" httP://evilcorP.com/asdf?a=b&c=d#e").geturl()
|
|
406
438
|
== "http://evilcorp.com/asdf"
|
|
407
439
|
)
|
|
408
|
-
assert helpers.validators.soft_validate(" httP://evilcorP.com/asdf?a=b&c=d#e", "url")
|
|
409
|
-
assert helpers.validators.soft_validate("!@#$", "url")
|
|
440
|
+
assert helpers.validators.soft_validate(" httP://evilcorP.com/asdf?a=b&c=d#e", "url") is True
|
|
441
|
+
assert helpers.validators.soft_validate("!@#$", "url") is False
|
|
410
442
|
with pytest.raises(ValueError):
|
|
411
443
|
helpers.validators.validate_url("!@#$")
|
|
412
444
|
# severities
|
|
413
445
|
assert helpers.validators.validate_severity(" iNfo") == "INFO"
|
|
414
|
-
assert helpers.validators.soft_validate(" iNfo", "severity")
|
|
415
|
-
assert helpers.validators.soft_validate("NOPE", "severity")
|
|
446
|
+
assert helpers.validators.soft_validate(" iNfo", "severity") is True
|
|
447
|
+
assert helpers.validators.soft_validate("NOPE", "severity") is False
|
|
416
448
|
with pytest.raises(ValueError):
|
|
417
449
|
helpers.validators.validate_severity("NOPE")
|
|
418
450
|
# emails
|
|
419
451
|
assert helpers.validators.validate_email(" bOb@eViLcorp.COM") == "bob@evilcorp.com"
|
|
420
|
-
assert helpers.validators.soft_validate(" bOb@eViLcorp.COM", "email")
|
|
421
|
-
assert helpers.validators.soft_validate("!@#$", "email")
|
|
452
|
+
assert helpers.validators.soft_validate(" bOb@eViLcorp.COM", "email") is True
|
|
453
|
+
assert helpers.validators.soft_validate("!@#$", "email") is False
|
|
422
454
|
with pytest.raises(ValueError):
|
|
423
455
|
helpers.validators.validate_email("!@#$")
|
|
424
456
|
|
|
425
457
|
assert type(helpers.make_date()) == str
|
|
426
458
|
|
|
459
|
+
# string formatter
|
|
460
|
+
s = "asdf {unused} {used}"
|
|
461
|
+
assert helpers.safe_format(s, used="fdsa") == "asdf {unused} fdsa"
|
|
462
|
+
|
|
427
463
|
# punycode
|
|
428
464
|
assert helpers.smart_encode_punycode("ドメイン.テスト") == "xn--eckwd4c7c.xn--zckzah"
|
|
429
465
|
assert helpers.smart_decode_punycode("xn--eckwd4c7c.xn--zckzah") == "ドメイン.テスト"
|
|
@@ -497,9 +533,9 @@ async def test_helpers_misc(helpers, scan, bbot_scanner, bbot_httpserver):
|
|
|
497
533
|
truncated_filename.unlink()
|
|
498
534
|
|
|
499
535
|
# misc DNS helpers
|
|
500
|
-
assert helpers.is_ptr("wsc-11-22-33-44-wat.evilcorp.com")
|
|
501
|
-
assert helpers.is_ptr("wsc-11-22-33-wat.evilcorp.com")
|
|
502
|
-
assert helpers.is_ptr("11wat.evilcorp.com")
|
|
536
|
+
assert helpers.is_ptr("wsc-11-22-33-44-wat.evilcorp.com") is True
|
|
537
|
+
assert helpers.is_ptr("wsc-11-22-33-wat.evilcorp.com") is False
|
|
538
|
+
assert helpers.is_ptr("11wat.evilcorp.com") is False
|
|
503
539
|
|
|
504
540
|
## NTLM
|
|
505
541
|
testheader = "TlRMTVNTUAACAAAAHgAeADgAAAAVgorilwL+bvnVipUAAAAAAAAAAJgAmABWAAAACgBjRQAAAA9XAEkATgAtAFMANAAyAE4ATwBCAEQAVgBUAEsAOAACAB4AVwBJAE4ALQBTADQAMgBOAE8AQgBEAFYAVABLADgAAQAeAFcASQBOAC0AUwA0ADIATgBPAEIARABWAFQASwA4AAQAHgBXAEkATgAtAFMANAAyAE4ATwBCAEQAVgBUAEsAOAADAB4AVwBJAE4ALQBTADQAMgBOAE8AQgBEAFYAVABLADgABwAIAHUwOZlfoNgBAAAAAA=="
|
|
@@ -577,8 +613,8 @@ async def test_helpers_misc(helpers, scan, bbot_scanner, bbot_httpserver):
|
|
|
577
613
|
assert len(helpers.get_exception_chain(e)) == 2
|
|
578
614
|
assert len([_ for _ in helpers.get_exception_chain(e) if isinstance(_, KeyboardInterrupt)]) == 1
|
|
579
615
|
assert len([_ for _ in helpers.get_exception_chain(e) if isinstance(_, ValueError)]) == 1
|
|
580
|
-
assert helpers.in_exception_chain(e, (KeyboardInterrupt, asyncio.CancelledError))
|
|
581
|
-
assert helpers.in_exception_chain(e, (TypeError, OSError))
|
|
616
|
+
assert helpers.in_exception_chain(e, (KeyboardInterrupt, asyncio.CancelledError)) is True
|
|
617
|
+
assert helpers.in_exception_chain(e, (TypeError, OSError)) is False
|
|
582
618
|
test_ran = True
|
|
583
619
|
assert test_ran
|
|
584
620
|
test_ran = False
|
|
@@ -591,9 +627,9 @@ async def test_helpers_misc(helpers, scan, bbot_scanner, bbot_httpserver):
|
|
|
591
627
|
assert len(helpers.get_exception_chain(e)) == 2
|
|
592
628
|
assert len([_ for _ in helpers.get_exception_chain(e) if isinstance(_, AttributeError)]) == 1
|
|
593
629
|
assert len([_ for _ in helpers.get_exception_chain(e) if isinstance(_, ValueError)]) == 1
|
|
594
|
-
assert helpers.in_exception_chain(e, (KeyboardInterrupt, asyncio.CancelledError))
|
|
595
|
-
assert helpers.in_exception_chain(e, (KeyboardInterrupt, AttributeError))
|
|
596
|
-
assert helpers.in_exception_chain(e, (AttributeError,))
|
|
630
|
+
assert helpers.in_exception_chain(e, (KeyboardInterrupt, asyncio.CancelledError)) is False
|
|
631
|
+
assert helpers.in_exception_chain(e, (KeyboardInterrupt, AttributeError)) is True
|
|
632
|
+
assert helpers.in_exception_chain(e, (AttributeError,)) is True
|
|
597
633
|
test_ran = True
|
|
598
634
|
assert test_ran
|
|
599
635
|
|
|
@@ -821,7 +857,6 @@ def test_liststring_invalidfnchars(helpers):
|
|
|
821
857
|
# test parameter validation
|
|
822
858
|
@pytest.mark.asyncio
|
|
823
859
|
async def test_parameter_validation(helpers):
|
|
824
|
-
|
|
825
860
|
getparam_valid_params = {
|
|
826
861
|
"name",
|
|
827
862
|
"age",
|
|
@@ -850,7 +885,7 @@ async def test_parameter_validation(helpers):
|
|
|
850
885
|
if helpers.validate_parameter(p, "getparam"):
|
|
851
886
|
assert p in getparam_valid_params and p not in getparam_invalid_params
|
|
852
887
|
else:
|
|
853
|
-
assert p in getparam_invalid_params and not
|
|
888
|
+
assert p in getparam_invalid_params and p not in getparam_valid_params
|
|
854
889
|
|
|
855
890
|
header_valid_params = {
|
|
856
891
|
"name",
|
|
@@ -881,7 +916,7 @@ async def test_parameter_validation(helpers):
|
|
|
881
916
|
if helpers.validate_parameter(p, "header"):
|
|
882
917
|
assert p in header_valid_params and p not in header_invalid_params
|
|
883
918
|
else:
|
|
884
|
-
assert p in header_invalid_params and not
|
|
919
|
+
assert p in header_invalid_params and p not in header_valid_params
|
|
885
920
|
|
|
886
921
|
cookie_valid_params = {
|
|
887
922
|
"name",
|
|
@@ -911,4 +946,4 @@ async def test_parameter_validation(helpers):
|
|
|
911
946
|
if helpers.validate_parameter(p, "cookie"):
|
|
912
947
|
assert p in cookie_valid_params and p not in cookie_invalid_params
|
|
913
948
|
else:
|
|
914
|
-
assert p in cookie_invalid_params and not
|
|
949
|
+
assert p in cookie_invalid_params and p not in cookie_valid_params
|
|
@@ -91,7 +91,7 @@ async def test_manager_deduplication(bbot_scanner):
|
|
|
91
91
|
_dns_mock=dns_mock_chain,
|
|
92
92
|
)
|
|
93
93
|
|
|
94
|
-
assert len(events) ==
|
|
94
|
+
assert len(events) == 22
|
|
95
95
|
assert 1 == len([e for e in events if e.type == "DNS_NAME" and e.data == "accept_dupes.test.notreal" and str(e.module) == "accept_dupes"])
|
|
96
96
|
assert 1 == len([e for e in events if e.type == "DNS_NAME" and e.data == "default_module.test.notreal" and str(e.module) == "default_module"])
|
|
97
97
|
assert 1 == len([e for e in events if e.type == "DNS_NAME" and e.data == "no_suppress_dupes.test.notreal" and str(e.module) == "no_suppress_dupes" and e.parent.data == "accept_dupes.test.notreal"])
|