bbot 2.0.1.4654rc0__py3-none-any.whl → 2.3.0.5397rc0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of bbot might be problematic. Click here for more details.
- 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 -6
- bbot/core/engine.py +9 -8
- bbot/core/event/base.py +162 -63
- bbot/core/helpers/bloom.py +10 -3
- bbot/core/helpers/command.py +9 -8
- bbot/core/helpers/depsinstaller/installer.py +89 -32
- bbot/core/helpers/depsinstaller/sudo_askpass.py +38 -2
- bbot/core/helpers/diff.py +10 -10
- bbot/core/helpers/dns/brute.py +18 -14
- bbot/core/helpers/dns/dns.py +16 -15
- bbot/core/helpers/dns/engine.py +159 -132
- bbot/core/helpers/dns/helpers.py +2 -2
- bbot/core/helpers/dns/mock.py +26 -8
- 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 +18 -13
- bbot/core/helpers/web/web.py +25 -116
- 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 +15 -10
- bbot/errors.py +0 -8
- 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 +18 -19
- 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 +27 -12
- bbot/modules/internal/dnsresolve.py +250 -276
- bbot/modules/internal/excavate.py +100 -64
- bbot/modules/internal/speculate.py +42 -33
- 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 -2
- 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 +5 -8
- 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 +11 -11
- bbot/modules/robots.py +3 -3
- bbot/modules/securitytrails.py +7 -10
- bbot/modules/securitytxt.py +128 -0
- 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 +53 -17
- bbot/modules/templates/webhook.py +2 -4
- bbot/modules/trickest.py +8 -37
- bbot/modules/trufflehog.py +18 -3
- 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 -0
- bbot/presets/spider.yml +4 -0
- bbot/presets/subdomain-enum.yml +7 -7
- bbot/scanner/manager.py +5 -16
- bbot/scanner/preset/args.py +44 -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 +176 -63
- bbot/scanner/target.py +236 -434
- bbot/scripts/docs.py +1 -1
- bbot/test/bbot_fixtures.py +22 -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_bbot_fastapi.py +82 -0
- bbot/test/test_step_1/test_bloom_filter.py +2 -0
- bbot/test/test_step_1/test_cli.py +138 -64
- bbot/test/test_step_1/test_dns.py +392 -70
- bbot/test/test_step_1/test_engine.py +17 -17
- bbot/test/test_step_1/test_events.py +203 -37
- bbot/test/test_step_1/test_helpers.py +64 -28
- bbot/test/test_step_1/test_manager_deduplication.py +1 -1
- bbot/test/test_step_1/test_manager_scope_accuracy.py +336 -338
- bbot/test/test_step_1/test_modules_basic.py +69 -71
- bbot/test/test_step_1/test_presets.py +184 -96
- 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 +5 -4
- bbot/test/test_step_1/test_target.py +243 -145
- bbot/test/test_step_1/test_web.py +48 -10
- bbot/test/test_step_2/module_tests/base.py +17 -20
- 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 +17 -37
- 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 -4
- 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 +24 -11
- 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 +6 -6
- bbot/test/test_step_2/module_tests/test_module_ntlm.py +7 -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_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_securitytxt.py +50 -0
- 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 +1 -1
- bbot/test/test_step_2/module_tests/test_module_social.py +11 -1
- bbot/test/test_step_2/module_tests/test_module_speculate.py +2 -6
- 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 -11
- 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 +135 -0
- {bbot-2.0.1.4654rc0.dist-info → bbot-2.3.0.5397rc0.dist-info}/METADATA +48 -18
- bbot-2.3.0.5397rc0.dist-info/RECORD +421 -0
- {bbot-2.0.1.4654rc0.dist-info → bbot-2.3.0.5397rc0.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.4654rc0.dist-info/RECORD +0 -385
- {bbot-2.0.1.4654rc0.dist-info → bbot-2.3.0.5397rc0.dist-info}/LICENSE +0 -0
- {bbot-2.0.1.4654rc0.dist-info → bbot-2.3.0.5397rc0.dist-info}/entry_points.txt +0 -0
|
@@ -9,6 +9,7 @@ from .base import ModuleTestBase
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class TestTrufflehog(ModuleTestBase):
|
|
12
|
+
config_overrides = {"modules": {"postman_download": {"api_key": "asdf"}}}
|
|
12
13
|
modules_overrides = [
|
|
13
14
|
"github_org",
|
|
14
15
|
"speculate",
|
|
@@ -16,6 +17,8 @@ class TestTrufflehog(ModuleTestBase):
|
|
|
16
17
|
"github_workflows",
|
|
17
18
|
"dockerhub",
|
|
18
19
|
"docker_pull",
|
|
20
|
+
"postman",
|
|
21
|
+
"postman_download",
|
|
19
22
|
"trufflehog",
|
|
20
23
|
]
|
|
21
24
|
|
|
@@ -23,6 +26,37 @@ class TestTrufflehog(ModuleTestBase):
|
|
|
23
26
|
|
|
24
27
|
async def setup_before_prep(self, module_test):
|
|
25
28
|
module_test.httpx_mock.add_response(url="https://api.github.com/zen")
|
|
29
|
+
module_test.httpx_mock.add_response(
|
|
30
|
+
url="https://api.getpostman.com/me",
|
|
31
|
+
json={
|
|
32
|
+
"user": {
|
|
33
|
+
"id": 000000,
|
|
34
|
+
"username": "test_key",
|
|
35
|
+
"email": "blacklanternsecurity@test.com",
|
|
36
|
+
"fullName": "Test Key",
|
|
37
|
+
"avatar": "",
|
|
38
|
+
"isPublic": True,
|
|
39
|
+
"teamId": 0,
|
|
40
|
+
"teamDomain": "",
|
|
41
|
+
"roles": ["user"],
|
|
42
|
+
},
|
|
43
|
+
"operations": [
|
|
44
|
+
{"name": "api_object_usage", "limit": 3, "usage": 0, "overage": 0},
|
|
45
|
+
{"name": "collection_run_limit", "limit": 25, "usage": 0, "overage": 0},
|
|
46
|
+
{"name": "file_storage_limit", "limit": 20, "usage": 0, "overage": 0},
|
|
47
|
+
{"name": "flow_count", "limit": 5, "usage": 0, "overage": 0},
|
|
48
|
+
{"name": "flow_requests", "limit": 5000, "usage": 0, "overage": 0},
|
|
49
|
+
{"name": "performance_test_limit", "limit": 25, "usage": 0, "overage": 0},
|
|
50
|
+
{"name": "postbot_calls", "limit": 50, "usage": 0, "overage": 0},
|
|
51
|
+
{"name": "reusable_packages", "limit": 3, "usage": 0, "overage": 0},
|
|
52
|
+
{"name": "test_data_retrieval", "limit": 1000, "usage": 0, "overage": 0},
|
|
53
|
+
{"name": "test_data_storage", "limit": 10, "usage": 0, "overage": 0},
|
|
54
|
+
{"name": "mock_usage", "limit": 1000, "usage": 0, "overage": 0},
|
|
55
|
+
{"name": "monitor_request_runs", "limit": 1000, "usage": 0, "overage": 0},
|
|
56
|
+
{"name": "api_usage", "limit": 1000, "usage": 0, "overage": 0},
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
)
|
|
26
60
|
module_test.httpx_mock.add_response(
|
|
27
61
|
url="https://api.github.com/orgs/blacklanternsecurity",
|
|
28
62
|
json={
|
|
@@ -812,6 +846,248 @@ class TestTrufflehog(ModuleTestBase):
|
|
|
812
846
|
)
|
|
813
847
|
|
|
814
848
|
async def setup_after_prep(self, module_test):
|
|
849
|
+
module_test.httpx_mock.add_response(
|
|
850
|
+
url="https://www.postman.com/_api/ws/proxy",
|
|
851
|
+
match_content=b'{"service": "search", "method": "POST", "path": "/search-all", "body": {"queryIndices": ["collaboration.workspace"], "queryText": "blacklanternsecurity", "size": 100, "from": 0, "clientTraceId": "", "requestOrigin": "srp", "mergeEntities": "true", "nonNestedRequests": "true", "domain": "public"}}',
|
|
852
|
+
json={
|
|
853
|
+
"data": [
|
|
854
|
+
{
|
|
855
|
+
"score": 611.41156,
|
|
856
|
+
"normalizedScore": 23,
|
|
857
|
+
"document": {
|
|
858
|
+
"watcherCount": 6,
|
|
859
|
+
"apiCount": 0,
|
|
860
|
+
"forkCount": 0,
|
|
861
|
+
"isblacklisted": "false",
|
|
862
|
+
"createdAt": "2021-06-15T14:03:51",
|
|
863
|
+
"publishertype": "team",
|
|
864
|
+
"publisherHandle": "blacklanternsecurity",
|
|
865
|
+
"id": "11498add-357d-4bc5-a008-0a2d44fb8829",
|
|
866
|
+
"slug": "bbot-public",
|
|
867
|
+
"updatedAt": "2024-07-30T11:00:35",
|
|
868
|
+
"entityType": "workspace",
|
|
869
|
+
"visibilityStatus": "public",
|
|
870
|
+
"forkcount": "0",
|
|
871
|
+
"tags": [],
|
|
872
|
+
"createdat": "2021-06-15T14:03:51",
|
|
873
|
+
"forkLabel": "",
|
|
874
|
+
"publisherName": "blacklanternsecurity",
|
|
875
|
+
"name": "BlackLanternSecurity BBOT [Public]",
|
|
876
|
+
"dependencyCount": 7,
|
|
877
|
+
"collectionCount": 6,
|
|
878
|
+
"warehouse__updated_at": "2024-07-30 11:00:00",
|
|
879
|
+
"privateNetworkFolders": [],
|
|
880
|
+
"isPublisherVerified": False,
|
|
881
|
+
"publisherType": "team",
|
|
882
|
+
"curatedInList": [],
|
|
883
|
+
"creatorId": "6900157",
|
|
884
|
+
"description": "",
|
|
885
|
+
"forklabel": "",
|
|
886
|
+
"publisherId": "299401",
|
|
887
|
+
"publisherLogo": "",
|
|
888
|
+
"popularity": 5,
|
|
889
|
+
"isPublic": True,
|
|
890
|
+
"categories": [],
|
|
891
|
+
"universaltags": "",
|
|
892
|
+
"views": 5788,
|
|
893
|
+
"summary": "BLS public workspaces.",
|
|
894
|
+
"memberCount": 2,
|
|
895
|
+
"isBlacklisted": False,
|
|
896
|
+
"publisherid": "299401",
|
|
897
|
+
"isPrivateNetworkEntity": False,
|
|
898
|
+
"isDomainNonTrivial": True,
|
|
899
|
+
"privateNetworkMeta": "",
|
|
900
|
+
"updatedat": "2021-10-20T16:19:29",
|
|
901
|
+
"documentType": "workspace",
|
|
902
|
+
},
|
|
903
|
+
"highlight": {"summary": "<b>BLS</b> BBOT api test."},
|
|
904
|
+
},
|
|
905
|
+
],
|
|
906
|
+
"meta": {
|
|
907
|
+
"queryText": "blacklanternsecurity",
|
|
908
|
+
"total": {
|
|
909
|
+
"collection": 0,
|
|
910
|
+
"request": 0,
|
|
911
|
+
"workspace": 1,
|
|
912
|
+
"api": 0,
|
|
913
|
+
"team": 0,
|
|
914
|
+
"user": 0,
|
|
915
|
+
"flow": 0,
|
|
916
|
+
"apiDefinition": 0,
|
|
917
|
+
"privateNetworkFolder": 0,
|
|
918
|
+
},
|
|
919
|
+
"state": "AQ4",
|
|
920
|
+
"spellCorrection": {"count": {"all": 1, "workspace": 1}, "correctedQueryText": None},
|
|
921
|
+
"featureFlags": {
|
|
922
|
+
"enabledPublicResultCuration": True,
|
|
923
|
+
"boostByPopularity": True,
|
|
924
|
+
"reRankPostNormalization": True,
|
|
925
|
+
"enableUrlBarHostNameSearch": True,
|
|
926
|
+
},
|
|
927
|
+
},
|
|
928
|
+
},
|
|
929
|
+
)
|
|
930
|
+
module_test.httpx_mock.add_response(
|
|
931
|
+
url="https://www.postman.com/_api/ws/proxy",
|
|
932
|
+
match_content=b'{"service": "workspaces", "method": "GET", "path": "/workspaces?handle=blacklanternsecurity&slug=bbot-public"}',
|
|
933
|
+
json={
|
|
934
|
+
"meta": {"model": "workspace", "action": "find", "nextCursor": ""},
|
|
935
|
+
"data": [
|
|
936
|
+
{
|
|
937
|
+
"id": "3a7e4bdc-7ff7-4dd4-8eaa-61ddce1c3d1b",
|
|
938
|
+
"name": "BlackLanternSecurity BBOT [Public]",
|
|
939
|
+
"description": None,
|
|
940
|
+
"summary": "BLS public workspaces.",
|
|
941
|
+
"createdBy": "299401",
|
|
942
|
+
"updatedBy": "299401",
|
|
943
|
+
"team": None,
|
|
944
|
+
"createdAt": "2021-10-20T16:19:29",
|
|
945
|
+
"updatedAt": "2021-10-20T16:19:29",
|
|
946
|
+
"visibilityStatus": "public",
|
|
947
|
+
"profileInfo": {
|
|
948
|
+
"slug": "bbot-public",
|
|
949
|
+
"profileType": "team",
|
|
950
|
+
"profileId": "000000",
|
|
951
|
+
"publicHandle": "https://www.postman.com/blacklanternsecurity",
|
|
952
|
+
"publicImageURL": "",
|
|
953
|
+
"publicName": "BlackLanternSecurity",
|
|
954
|
+
"isVerified": False,
|
|
955
|
+
},
|
|
956
|
+
}
|
|
957
|
+
],
|
|
958
|
+
},
|
|
959
|
+
)
|
|
960
|
+
module_test.httpx_mock.add_response(
|
|
961
|
+
url="https://api.getpostman.com/workspaces/3a7e4bdc-7ff7-4dd4-8eaa-61ddce1c3d1b",
|
|
962
|
+
json={
|
|
963
|
+
"workspace": {
|
|
964
|
+
"id": "3a7e4bdc-7ff7-4dd4-8eaa-61ddce1c3d1b",
|
|
965
|
+
"name": "BlackLanternSecurity BBOT [Public]",
|
|
966
|
+
"type": "personal",
|
|
967
|
+
"description": None,
|
|
968
|
+
"visibility": "public",
|
|
969
|
+
"createdBy": "00000000",
|
|
970
|
+
"updatedBy": "00000000",
|
|
971
|
+
"createdAt": "2021-11-17T06:09:01.000Z",
|
|
972
|
+
"updatedAt": "2021-11-17T08:57:16.000Z",
|
|
973
|
+
"collections": [
|
|
974
|
+
{
|
|
975
|
+
"id": "2aab9fd0-3715-4abe-8bb0-8cb0264d023f",
|
|
976
|
+
"name": "BBOT Public",
|
|
977
|
+
"uid": "10197090-2aab9fd0-3715-4abe-8bb0-8cb0264d023f",
|
|
978
|
+
},
|
|
979
|
+
],
|
|
980
|
+
"environments": [
|
|
981
|
+
{
|
|
982
|
+
"id": "f770f816-9c6a-40f7-bde3-c0855d2a1089",
|
|
983
|
+
"name": "BBOT Test",
|
|
984
|
+
"uid": "10197090-f770f816-9c6a-40f7-bde3-c0855d2a1089",
|
|
985
|
+
}
|
|
986
|
+
],
|
|
987
|
+
"apis": [],
|
|
988
|
+
}
|
|
989
|
+
},
|
|
990
|
+
)
|
|
991
|
+
module_test.httpx_mock.add_response(
|
|
992
|
+
url="https://www.postman.com/_api/workspace/3a7e4bdc-7ff7-4dd4-8eaa-61ddce1c3d1b/globals",
|
|
993
|
+
json={
|
|
994
|
+
"model_id": "8be7574b-219f-49e0-8d25-da447a882e4e",
|
|
995
|
+
"meta": {"model": "globals", "action": "find"},
|
|
996
|
+
"data": {
|
|
997
|
+
"workspace": "3a7e4bdc-7ff7-4dd4-8eaa-61ddce1c3d1b",
|
|
998
|
+
"lastUpdatedBy": "00000000",
|
|
999
|
+
"lastRevision": 1637239113000,
|
|
1000
|
+
"id": "8be7574b-219f-49e0-8d25-da447a882e4e",
|
|
1001
|
+
"values": [
|
|
1002
|
+
{
|
|
1003
|
+
"key": "endpoint_url",
|
|
1004
|
+
"value": "https://api.blacklanternsecurity.com/",
|
|
1005
|
+
"enabled": True,
|
|
1006
|
+
},
|
|
1007
|
+
],
|
|
1008
|
+
"createdAt": "2021-11-17T06:09:01.000Z",
|
|
1009
|
+
"updatedAt": "2021-11-18T12:38:33.000Z",
|
|
1010
|
+
},
|
|
1011
|
+
},
|
|
1012
|
+
)
|
|
1013
|
+
module_test.httpx_mock.add_response(
|
|
1014
|
+
url="https://api.getpostman.com/environments/10197090-f770f816-9c6a-40f7-bde3-c0855d2a1089",
|
|
1015
|
+
json={
|
|
1016
|
+
"environment": {
|
|
1017
|
+
"id": "f770f816-9c6a-40f7-bde3-c0855d2a1089",
|
|
1018
|
+
"name": "BBOT Test",
|
|
1019
|
+
"owner": "00000000",
|
|
1020
|
+
"createdAt": "2021-11-17T06:29:54.000Z",
|
|
1021
|
+
"updatedAt": "2021-11-23T07:06:53.000Z",
|
|
1022
|
+
"values": [
|
|
1023
|
+
{
|
|
1024
|
+
"key": "temp_session_endpoint",
|
|
1025
|
+
"value": "https://api.blacklanternsecurity.com/",
|
|
1026
|
+
"enabled": True,
|
|
1027
|
+
},
|
|
1028
|
+
],
|
|
1029
|
+
"isPublic": True,
|
|
1030
|
+
}
|
|
1031
|
+
},
|
|
1032
|
+
)
|
|
1033
|
+
module_test.httpx_mock.add_response(
|
|
1034
|
+
url="https://api.getpostman.com/collections/10197090-2aab9fd0-3715-4abe-8bb0-8cb0264d023f",
|
|
1035
|
+
json={
|
|
1036
|
+
"collection": {
|
|
1037
|
+
"info": {
|
|
1038
|
+
"_postman_id": "62b91565-d2e2-4bcd-8248-4dba2e3452f0",
|
|
1039
|
+
"name": "BBOT Public",
|
|
1040
|
+
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
|
|
1041
|
+
"updatedAt": "2021-11-17T07:13:16.000Z",
|
|
1042
|
+
"createdAt": "2021-11-17T07:13:15.000Z",
|
|
1043
|
+
"lastUpdatedBy": "00000000",
|
|
1044
|
+
"uid": "172983-62b91565-d2e2-4bcd-8248-4dba2e3452f0",
|
|
1045
|
+
},
|
|
1046
|
+
"item": [
|
|
1047
|
+
{
|
|
1048
|
+
"name": "Generate API Session",
|
|
1049
|
+
"id": "c1bac38c-dfc9-4cc0-9c19-828cbc8543b1",
|
|
1050
|
+
"protocolProfileBehavior": {"disableBodyPruning": True},
|
|
1051
|
+
"request": {
|
|
1052
|
+
"method": "POST",
|
|
1053
|
+
"header": [{"key": "Content-Type", "value": "application/json"}],
|
|
1054
|
+
"body": {
|
|
1055
|
+
"mode": "raw",
|
|
1056
|
+
"raw": '{"username": "test", "password": "Test"}',
|
|
1057
|
+
},
|
|
1058
|
+
"url": {
|
|
1059
|
+
"raw": "https://admin:admin@the-internet.herokuapp.com/basic_auth",
|
|
1060
|
+
"host": ["https://admin:admin@the-internet.herokuapp.com/basic_auth"],
|
|
1061
|
+
},
|
|
1062
|
+
"description": "",
|
|
1063
|
+
},
|
|
1064
|
+
"response": [],
|
|
1065
|
+
"uid": "10197090-c1bac38c-dfc9-4cc0-9c19-828cbc8543b1",
|
|
1066
|
+
},
|
|
1067
|
+
{
|
|
1068
|
+
"name": "Generate API Session",
|
|
1069
|
+
"id": "c1bac38c-dfc9-4cc0-9c19-828cbc8543b1",
|
|
1070
|
+
"protocolProfileBehavior": {"disableBodyPruning": True},
|
|
1071
|
+
"request": {
|
|
1072
|
+
"method": "POST",
|
|
1073
|
+
"header": [{"key": "Content-Type", "value": "application/json"}],
|
|
1074
|
+
"body": {
|
|
1075
|
+
"mode": "raw",
|
|
1076
|
+
"raw": '{"username": "test", "password": "Test"}',
|
|
1077
|
+
},
|
|
1078
|
+
"url": {
|
|
1079
|
+
"raw": "https://admin:admin@internal.host.com",
|
|
1080
|
+
"host": ["https://admin:admin@internal.host.com"],
|
|
1081
|
+
},
|
|
1082
|
+
"description": "",
|
|
1083
|
+
},
|
|
1084
|
+
"response": [],
|
|
1085
|
+
"uid": "10197090-c1bac38c-dfc9-4cc0-9c19-828cbc8543b1",
|
|
1086
|
+
},
|
|
1087
|
+
],
|
|
1088
|
+
}
|
|
1089
|
+
},
|
|
1090
|
+
)
|
|
815
1091
|
temp_path = Path("/tmp/.bbot_test")
|
|
816
1092
|
temp_repo_path = temp_path / "test_keys"
|
|
817
1093
|
shutil.rmtree(temp_repo_path, ignore_errors=True)
|
|
@@ -849,21 +1125,26 @@ class TestTrufflehog(ModuleTestBase):
|
|
|
849
1125
|
e
|
|
850
1126
|
for e in events
|
|
851
1127
|
if e.type == "VULNERABILITY"
|
|
852
|
-
and (
|
|
1128
|
+
and (
|
|
1129
|
+
e.data["host"] == "hub.docker.com"
|
|
1130
|
+
or e.data["host"] == "github.com"
|
|
1131
|
+
or e.data["host"] == "www.postman.com"
|
|
1132
|
+
)
|
|
853
1133
|
and "Verified Secret Found." in e.data["description"]
|
|
854
1134
|
and "Raw result: [https://admin:admin@the-internet.herokuapp.com]" in e.data["description"]
|
|
855
1135
|
and "RawV2 result: [https://admin:admin@the-internet.herokuapp.com/basic_auth]" in e.data["description"]
|
|
856
1136
|
]
|
|
857
|
-
|
|
1137
|
+
# Trufflehog should find 4 verifiable secrets, 1 from the github, 1 from the workflow log, 1 from the docker image and 1 from the postman.
|
|
1138
|
+
assert 4 == len(vuln_events), "Failed to find secret in events"
|
|
858
1139
|
github_repo_event = [e for e in vuln_events if "test_keys" in e.data["description"]][0].parent
|
|
859
1140
|
folder = Path(github_repo_event.data["path"])
|
|
860
1141
|
assert folder.is_dir(), "Destination folder doesn't exist"
|
|
861
1142
|
with open(folder / "keys.txt") as f:
|
|
862
1143
|
content = f.read()
|
|
863
1144
|
assert content == self.file_content, "File content doesn't match"
|
|
864
|
-
filesystem_events = [e.parent for e in vuln_events
|
|
865
|
-
assert len(filesystem_events) ==
|
|
866
|
-
assert all(
|
|
1145
|
+
filesystem_events = [e.parent for e in vuln_events]
|
|
1146
|
+
assert len(filesystem_events) == 4
|
|
1147
|
+
assert all(e.type == "FILESYSTEM" for e in filesystem_events)
|
|
867
1148
|
assert 1 == len(
|
|
868
1149
|
[
|
|
869
1150
|
e
|
|
@@ -887,30 +1168,45 @@ class TestTrufflehog(ModuleTestBase):
|
|
|
887
1168
|
and Path(e.data["path"]).is_file()
|
|
888
1169
|
]
|
|
889
1170
|
), "Docker image file does not exist"
|
|
1171
|
+
assert 1 == len(
|
|
1172
|
+
[
|
|
1173
|
+
e
|
|
1174
|
+
for e in filesystem_events
|
|
1175
|
+
if e.data["path"].endswith(
|
|
1176
|
+
"/postman_workspaces/BlackLanternSecurity BBOT [Public]/3a7e4bdc-7ff7-4dd4-8eaa-61ddce1c3d1b.zip"
|
|
1177
|
+
)
|
|
1178
|
+
and Path(e.data["path"]).is_file()
|
|
1179
|
+
]
|
|
1180
|
+
), "Failed to find blacklanternsecurity postman workspace"
|
|
890
1181
|
|
|
891
1182
|
|
|
892
1183
|
class TestTrufflehog_NonVerified(TestTrufflehog):
|
|
893
|
-
config_overrides = {"modules": {"trufflehog": {"only_verified": False}}}
|
|
1184
|
+
config_overrides = {"modules": {"trufflehog": {"only_verified": False}, "postman_download": {"api_key": "asdf"}}}
|
|
894
1185
|
|
|
895
1186
|
def check(self, module_test, events):
|
|
896
1187
|
finding_events = [
|
|
897
1188
|
e
|
|
898
1189
|
for e in events
|
|
899
1190
|
if e.type == e.type == "FINDING"
|
|
900
|
-
and (
|
|
1191
|
+
and (
|
|
1192
|
+
e.data["host"] == "hub.docker.com"
|
|
1193
|
+
or e.data["host"] == "github.com"
|
|
1194
|
+
or e.data["host"] == "www.postman.com"
|
|
1195
|
+
)
|
|
901
1196
|
and "Potential Secret Found." in e.data["description"]
|
|
902
1197
|
and "Raw result: [https://admin:admin@internal.host.com]" in e.data["description"]
|
|
903
1198
|
]
|
|
904
|
-
|
|
1199
|
+
# Trufflehog should find 4 unverifiable secrets, 1 from the github, 1 from the workflow log, 1 from the docker image and 1 from the postman.
|
|
1200
|
+
assert 4 == len(finding_events), "Failed to find secret in events"
|
|
905
1201
|
github_repo_event = [e for e in finding_events if "test_keys" in e.data["description"]][0].parent
|
|
906
1202
|
folder = Path(github_repo_event.data["path"])
|
|
907
1203
|
assert folder.is_dir(), "Destination folder doesn't exist"
|
|
908
1204
|
with open(folder / "keys.txt") as f:
|
|
909
1205
|
content = f.read()
|
|
910
1206
|
assert content == self.file_content, "File content doesn't match"
|
|
911
|
-
filesystem_events = [e.parent for e in finding_events
|
|
912
|
-
assert len(filesystem_events) ==
|
|
913
|
-
assert all(
|
|
1207
|
+
filesystem_events = [e.parent for e in finding_events]
|
|
1208
|
+
assert len(filesystem_events) == 4
|
|
1209
|
+
assert all(e.type == "FILESYSTEM" for e in filesystem_events)
|
|
914
1210
|
assert 1 == len(
|
|
915
1211
|
[
|
|
916
1212
|
e
|
|
@@ -934,3 +1230,13 @@ class TestTrufflehog_NonVerified(TestTrufflehog):
|
|
|
934
1230
|
and Path(e.data["path"]).is_file()
|
|
935
1231
|
]
|
|
936
1232
|
), "Docker image file does not exist"
|
|
1233
|
+
assert 1 == len(
|
|
1234
|
+
[
|
|
1235
|
+
e
|
|
1236
|
+
for e in filesystem_events
|
|
1237
|
+
if e.data["path"].endswith(
|
|
1238
|
+
"/postman_workspaces/BlackLanternSecurity BBOT [Public]/3a7e4bdc-7ff7-4dd4-8eaa-61ddce1c3d1b.zip"
|
|
1239
|
+
)
|
|
1240
|
+
and Path(e.data["path"]).is_file()
|
|
1241
|
+
]
|
|
1242
|
+
), "Failed to find blacklanternsecurity postman workspace"
|
|
@@ -4,7 +4,7 @@ from .base import ModuleTestBase
|
|
|
4
4
|
class TestWayback(ModuleTestBase):
|
|
5
5
|
async def setup_after_prep(self, module_test):
|
|
6
6
|
module_test.httpx_mock.add_response(
|
|
7
|
-
url=
|
|
7
|
+
url="http://web.archive.org/cdx/search/cdx?url=blacklanternsecurity.com&matchType=domain&output=json&fl=original&collapse=original",
|
|
8
8
|
json=[["original"], ["http://asdf.blacklanternsecurity.com"]],
|
|
9
9
|
)
|
|
10
10
|
|
|
@@ -84,3 +84,138 @@ class TestSubdomainEnumLowestParent(TestSubdomainEnumHighestParent):
|
|
|
84
84
|
"asdf.www.blacklanternsecurity.com",
|
|
85
85
|
"www.blacklanternsecurity.com",
|
|
86
86
|
}
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class TestSubdomainEnumWildcardBaseline(ModuleTestBase):
|
|
90
|
+
# oh walmart.cn why are you like this
|
|
91
|
+
targets = ["www.walmart.cn"]
|
|
92
|
+
whitelist = ["walmart.cn"]
|
|
93
|
+
modules_overrides = []
|
|
94
|
+
config_overrides = {"dns": {"minimal": False}, "scope": {"report_distance": 10}, "omit_event_types": []}
|
|
95
|
+
dedup_strategy = "highest_parent"
|
|
96
|
+
|
|
97
|
+
dns_mock_data = {
|
|
98
|
+
"walmart.cn": {"A": ["127.0.0.1"]},
|
|
99
|
+
"www.walmart.cn": {"A": ["127.0.0.1"]},
|
|
100
|
+
"test.walmart.cn": {"A": ["127.0.0.1"]},
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async def setup_before_prep(self, module_test):
|
|
104
|
+
await module_test.mock_dns(self.dns_mock_data)
|
|
105
|
+
self.queries = []
|
|
106
|
+
|
|
107
|
+
async def mock_query(query):
|
|
108
|
+
self.queries.append(query)
|
|
109
|
+
return ["walmart.cn", "www.walmart.cn", "test.walmart.cn", "asdf.walmart.cn"]
|
|
110
|
+
|
|
111
|
+
# load subdomain enum template as module
|
|
112
|
+
from bbot.modules.templates.subdomain_enum import subdomain_enum
|
|
113
|
+
|
|
114
|
+
subdomain_enum_module = subdomain_enum(module_test.scan)
|
|
115
|
+
|
|
116
|
+
subdomain_enum_module.query = mock_query
|
|
117
|
+
subdomain_enum_module._name = "subdomain_enum"
|
|
118
|
+
subdomain_enum_module.dedup_strategy = self.dedup_strategy
|
|
119
|
+
module_test.scan.modules["subdomain_enum"] = subdomain_enum_module
|
|
120
|
+
|
|
121
|
+
def check(self, module_test, events):
|
|
122
|
+
assert self.queries == ["walmart.cn"]
|
|
123
|
+
assert len(events) == 7
|
|
124
|
+
assert 2 == len(
|
|
125
|
+
[
|
|
126
|
+
e
|
|
127
|
+
for e in events
|
|
128
|
+
if e.type == "IP_ADDRESS" and e.data == "127.0.0.1" and str(e.module) == "A" and e.scope_distance == 1
|
|
129
|
+
]
|
|
130
|
+
)
|
|
131
|
+
assert 1 == len(
|
|
132
|
+
[
|
|
133
|
+
e
|
|
134
|
+
for e in events
|
|
135
|
+
if e.type == "DNS_NAME"
|
|
136
|
+
and e.data == "www.walmart.cn"
|
|
137
|
+
and str(e.module) == "TARGET"
|
|
138
|
+
and e.scope_distance == 0
|
|
139
|
+
]
|
|
140
|
+
)
|
|
141
|
+
assert 1 == len(
|
|
142
|
+
[
|
|
143
|
+
e
|
|
144
|
+
for e in events
|
|
145
|
+
if e.type == "DNS_NAME"
|
|
146
|
+
and e.data == "test.walmart.cn"
|
|
147
|
+
and str(e.module) == "subdomain_enum"
|
|
148
|
+
and e.scope_distance == 0
|
|
149
|
+
]
|
|
150
|
+
)
|
|
151
|
+
assert 1 == len(
|
|
152
|
+
[
|
|
153
|
+
e
|
|
154
|
+
for e in events
|
|
155
|
+
if e.type == "DNS_NAME_UNRESOLVED"
|
|
156
|
+
and e.data == "asdf.walmart.cn"
|
|
157
|
+
and str(e.module) == "subdomain_enum"
|
|
158
|
+
and e.scope_distance == 0
|
|
159
|
+
]
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
class TestSubdomainEnumWildcardDefense(TestSubdomainEnumWildcardBaseline):
|
|
164
|
+
# oh walmart.cn why are you like this
|
|
165
|
+
targets = ["walmart.cn"]
|
|
166
|
+
modules_overrides = []
|
|
167
|
+
config_overrides = {"dns": {"minimal": False}, "scope": {"report_distance": 10}}
|
|
168
|
+
dedup_strategy = "highest_parent"
|
|
169
|
+
|
|
170
|
+
dns_mock_data = {
|
|
171
|
+
"walmart.cn": {"A": ["127.0.0.2"], "TXT": ["asdf.walmart.cn"]},
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
async def setup_after_prep(self, module_test):
|
|
175
|
+
# simulate wildcard
|
|
176
|
+
custom_lookup = """
|
|
177
|
+
def custom_lookup(query, rdtype):
|
|
178
|
+
import random
|
|
179
|
+
if rdtype == "A" and query.endswith(".walmart.cn"):
|
|
180
|
+
ip = ".".join([str(random.randint(0,256)) for _ in range(4)])
|
|
181
|
+
return {ip}
|
|
182
|
+
"""
|
|
183
|
+
await module_test.mock_dns(self.dns_mock_data, custom_lookup_fn=custom_lookup)
|
|
184
|
+
|
|
185
|
+
def check(self, module_test, events):
|
|
186
|
+
# no subdomain enum should happen on this domain!
|
|
187
|
+
assert self.queries == []
|
|
188
|
+
assert len(events) == 7
|
|
189
|
+
assert 2 == len(
|
|
190
|
+
[e for e in events if e.type == "IP_ADDRESS" and str(e.module) == "A" and e.scope_distance == 1]
|
|
191
|
+
)
|
|
192
|
+
assert 1 == len(
|
|
193
|
+
[
|
|
194
|
+
e
|
|
195
|
+
for e in events
|
|
196
|
+
if e.type == "DNS_NAME"
|
|
197
|
+
and e.data == "walmart.cn"
|
|
198
|
+
and str(e.module) == "TARGET"
|
|
199
|
+
and e.scope_distance == 0
|
|
200
|
+
]
|
|
201
|
+
)
|
|
202
|
+
assert 1 == len(
|
|
203
|
+
[
|
|
204
|
+
e
|
|
205
|
+
for e in events
|
|
206
|
+
if e.type == "DNS_NAME"
|
|
207
|
+
and e.data == "asdf.walmart.cn"
|
|
208
|
+
and str(e.module) == "TXT"
|
|
209
|
+
and e.scope_distance == 0
|
|
210
|
+
and "wildcard-possible" in e.tags
|
|
211
|
+
and "a-wildcard-possible" in e.tags
|
|
212
|
+
]
|
|
213
|
+
)
|
|
214
|
+
assert 1 == len(
|
|
215
|
+
[
|
|
216
|
+
e
|
|
217
|
+
for e in events
|
|
218
|
+
if e.type == "RAW_DNS_RECORD"
|
|
219
|
+
and e.data == {"host": "walmart.cn", "type": "TXT", "answer": '"asdf.walmart.cn"'}
|
|
220
|
+
]
|
|
221
|
+
)
|