bbot 2.1.0.4959rc0__tar.gz → 2.1.0.5028rc0__tar.gz
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.
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/PKG-INFO +2 -1
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/__init__.py +1 -1
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/event/base.py +28 -9
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/misc.py +10 -3
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/regexes.py +3 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/web/web.py +0 -48
- bbot-2.1.0.5028rc0/bbot/modules/apkpure.py +53 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/badsecrets.py +3 -2
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/base.py +5 -3
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/dotnetnuke.py +18 -17
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/generic_ssrf.py +2 -2
- bbot-2.1.0.5028rc0/bbot/modules/google_playstore.py +93 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/httpx.py +0 -3
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/internal/cloudcheck.py +2 -2
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/internal/dnsresolve.py +2 -8
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/internal/excavate.py +53 -4
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/internal/speculate.py +3 -4
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/internetdb.py +3 -1
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/shodan_dns.py +7 -9
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/templates/subdomain_enum.py +43 -4
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/trickest.py +4 -28
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/trufflehog.py +1 -1
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/virustotal.py +4 -14
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/subdomain-enum.yml +7 -7
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/manager.py +4 -14
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/preset/preset.py +0 -2
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/scanner.py +17 -13
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/bbot_fixtures.py +7 -0
- bbot-2.1.0.5028rc0/bbot/test/owasp_mastg.apk +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_cli.py +0 -8
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_events.py +36 -7
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_helpers.py +15 -2
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_manager_scope_accuracy.py +9 -7
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_modules_basic.py +15 -13
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_presets.py +21 -3
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_regexes.py +9 -2
- bbot-2.1.0.5028rc0/bbot/test/test_step_2/module_tests/test_module_apkpure.py +69 -0
- bbot-2.1.0.5028rc0/bbot/test/test_step_2/module_tests/test_module_google_playstore.py +83 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_httpx.py +3 -1
- bbot-2.1.0.5028rc0/bbot/test/test_step_2/module_tests/test_module_shodan_dns.py +40 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/pyproject.toml +2 -2
- bbot-2.1.0.4959rc0/bbot/test/test_step_2/module_tests/test_module_shodan_dns.py +0 -21
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/LICENSE +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/README.md +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/cli.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/__init__.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/config/__init__.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/config/files.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/config/logger.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/core.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/engine.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/event/__init__.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/event/helpers.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/flags.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/__init__.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/async_helpers.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/bloom.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/cache.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/command.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/depsinstaller/__init__.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/depsinstaller/installer.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/depsinstaller/sudo_askpass.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/diff.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/dns/__init__.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/dns/brute.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/dns/dns.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/dns/engine.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/dns/helpers.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/dns/mock.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/files.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/helper.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/interactsh.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/names_generator.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/ntlm.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/process.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/ratelimiter.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/regex.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/url.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/validators.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/web/__init__.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/web/client.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/web/engine.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/web/ssl_context.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/helpers/wordcloud.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/modules.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/core/shared_deps.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/defaults.yml +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/errors.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/logger.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/__init__.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/ajaxpro.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/anubisdb.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/azure_realm.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/azure_tenant.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/baddns.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/baddns_direct.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/baddns_zone.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/bevigil.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/binaryedge.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/bucket_amazon.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/bucket_azure.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/bucket_digitalocean.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/bucket_file_enum.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/bucket_firebase.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/bucket_google.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/builtwith.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/bypass403.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/c99.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/censys.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/certspotter.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/chaos.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/code_repository.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/columbus.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/credshed.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/crt.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/deadly/dastardly.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/deadly/ffuf.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/deadly/nuclei.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/deadly/vhost.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/dehashed.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/digitorus.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/dnsbrute.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/dnsbrute_mutations.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/dnscaa.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/dnscommonsrv.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/dnsdumpster.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/docker_pull.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/dockerhub.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/emailformat.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/ffuf_shortnames.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/filedownload.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/fingerprintx.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/fullhunt.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/git.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/git_clone.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/github_codesearch.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/github_org.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/github_workflows.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/gitlab.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/gowitness.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/hackertarget.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/host_header.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/hunt.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/hunterio.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/iis_shortnames.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/internal/__init__.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/internal/aggregate.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/internal/base.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/ip2location.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/ipneighbor.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/ipstack.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/leakix.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/myssl.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/newsletters.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/ntlm.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/oauth.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/otx.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/__init__.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/asset_inventory.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/base.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/csv.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/discord.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/emails.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/http.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/json.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/neo4j.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/python.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/slack.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/splunk.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/stdout.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/subdomains.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/teams.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/txt.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/web_report.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/output/websocket.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/paramminer_cookies.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/paramminer_getparams.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/paramminer_headers.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/passivetotal.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/pgp.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/portscan.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/postman.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/postman_download.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/rapiddns.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/report/affiliates.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/report/asn.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/report/base.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/robots.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/secretsdb.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/securitytrails.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/securitytxt.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/sitedossier.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/skymem.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/smuggler.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/social.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/sslcert.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/subdomaincenter.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/subdomainradar.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/telerik.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/templates/bucket.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/templates/github.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/templates/postman.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/templates/shodan.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/templates/webhook.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/unstructured.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/url_manipulation.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/urlscan.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/viewdns.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/wafw00f.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/wappalyzer.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/wayback.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/wpscan.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/modules/zoomeye.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/baddns-thorough.yml +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/cloud-enum.yml +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/code-enum.yml +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/email-enum.yml +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/kitchen-sink.yml +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/spider.yml +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/web/dirbust-heavy.yml +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/web/dirbust-light.yml +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/web/dotnet-audit.yml +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/web/iis-shortnames.yml +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/web/paramminer.yml +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/web-basic.yml +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/web-screenshots.yml +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/presets/web-thorough.yml +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/__init__.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/dispatcher.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/preset/__init__.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/preset/args.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/preset/conditions.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/preset/environ.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/preset/path.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/stats.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/scanner/target.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/scripts/docs.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/__init__.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/conftest.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/coverage.cfg +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/run_tests.sh +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test.conf +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_output.ndjson +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/__init__.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test__module__tests.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_bloom_filter.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_command.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_config.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_depsinstaller.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_dns.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_docs.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_engine.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_files.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_manager_deduplication.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_python_api.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_scan.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_scope.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_target.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_1/test_web.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/__init__.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/__init__.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/base.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_affiliates.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_aggregate.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_ajaxpro.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_anubisdb.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_asn.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_asset_inventory.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_azure_realm.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_azure_tenant.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_baddns.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_baddns_direct.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_baddns_zone.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_badsecrets.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_bevigil.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_binaryedge.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_bucket_amazon.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_bucket_azure.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_bucket_digitalocean.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_bucket_file_enum.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_bucket_firebase.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_bucket_google.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_builtwith.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_bypass403.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_c99.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_censys.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_certspotter.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_chaos.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_cloudcheck.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_code_repository.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_columbus.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_credshed.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_crt.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_csv.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dastardly.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dehashed.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_digitorus.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_discord.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dnsbrute.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dnsbrute_mutations.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dnscaa.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dnscommonsrv.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dnsdumpster.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dnsresolve.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_docker_pull.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dockerhub.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_dotnetnuke.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_emailformat.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_emails.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_excavate.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_ffuf.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_ffuf_shortnames.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_filedownload.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_fingerprintx.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_fullhunt.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_generic_ssrf.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_git.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_git_clone.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_github_codesearch.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_github_org.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_github_workflows.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_gitlab.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_gowitness.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_hackertarget.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_host_header.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_http.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_hunt.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_hunterio.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_iis_shortnames.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_internetdb.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_ip2location.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_ipneighbor.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_ipstack.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_json.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_leakix.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_myssl.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_neo4j.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_newsletters.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_ntlm.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_nuclei.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_oauth.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_otx.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_paramminer_cookies.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_paramminer_getparams.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_paramminer_headers.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_passivetotal.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_pgp.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_portscan.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_postman.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_postman_download.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_python.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_rapiddns.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_robots.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_secretsdb.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_securitytrails.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_securitytxt.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_sitedossier.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_skymem.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_slack.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_smuggler.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_social.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_speculate.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_splunk.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_sslcert.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_stdout.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_subdomaincenter.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_subdomainradar.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_subdomains.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_teams.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_telerik.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_trickest.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_trufflehog.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_txt.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_unstructured.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_url_manipulation.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_urlscan.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_vhost.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_viewdns.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_virustotal.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_wafw00f.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_wappalyzer.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_wayback.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_web_report.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_websocket.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_wpscan.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/module_tests/test_module_zoomeye.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/template_tests/__init__.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/test_step_2/template_tests/test_template_subdomain_enum.py +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/testsslcert.pem +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/test/testsslkey.pem +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/wordlists/devops_mutations.txt +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/wordlists/ffuf_shortname_candidates.txt +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/wordlists/ms_on_prem_subdomains.txt +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/wordlists/nameservers.txt +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/wordlists/paramminer_headers.txt +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/wordlists/paramminer_parameters.txt +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/wordlists/raft-small-extensions-lowercase_CLEANED.txt +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/wordlists/top_open_ports_nmap.txt +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/wordlists/valid_url_schemes.txt +0 -0
- {bbot-2.1.0.4959rc0 → bbot-2.1.0.5028rc0}/bbot/wordlists/wordninja_dns.txt.gz +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: bbot
|
|
3
|
-
Version: 2.1.0.
|
|
3
|
+
Version: 2.1.0.5028rc0
|
|
4
4
|
Summary: OSINT automation for hackers.
|
|
5
5
|
Home-page: https://github.com/blacklanternsecurity/bbot
|
|
6
6
|
License: GPL-3.0
|
|
@@ -14,6 +14,7 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.10
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
18
|
Classifier: Topic :: Security
|
|
18
19
|
Requires-Dist: ansible (>=7.3,<9.0)
|
|
19
20
|
Requires-Dist: ansible-runner (>=2.3.2,<3.0.0)
|
|
@@ -25,6 +25,7 @@ from bbot.core.helpers import (
|
|
|
25
25
|
is_domain,
|
|
26
26
|
is_subdomain,
|
|
27
27
|
is_ip,
|
|
28
|
+
is_ip_type,
|
|
28
29
|
is_ptr,
|
|
29
30
|
is_uri,
|
|
30
31
|
url_depth,
|
|
@@ -157,7 +158,7 @@ class BaseEvent:
|
|
|
157
158
|
Raises:
|
|
158
159
|
ValidationError: If either `scan` or `parent` are not specified and `_dummy` is False.
|
|
159
160
|
"""
|
|
160
|
-
self.
|
|
161
|
+
self._uuid = uuid.uuid4()
|
|
161
162
|
self._id = None
|
|
162
163
|
self._hash = None
|
|
163
164
|
self._data = None
|
|
@@ -352,6 +353,12 @@ class BaseEvent:
|
|
|
352
353
|
return 80
|
|
353
354
|
return self._port
|
|
354
355
|
|
|
356
|
+
@property
|
|
357
|
+
def netloc(self):
|
|
358
|
+
if self.host and is_ip_type(self.host, network=False):
|
|
359
|
+
return make_netloc(self.host, self.port)
|
|
360
|
+
return None
|
|
361
|
+
|
|
355
362
|
@property
|
|
356
363
|
def host_stem(self):
|
|
357
364
|
"""
|
|
@@ -440,11 +447,6 @@ class BaseEvent:
|
|
|
440
447
|
no_host_information = not bool(self.host)
|
|
441
448
|
return self._always_emit or always_emit_tags or no_host_information
|
|
442
449
|
|
|
443
|
-
@property
|
|
444
|
-
def quick_emit(self):
|
|
445
|
-
no_host_information = not bool(self.host)
|
|
446
|
-
return self._quick_emit or no_host_information
|
|
447
|
-
|
|
448
450
|
@property
|
|
449
451
|
def id(self):
|
|
450
452
|
"""
|
|
@@ -454,6 +456,13 @@ class BaseEvent:
|
|
|
454
456
|
self._id = f"{self.type}:{self.data_hash.hex()}"
|
|
455
457
|
return self._id
|
|
456
458
|
|
|
459
|
+
@property
|
|
460
|
+
def uuid(self):
|
|
461
|
+
"""
|
|
462
|
+
A universally unique identifier for the event
|
|
463
|
+
"""
|
|
464
|
+
return f"{self.type}:{self._uuid}"
|
|
465
|
+
|
|
457
466
|
@property
|
|
458
467
|
def data_hash(self):
|
|
459
468
|
"""
|
|
@@ -746,7 +755,7 @@ class BaseEvent:
|
|
|
746
755
|
"""
|
|
747
756
|
j = dict()
|
|
748
757
|
# type, ID, scope description
|
|
749
|
-
for i in ("type", "id", "uuid", "scope_description"):
|
|
758
|
+
for i in ("type", "id", "uuid", "scope_description", "netloc"):
|
|
750
759
|
v = getattr(self, i, "")
|
|
751
760
|
if v:
|
|
752
761
|
j.update({i: str(v)})
|
|
@@ -765,6 +774,8 @@ class BaseEvent:
|
|
|
765
774
|
j["host"] = str(self.host)
|
|
766
775
|
j["resolved_hosts"] = sorted(str(h) for h in self.resolved_hosts)
|
|
767
776
|
j["dns_children"] = {k: list(v) for k, v in self.dns_children.items()}
|
|
777
|
+
if isinstance(self.port, int):
|
|
778
|
+
j["port"] = self.port
|
|
768
779
|
# web spider distance
|
|
769
780
|
web_spider_distance = getattr(self, "web_spider_distance", None)
|
|
770
781
|
if web_spider_distance is not None:
|
|
@@ -1537,6 +1548,13 @@ class RAW_DNS_RECORD(DictHostEvent, DnsEvent):
|
|
|
1537
1548
|
_always_emit_tags = ["target"]
|
|
1538
1549
|
|
|
1539
1550
|
|
|
1551
|
+
class MOBILE_APP(DictEvent):
|
|
1552
|
+
_always_emit = True
|
|
1553
|
+
|
|
1554
|
+
def _pretty_string(self):
|
|
1555
|
+
return self.data["url"]
|
|
1556
|
+
|
|
1557
|
+
|
|
1540
1558
|
def make_event(
|
|
1541
1559
|
data,
|
|
1542
1560
|
event_type=None,
|
|
@@ -1707,7 +1725,7 @@ def event_from_json(j, siem_friendly=False):
|
|
|
1707
1725
|
event = make_event(**kwargs)
|
|
1708
1726
|
event_uuid = j.get("uuid", None)
|
|
1709
1727
|
if event_uuid is not None:
|
|
1710
|
-
event.
|
|
1728
|
+
event._uuid = uuid.UUID(event_uuid.split(":")[-1])
|
|
1711
1729
|
|
|
1712
1730
|
resolved_hosts = j.get("resolved_hosts", [])
|
|
1713
1731
|
event._resolved_hosts = set(resolved_hosts)
|
|
@@ -1719,7 +1737,8 @@ def event_from_json(j, siem_friendly=False):
|
|
|
1719
1737
|
event._parent_id = parent_id
|
|
1720
1738
|
parent_uuid = j.get("parent_uuid", None)
|
|
1721
1739
|
if parent_uuid is not None:
|
|
1722
|
-
|
|
1740
|
+
parent_type, parent_uuid = parent_uuid.split(":", 1)
|
|
1741
|
+
event._parent_uuid = parent_type + ":" + str(uuid.UUID(parent_uuid))
|
|
1723
1742
|
return event
|
|
1724
1743
|
except KeyError as e:
|
|
1725
1744
|
raise ValidationError(f"Event missing required field: {e}")
|
|
@@ -621,12 +621,13 @@ def is_ip(d, version=None):
|
|
|
621
621
|
return False
|
|
622
622
|
|
|
623
623
|
|
|
624
|
-
def is_ip_type(i):
|
|
624
|
+
def is_ip_type(i, network=None):
|
|
625
625
|
"""
|
|
626
626
|
Checks if the given object is an instance of an IPv4 or IPv6 type from the ipaddress module.
|
|
627
627
|
|
|
628
628
|
Args:
|
|
629
629
|
i (ipaddress._BaseV4 or ipaddress._BaseV6): The IP object to check.
|
|
630
|
+
network (bool, optional): Whether to restrict the check to network types (IPv4Network or IPv6Network). Defaults to False.
|
|
630
631
|
|
|
631
632
|
Returns:
|
|
632
633
|
bool: True if the object is an instance of ipaddress._BaseV4 or ipaddress._BaseV6, False otherwise.
|
|
@@ -639,6 +640,12 @@ def is_ip_type(i):
|
|
|
639
640
|
>>> is_ip_type("192.168.1.0/24")
|
|
640
641
|
False
|
|
641
642
|
"""
|
|
643
|
+
if network is not None:
|
|
644
|
+
is_network = ipaddress._BaseNetwork in i.__class__.__mro__
|
|
645
|
+
if network:
|
|
646
|
+
return is_network
|
|
647
|
+
else:
|
|
648
|
+
return not is_network
|
|
642
649
|
return ipaddress._IPAddressBase in i.__class__.__mro__
|
|
643
650
|
|
|
644
651
|
|
|
@@ -1260,7 +1267,7 @@ def gen_numbers(n, padding=2):
|
|
|
1260
1267
|
return results
|
|
1261
1268
|
|
|
1262
1269
|
|
|
1263
|
-
def make_netloc(host, port):
|
|
1270
|
+
def make_netloc(host, port=None):
|
|
1264
1271
|
"""Constructs a network location string from a given host and port.
|
|
1265
1272
|
|
|
1266
1273
|
Args:
|
|
@@ -1289,7 +1296,7 @@ def make_netloc(host, port):
|
|
|
1289
1296
|
if is_ip(host, version=6):
|
|
1290
1297
|
host = f"[{host}]"
|
|
1291
1298
|
if port is None:
|
|
1292
|
-
return host
|
|
1299
|
+
return str(host)
|
|
1293
1300
|
return f"{host}:{port}"
|
|
1294
1301
|
|
|
1295
1302
|
|
|
@@ -54,6 +54,9 @@ ptr_regex = re.compile(_ptr_regex)
|
|
|
54
54
|
# uuid regex
|
|
55
55
|
_uuid_regex = r"[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}"
|
|
56
56
|
uuid_regex = re.compile(_uuid_regex, re.I)
|
|
57
|
+
# event uuid regex
|
|
58
|
+
_event_uuid_regex = r"[0-9A-Z_]+:[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}"
|
|
59
|
+
event_uuid_regex = re.compile(_event_uuid_regex, re.I)
|
|
57
60
|
|
|
58
61
|
_open_port_regexes = (
|
|
59
62
|
_dns_name_regex + r":[0-9]{1,5}",
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import re
|
|
2
1
|
import logging
|
|
3
2
|
import warnings
|
|
4
3
|
from pathlib import Path
|
|
@@ -464,53 +463,6 @@ class WebHelper(EngineClient):
|
|
|
464
463
|
log.debug(f"Error parsing beautifulsoup: {e}")
|
|
465
464
|
return False
|
|
466
465
|
|
|
467
|
-
user_keywords = [re.compile(r, re.I) for r in ["user", "login", "email"]]
|
|
468
|
-
pass_keywords = [re.compile(r, re.I) for r in ["pass"]]
|
|
469
|
-
|
|
470
|
-
def is_login_page(self, html):
|
|
471
|
-
"""
|
|
472
|
-
TODO: convert this into an excavate YARA rule
|
|
473
|
-
|
|
474
|
-
Determines if the provided HTML content contains a login page.
|
|
475
|
-
|
|
476
|
-
This function parses the HTML to search for forms with input fields typically used for
|
|
477
|
-
authentication. If it identifies password fields or a combination of username and password
|
|
478
|
-
fields, it returns True.
|
|
479
|
-
|
|
480
|
-
Args:
|
|
481
|
-
html (str): The HTML content to analyze.
|
|
482
|
-
|
|
483
|
-
Returns:
|
|
484
|
-
bool: True if the HTML contains a login page, otherwise False.
|
|
485
|
-
|
|
486
|
-
Examples:
|
|
487
|
-
>>> is_login_page('<form><input type="text" name="username"><input type="password" name="password"></form>')
|
|
488
|
-
True
|
|
489
|
-
|
|
490
|
-
>>> is_login_page('<form><input type="text" name="search"></form>')
|
|
491
|
-
False
|
|
492
|
-
"""
|
|
493
|
-
try:
|
|
494
|
-
soup = BeautifulSoup(html, "html.parser")
|
|
495
|
-
except Exception as e:
|
|
496
|
-
log.debug(f"Error parsing html: {e}")
|
|
497
|
-
return False
|
|
498
|
-
|
|
499
|
-
forms = soup.find_all("form")
|
|
500
|
-
|
|
501
|
-
# first, check for obvious password fields
|
|
502
|
-
for form in forms:
|
|
503
|
-
if form.find_all("input", {"type": "password"}):
|
|
504
|
-
return True
|
|
505
|
-
|
|
506
|
-
# next, check for forms that have both a user-like and password-like field
|
|
507
|
-
for form in forms:
|
|
508
|
-
user_fields = sum(bool(form.find_all("input", {"name": r})) for r in self.user_keywords)
|
|
509
|
-
pass_fields = sum(bool(form.find_all("input", {"name": r})) for r in self.pass_keywords)
|
|
510
|
-
if user_fields and pass_fields:
|
|
511
|
-
return True
|
|
512
|
-
return False
|
|
513
|
-
|
|
514
466
|
def response_to_json(self, response):
|
|
515
467
|
"""
|
|
516
468
|
Convert web response to JSON object, similar to the output of `httpx -irr -json`
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from bbot.modules.base import BaseModule
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class apkpure(BaseModule):
|
|
6
|
+
watched_events = ["MOBILE_APP"]
|
|
7
|
+
produced_events = ["FILESYSTEM"]
|
|
8
|
+
flags = ["passive", "safe", "code-enum"]
|
|
9
|
+
meta = {
|
|
10
|
+
"description": "Download android applications from apkpure.com",
|
|
11
|
+
"created_date": "2024-10-11",
|
|
12
|
+
"author": "@domwhewell-sage",
|
|
13
|
+
}
|
|
14
|
+
options = {"output_folder": ""}
|
|
15
|
+
options_desc = {"output_folder": "Folder to download apk's to"}
|
|
16
|
+
|
|
17
|
+
async def setup(self):
|
|
18
|
+
output_folder = self.config.get("output_folder")
|
|
19
|
+
if output_folder:
|
|
20
|
+
self.output_dir = Path(output_folder) / "apk_files"
|
|
21
|
+
else:
|
|
22
|
+
self.output_dir = self.scan.home / "apk_files"
|
|
23
|
+
self.helpers.mkdir(self.output_dir)
|
|
24
|
+
return await super().setup()
|
|
25
|
+
|
|
26
|
+
async def filter_event(self, event):
|
|
27
|
+
if event.type == "MOBILE_APP":
|
|
28
|
+
if "android" not in event.tags:
|
|
29
|
+
return False, "event is not an android app"
|
|
30
|
+
return True
|
|
31
|
+
|
|
32
|
+
async def handle_event(self, event):
|
|
33
|
+
app_id = event.data.get("id", "")
|
|
34
|
+
path = await self.download_apk(app_id)
|
|
35
|
+
if path:
|
|
36
|
+
await self.emit_event(
|
|
37
|
+
{"path": str(path)},
|
|
38
|
+
"FILESYSTEM",
|
|
39
|
+
tags=["apk", "file"],
|
|
40
|
+
parent=event,
|
|
41
|
+
context=f'{{module}} downloaded the apk "{app_id}" to: {path}',
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
async def download_apk(self, app_id):
|
|
45
|
+
path = None
|
|
46
|
+
url = f"https://d.apkpure.com/b/XAPK/{app_id}?version=latest"
|
|
47
|
+
self.helpers.mkdir(self.output_dir / app_id)
|
|
48
|
+
file_destination = self.output_dir / app_id / f"{app_id}.xapk"
|
|
49
|
+
result = await self.helpers.download(url, warn=False, filename=file_destination)
|
|
50
|
+
if result:
|
|
51
|
+
self.info(f'Downloaded "{app_id}" from "{url}", saved to {file_destination}')
|
|
52
|
+
path = file_destination
|
|
53
|
+
return path
|
|
@@ -23,12 +23,13 @@ class badsecrets(BaseModule):
|
|
|
23
23
|
self.custom_secrets = None
|
|
24
24
|
custom_secrets = self.config.get("custom_secrets", None)
|
|
25
25
|
if custom_secrets:
|
|
26
|
-
|
|
26
|
+
secrets_path = Path(custom_secrets).expanduser()
|
|
27
|
+
if secrets_path.is_file():
|
|
27
28
|
self.custom_secrets = custom_secrets
|
|
28
29
|
self.info(f"Successfully loaded secrets file [{custom_secrets}]")
|
|
29
30
|
else:
|
|
30
31
|
self.warning(f"custom secrets file [{custom_secrets}] is not valid")
|
|
31
|
-
return
|
|
32
|
+
return False, "Custom secrets file not valid"
|
|
32
33
|
return True
|
|
33
34
|
|
|
34
35
|
@property
|
|
@@ -984,8 +984,11 @@ class BaseModule:
|
|
|
984
984
|
def _outgoing_dedup_hash(self, event):
|
|
985
985
|
"""
|
|
986
986
|
Determines the criteria for what is considered to be a duplicate event if `suppress_dupes` is True.
|
|
987
|
+
|
|
988
|
+
We take into account the `internal` attribute we don't want an internal event (which isn't distributed to output modules)
|
|
989
|
+
to inadvertently suppress a non-internal event.
|
|
987
990
|
"""
|
|
988
|
-
return hash((event, self.name))
|
|
991
|
+
return hash((event, self.name, event.internal, event.always_emit))
|
|
989
992
|
|
|
990
993
|
def get_per_host_hash(self, event):
|
|
991
994
|
"""
|
|
@@ -1559,7 +1562,7 @@ class BaseModule:
|
|
|
1559
1562
|
self.trace()
|
|
1560
1563
|
|
|
1561
1564
|
|
|
1562
|
-
class
|
|
1565
|
+
class BaseInterceptModule(BaseModule):
|
|
1563
1566
|
"""
|
|
1564
1567
|
An Intercept Module is a special type of high-priority module that gets early access to events.
|
|
1565
1568
|
|
|
@@ -1571,7 +1574,6 @@ class InterceptModule(BaseModule):
|
|
|
1571
1574
|
"""
|
|
1572
1575
|
|
|
1573
1576
|
accept_dupes = True
|
|
1574
|
-
suppress_dupes = False
|
|
1575
1577
|
_intercept = True
|
|
1576
1578
|
|
|
1577
1579
|
async def _worker(self):
|
|
@@ -155,24 +155,25 @@ class dotnetnuke(BaseModule):
|
|
|
155
155
|
|
|
156
156
|
# InstallWizard SuperUser Privilege Escalation
|
|
157
157
|
result = await self.helpers.request(f'{event.data["url"]}/Install/InstallWizard.aspx')
|
|
158
|
-
if result
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
if result_confirm.status_code == 500:
|
|
163
|
-
description = "DotNetNuke InstallWizard SuperUser Privilege Escalation"
|
|
164
|
-
await self.emit_event(
|
|
165
|
-
{
|
|
166
|
-
"severity": "CRITICAL",
|
|
167
|
-
"description": description,
|
|
168
|
-
"host": str(event.host),
|
|
169
|
-
"url": f'{event.data["url"]}/Install/InstallWizard.aspx',
|
|
170
|
-
},
|
|
171
|
-
"VULNERABILITY",
|
|
172
|
-
event,
|
|
173
|
-
context=f'{{module}} scanned {event.data["url"]} and found critical {{event.type}}: {description}',
|
|
158
|
+
if result:
|
|
159
|
+
if result.status_code == 200:
|
|
160
|
+
result_confirm = await self.helpers.request(
|
|
161
|
+
f'{event.data["url"]}/Install/InstallWizard.aspx?__viewstate=1'
|
|
174
162
|
)
|
|
175
|
-
|
|
163
|
+
if result_confirm.status_code == 500:
|
|
164
|
+
description = "DotNetNuke InstallWizard SuperUser Privilege Escalation"
|
|
165
|
+
await self.emit_event(
|
|
166
|
+
{
|
|
167
|
+
"severity": "CRITICAL",
|
|
168
|
+
"description": description,
|
|
169
|
+
"host": str(event.host),
|
|
170
|
+
"url": f'{event.data["url"]}/Install/InstallWizard.aspx',
|
|
171
|
+
},
|
|
172
|
+
"VULNERABILITY",
|
|
173
|
+
event,
|
|
174
|
+
context=f'{{module}} scanned {event.data["url"]} and found critical {{event.type}}: {description}',
|
|
175
|
+
)
|
|
176
|
+
return
|
|
176
177
|
|
|
177
178
|
# DNNImageHandler.ashx Blind SSRF
|
|
178
179
|
self.event_dict[event.data["url"]] = event
|
|
@@ -137,10 +137,10 @@ class Generic_XXE(BaseSubmodule):
|
|
|
137
137
|
post_body = f"""<?xml version="1.0" encoding="ISO-8859-1"?>
|
|
138
138
|
<!DOCTYPE foo [
|
|
139
139
|
<!ELEMENT foo ANY >
|
|
140
|
-
<!ENTITY
|
|
140
|
+
<!ENTITY {rand_entity} SYSTEM "http://{subdomain_tag}.{self.parent_module.interactsh_domain}" >
|
|
141
141
|
]>
|
|
142
142
|
<foo>&{rand_entity};</foo>"""
|
|
143
|
-
test_url =
|
|
143
|
+
test_url = event.parsed_url.geturl()
|
|
144
144
|
r = await self.parent_module.helpers.curl(
|
|
145
145
|
url=test_url, method="POST", raw_body=post_body, headers={"Content-type": "application/xml"}
|
|
146
146
|
)
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
from bbot.modules.base import BaseModule
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class google_playstore(BaseModule):
|
|
5
|
+
watched_events = ["ORG_STUB", "CODE_REPOSITORY"]
|
|
6
|
+
produced_events = ["MOBILE_APP"]
|
|
7
|
+
flags = ["passive", "safe", "code-enum"]
|
|
8
|
+
meta = {
|
|
9
|
+
"description": "Search for android applications on play.google.com",
|
|
10
|
+
"created_date": "2024-10-08",
|
|
11
|
+
"author": "@domwhewell-sage",
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
base_url = "https://play.google.com"
|
|
15
|
+
|
|
16
|
+
async def setup(self):
|
|
17
|
+
self.app_link_regex = self.helpers.re.compile(r"/store/apps/details\?id=([a-zA-Z0-9._-]+)")
|
|
18
|
+
return True
|
|
19
|
+
|
|
20
|
+
async def filter_event(self, event):
|
|
21
|
+
if event.type == "CODE_REPOSITORY":
|
|
22
|
+
if "android" not in event.tags:
|
|
23
|
+
return False, "event is not an android repository"
|
|
24
|
+
return True
|
|
25
|
+
|
|
26
|
+
async def handle_event(self, event):
|
|
27
|
+
if event.type == "CODE_REPOSITORY":
|
|
28
|
+
await self.handle_url(event)
|
|
29
|
+
elif event.type == "ORG_STUB":
|
|
30
|
+
await self.handle_org_stub(event)
|
|
31
|
+
|
|
32
|
+
async def handle_url(self, event):
|
|
33
|
+
repo_url = event.data.get("url")
|
|
34
|
+
app_id = repo_url.split("id=")[1].split("&")[0]
|
|
35
|
+
await self.emit_event(
|
|
36
|
+
{"id": app_id, "url": repo_url},
|
|
37
|
+
"MOBILE_APP",
|
|
38
|
+
tags="android",
|
|
39
|
+
parent=event,
|
|
40
|
+
context=f'{{module}} extracted the mobile app name "{app_id}" from: {repo_url}',
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
async def handle_org_stub(self, event):
|
|
44
|
+
org_name = event.data
|
|
45
|
+
self.verbose(f"Searching for any android applications for {org_name}")
|
|
46
|
+
for apk_name in await self.query(org_name):
|
|
47
|
+
valid_apk = await self.validate_apk(apk_name)
|
|
48
|
+
if valid_apk:
|
|
49
|
+
self.verbose(f"Got {apk_name} from playstore")
|
|
50
|
+
await self.emit_event(
|
|
51
|
+
{"id": apk_name, "url": f"{self.base_url}/store/apps/details?id={apk_name}"},
|
|
52
|
+
"MOBILE_APP",
|
|
53
|
+
tags="android",
|
|
54
|
+
parent=event,
|
|
55
|
+
context=f'{{module}} searched play.google.com for apps belonging to "{org_name}" and found "{apk_name}" to be in scope',
|
|
56
|
+
)
|
|
57
|
+
else:
|
|
58
|
+
self.debug(f"Got {apk_name} from playstore app details does not contain any in-scope URLs or Emails")
|
|
59
|
+
|
|
60
|
+
async def query(self, query):
|
|
61
|
+
app_links = []
|
|
62
|
+
url = f"{self.base_url}/store/search?q={self.helpers.quote(query)}&c=apps"
|
|
63
|
+
r = await self.helpers.request(url)
|
|
64
|
+
if r is None:
|
|
65
|
+
return app_links
|
|
66
|
+
status_code = getattr(r, "status_code", 0)
|
|
67
|
+
try:
|
|
68
|
+
html_content = r.content.decode("utf-8")
|
|
69
|
+
# Use regex to find all app links
|
|
70
|
+
app_links = await self.helpers.re.findall(self.app_link_regex, html_content)
|
|
71
|
+
except Exception as e:
|
|
72
|
+
self.warning(f"Failed to parse html response from {r.url} (HTTP status: {status_code}): {e}")
|
|
73
|
+
return app_links
|
|
74
|
+
return app_links
|
|
75
|
+
|
|
76
|
+
async def validate_apk(self, apk_name):
|
|
77
|
+
"""
|
|
78
|
+
Check the app details page the "App support" section will include URLs or Emails to the app developer
|
|
79
|
+
"""
|
|
80
|
+
in_scope = False
|
|
81
|
+
url = f"{self.base_url}/store/apps/details?id={apk_name}"
|
|
82
|
+
r = await self.helpers.request(url)
|
|
83
|
+
if r is None:
|
|
84
|
+
return in_scope
|
|
85
|
+
status_code = getattr(r, "status_code", 0)
|
|
86
|
+
if status_code == 200:
|
|
87
|
+
html = r.text
|
|
88
|
+
in_scope_hosts = await self.scan.extract_in_scope_hostnames(html)
|
|
89
|
+
if in_scope_hosts:
|
|
90
|
+
in_scope = True
|
|
91
|
+
else:
|
|
92
|
+
self.warning(f"Failed to fetch {url} (HTTP status: {status_code})")
|
|
93
|
+
return in_scope
|
|
@@ -172,9 +172,6 @@ class httpx(BaseModule):
|
|
|
172
172
|
httpx_ip = j.get("host", "")
|
|
173
173
|
if httpx_ip:
|
|
174
174
|
tags.append(f"ip-{httpx_ip}")
|
|
175
|
-
# detect login pages
|
|
176
|
-
if self.helpers.web.is_login_page(j.get("body", "")):
|
|
177
|
-
tags.append("login-page")
|
|
178
175
|
# grab title
|
|
179
176
|
title = self.helpers.tagify(j.get("title", ""), maxlen=30)
|
|
180
177
|
if title:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
from bbot.modules.base import
|
|
1
|
+
from bbot.modules.base import BaseInterceptModule
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
class CloudCheck(
|
|
4
|
+
class CloudCheck(BaseInterceptModule):
|
|
5
5
|
watched_events = ["*"]
|
|
6
6
|
meta = {"description": "Tag events by cloud provider, identify cloud resources like storage buckets"}
|
|
7
7
|
scope_distance_modifier = 1
|
|
@@ -3,11 +3,11 @@ from contextlib import suppress
|
|
|
3
3
|
|
|
4
4
|
from bbot.errors import ValidationError
|
|
5
5
|
from bbot.core.helpers.dns.engine import all_rdtypes
|
|
6
|
-
from bbot.modules.base import InterceptModule, BaseModule
|
|
7
6
|
from bbot.core.helpers.dns.helpers import extract_targets
|
|
7
|
+
from bbot.modules.base import BaseInterceptModule, BaseModule
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
class DNSResolve(
|
|
10
|
+
class DNSResolve(BaseInterceptModule):
|
|
11
11
|
watched_events = ["*"]
|
|
12
12
|
_priority = 1
|
|
13
13
|
scope_distance_modifier = None
|
|
@@ -16,12 +16,6 @@ class DNSResolve(InterceptModule):
|
|
|
16
16
|
_name = "host"
|
|
17
17
|
_type = "internal"
|
|
18
18
|
|
|
19
|
-
def _outgoing_dedup_hash(self, event):
|
|
20
|
-
# this exists to ensure a second, more interesting host isn't passed up
|
|
21
|
-
# because its ugly cousin spent its one dedup token before it arrived
|
|
22
|
-
# by removing those race conditions, this makes for more consistent results
|
|
23
|
-
return hash((event, self.name, event.always_emit))
|
|
24
|
-
|
|
25
19
|
@property
|
|
26
20
|
def module_threads(self):
|
|
27
21
|
return self.dns_config.get("threads", 25)
|
|
@@ -6,6 +6,7 @@ import regex as re
|
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
from bbot.errors import ExcavateError
|
|
8
8
|
import bbot.core.helpers.regexes as bbot_regexes
|
|
9
|
+
from bbot.modules.base import BaseInterceptModule
|
|
9
10
|
from bbot.modules.internal.base import BaseInternalModule
|
|
10
11
|
from urllib.parse import urlparse, urljoin, parse_qs, urlunparse
|
|
11
12
|
|
|
@@ -153,7 +154,9 @@ class ExcavateRule:
|
|
|
153
154
|
yara_rule_settings = YaraRuleSettings(description, tags, emit_match)
|
|
154
155
|
yara_results = {}
|
|
155
156
|
for h in r.strings:
|
|
156
|
-
yara_results[h.identifier.lstrip("$")] = sorted(
|
|
157
|
+
yara_results[h.identifier.lstrip("$")] = sorted(
|
|
158
|
+
set([i.matched_data.decode("utf-8", errors="ignore") for i in h.instances])
|
|
159
|
+
)
|
|
157
160
|
await self.process(yara_results, event, yara_rule_settings, discovery_context)
|
|
158
161
|
|
|
159
162
|
async def process(self, yara_results, event, yara_rule_settings, discovery_context):
|
|
@@ -279,7 +282,7 @@ class CustomExtractor(ExcavateRule):
|
|
|
279
282
|
await self.report(event_data, event, yara_rule_settings, discovery_context)
|
|
280
283
|
|
|
281
284
|
|
|
282
|
-
class excavate(BaseInternalModule):
|
|
285
|
+
class excavate(BaseInternalModule, BaseInterceptModule):
|
|
283
286
|
"""
|
|
284
287
|
Example (simple) Excavate Rules:
|
|
285
288
|
|
|
@@ -310,6 +313,7 @@ class excavate(BaseInternalModule):
|
|
|
310
313
|
"custom_yara_rules": "Include custom Yara rules",
|
|
311
314
|
}
|
|
312
315
|
scope_distance_modifier = None
|
|
316
|
+
accept_dupes = False
|
|
313
317
|
|
|
314
318
|
_module_threads = 8
|
|
315
319
|
|
|
@@ -669,8 +673,32 @@ class excavate(BaseInternalModule):
|
|
|
669
673
|
|
|
670
674
|
class URLExtractor(ExcavateRule):
|
|
671
675
|
yara_rules = {
|
|
672
|
-
"url_full":
|
|
673
|
-
|
|
676
|
+
"url_full": (
|
|
677
|
+
r"""
|
|
678
|
+
rule url_full {
|
|
679
|
+
meta:
|
|
680
|
+
tags = "spider-danger"
|
|
681
|
+
description = "contains full URL"
|
|
682
|
+
strings:
|
|
683
|
+
$url_full = /https?:\/\/([\w\.-]+)(:\d{1,5})?([\/\w\.-]*)/
|
|
684
|
+
condition:
|
|
685
|
+
$url_full
|
|
686
|
+
}
|
|
687
|
+
"""
|
|
688
|
+
),
|
|
689
|
+
"url_attr": (
|
|
690
|
+
r"""
|
|
691
|
+
rule url_attr {
|
|
692
|
+
meta:
|
|
693
|
+
tags = "spider-danger"
|
|
694
|
+
description = "contains tag with src or href attribute"
|
|
695
|
+
strings:
|
|
696
|
+
$url_attr = /<[^>]+(href|src)=["\'][^"\']*["\'][^>]*>/
|
|
697
|
+
condition:
|
|
698
|
+
$url_attr
|
|
699
|
+
}
|
|
700
|
+
"""
|
|
701
|
+
),
|
|
674
702
|
}
|
|
675
703
|
full_url_regex = re.compile(r"(https?)://((?:\w|\d)(?:[\d\w-]+\.?)+(?::\d{1,5})?(?:/[-\w\.\(\)]*[-\w\.]+)*/?)")
|
|
676
704
|
full_url_regex_strict = re.compile(r"^(https?):\/\/([\w.-]+)(?::\d{1,5})?(\/[\w\/\.-]*)?(\?[^\s]+)?$")
|
|
@@ -749,6 +777,25 @@ class excavate(BaseInternalModule):
|
|
|
749
777
|
for domain_str in yara_results[identifier]:
|
|
750
778
|
await self.report(domain_str, event, yara_rule_settings, discovery_context, event_type="DNS_NAME")
|
|
751
779
|
|
|
780
|
+
class LoginPageExtractor(ExcavateRule):
|
|
781
|
+
yara_rules = {
|
|
782
|
+
"login_page": r"""
|
|
783
|
+
rule login_page {
|
|
784
|
+
meta:
|
|
785
|
+
description = "Detects login pages with username and password fields"
|
|
786
|
+
strings:
|
|
787
|
+
$username_field = /<input[^>]+name=["']?(user|login|email)/ nocase
|
|
788
|
+
$password_field = /<input[^>]+name=["']?passw?/ nocase
|
|
789
|
+
condition:
|
|
790
|
+
$username_field and $password_field
|
|
791
|
+
}
|
|
792
|
+
"""
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
async def process(self, yara_results, event, yara_rule_settings, discovery_context):
|
|
796
|
+
if yara_results:
|
|
797
|
+
event.add_tag("login-page")
|
|
798
|
+
|
|
752
799
|
def add_yara_rule(self, rule_name, rule_content, rule_instance):
|
|
753
800
|
rule_instance.name = rule_name
|
|
754
801
|
self.yara_rules_dict[rule_name] = rule_content
|
|
@@ -829,6 +876,8 @@ class excavate(BaseInternalModule):
|
|
|
829
876
|
yara_rules_combined = "\n".join(self.yara_rules_dict.values())
|
|
830
877
|
try:
|
|
831
878
|
self.info(f"Compiling {len(self.yara_rules_dict):,} YARA rules")
|
|
879
|
+
for rule_name, rule_content in self.yara_rules_dict.items():
|
|
880
|
+
self.debug(f" - {rule_name}")
|
|
832
881
|
self.yara_rules = yara.compile(source=yara_rules_combined)
|
|
833
882
|
except yara.SyntaxError as e:
|
|
834
883
|
self.debug(yara_rules_combined)
|