Configuration Overview
BBOT has a YAML config at ~/.config/bbot
. This config is different from the command-line arguments. This is where you change settings such as BBOT's HTTP proxy, rate limits, or global User-Agent. It's also where you put modules' API keys.
For a list of all possible config options, see:
For examples of common config changes, see Tips and Tricks.
Configuration Files
BBOT loads its config from the following files, in this order:
~/.config/bbot/bbot.yml
<-- Use this one as your main config~/.config/bbot/secrets.yml
<-- Use this one for sensitive stuff like API keys- command line (
--config
) <-- Use this to specify a custom config file or override individual config options
These config files will be automatically created for you when you first run BBOT.
YAML Config vs Command Line
You can specify config options either via the command line or the config. For example, if you want to proxy your BBOT scan through a local proxy like Burp Suite, you could either do:
# send BBOT traffic through an HTTP proxy
bbot -t evilcorp.com --config http_proxy=http://127.0.0.1:8080
Or, in ~/.config/bbot/config.yml
:
http_proxy: http://127.0.0.1:8080
These two are equivalent.
Config options specified via the command-line take precedence over all others. You can give BBOT a custom config file with --config myconf.yml
, or individual arguments like this: --config modules.shodan_dns.api_key=deadbeef
. To display the full and current BBOT config, including any command-line arguments, use bbot --current-config
.
Note that placing the following in bbot.yml
:
modules:
shodan_dns:
api_key: deadbeef
bbot --config modules.shodan_dns.api_key=deadbeef
Global Config Options
Below is a full list of the config options supported, along with their defaults.
### BASIC OPTIONS ###
# BBOT working directory
home: ~/.bbot
# Don't output events that are further than this from the main scope
# 1 == 1 hope away from main scope
# 0 == in scope only
scope_report_distance: 0
# Generate new DNS_NAME and IP_ADDRESS events through DNS resolution
dns_resolution: true
# Limit the number of BBOT threads
max_threads: 25
# Rate-limit DNS
dns_queries_per_second: 1000
# Rate-limit HTTP
web_requests_per_second: 100
# Interval for displaying status messages
status_frequency: 15
# HTTP proxy
http_proxy:
# Web user-agent
user_agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.2151.97
### WEB SPIDER ###
# Set the maximum number of HTTP links that can be followed in a row (0 == no spidering allowed)
web_spider_distance: 0
# Set the maximum directory depth for the web spider
web_spider_depth: 1
# Set the maximum number of links that can be followed per page
web_spider_links_per_page: 25
### ADVANCED OPTIONS ###
# How far out from the main scope to search
scope_search_distance: 0
# How far out from the main scope to resolve DNS names / IPs
scope_dns_search_distance: 1
# Limit how many DNS records can be followed in a row (stop malicious/runaway DNS records)
dns_resolve_distance: 5
# Infer certain events from others, e.g. IPs from IP ranges, DNS_NAMEs from URLs, etc.
speculate: True
# Passively search event data for URLs, hostnames, emails, etc.
excavate: True
# Summarize activity at the end of a scan
aggregate: True
# HTTP timeout (for Python requests; API calls, etc.)
http_timeout: 10
# HTTP timeout (for httpx)
httpx_timeout: 5
# Custom HTTP headers (e.g. cookies, etc.)
# in the format { "Header-Key": "header_value" }
# These are attached to all in-scope HTTP requests
# Note that some modules (e.g. github) may end up sending these to out-of-scope resources
http_headers: {}
# HTTP retries (for Python requests; API calls, etc.)
http_retries: 1
# HTTP retries (for httpx)
httpx_retries: 1
# Enable/disable debug messages for web requests/responses
http_debug: false
# Maximum number of HTTP redirects to follow
http_max_redirects: 5
# DNS query timeout
dns_timeout: 5
# How many times to retry DNS queries
dns_retries: 1
# Disable BBOT's smart DNS wildcard handling for select domains
dns_wildcard_ignore: []
# How many sanity checks to make when verifying wildcard DNS
# Increase this value if BBOT's wildcard detection isn't working
dns_wildcard_tests: 10
# Skip DNS requests for a certain domain and rdtype after encountering this many timeouts or SERVFAILs
# This helps prevent faulty DNS servers from hanging up the scan
dns_abort_threshold: 50
# Don't show PTR records containing IP addresses
dns_filter_ptrs: true
# Enable/disable debug messages for dns queries
dns_debug: false
# Whether to verify SSL certificates
ssl_verify: false
# How many scan results to keep before cleaning up the older ones
keep_scans: 20
# Completely ignore URLs with these extensions
url_extension_blacklist:
# images
- png
- jpg
- bmp
- ico
- jpeg
- gif
- svg
- webp
# web/fonts
- css
- woff
- woff2
- ttf
- eot
- sass
- scss
# audio
- mp3
- m4a
- wav
- flac
# video
- mp4
- mkv
- avi
- wmv
- mov
- flv
- webm
# Distribute URLs with these extensions only to httpx (these are omitted from output)
url_extension_httpx_only:
- js
# Don't output these types of events (they are still distributed to modules)
omit_event_types:
- HTTP_RESPONSE
- URL_UNVERIFIED
- DNS_NAME_UNRESOLVED
# - IP_ADDRESS
# URL of BBOT server
agent_url: ''
# Agent Bearer authentication token
agent_token: ''
# Custom interactsh server settings
interactsh_server: null
interactsh_token: null
interactsh_disable: false
# For performance reasons, always skip these DNS queries
# Microsoft's DNS infrastructure is misconfigured so that certain queries to mail.protection.outlook.com always time out
dns_omit_queries:
- SRV:mail.protection.outlook.com
- CNAME:mail.protection.outlook.com
- TXT:mail.protection.outlook.com
Module Config Options
Many modules accept their own configuration options. These options have the ability to change their behavior. For example, the nmap
module accepts options for ports
, timing
, etc. Below is a list of all possible module config options.
Config Option | Type | Description | Default |
---|---|---|---|
modules.baddns.custom_nameservers | list | Force BadDNS to use a list of custom nameservers | [] |
modules.baddns.only_high_confidence | bool | Do not emit low-confidence or generic detections | False |
modules.baddns_zone.custom_nameservers | list | Force BadDNS to use a list of custom nameservers | [] |
modules.baddns_zone.only_high_confidence | bool | Do not emit low-confidence or generic detections | False |
modules.bucket_amazon.permutations | bool | Whether to try permutations | False |
modules.bucket_azure.permutations | bool | Whether to try permutations | False |
modules.bucket_digitalocean.permutations | bool | Whether to try permutations | False |
modules.bucket_firebase.permutations | bool | Whether to try permutations | False |
modules.bucket_google.permutations | bool | Whether to try permutations | False |
modules.ffuf.extensions | str | Optionally include a list of extensions to extend the keyword with (comma separated) | |
modules.ffuf.lines | int | take only the first N lines from the wordlist when finding directories | 5000 |
modules.ffuf.max_depth | int | the maximum directory depth to attempt to solve | 0 |
modules.ffuf.version | str | ffuf version | 2.0.0 |
modules.ffuf.wordlist | str | Specify wordlist to use when finding directories | https://raw.githubusercontent.com/danielmiessler/SecLists/master/Discovery/Web-Content/raft-small-directories.txt |
modules.ffuf_shortnames.extensions | str | Optionally include a list of extensions to extend the keyword with (comma separated) | |
modules.ffuf_shortnames.find_common_prefixes | bool | Attempt to automatically detect common prefixes and make additional ffuf runs against them | False |
modules.ffuf_shortnames.find_delimiters | bool | Attempt to detect common delimiters and make additional ffuf runs against them | True |
modules.ffuf_shortnames.ignore_redirects | bool | Explicitly ignore redirects (301,302) | True |
modules.ffuf_shortnames.lines | int | take only the first N lines from the wordlist when finding directories | 1000000 |
modules.ffuf_shortnames.max_depth | int | the maximum directory depth to attempt to solve | 1 |
modules.ffuf_shortnames.version | str | ffuf version | 2.0.0 |
modules.ffuf_shortnames.wordlist | str | Specify wordlist to use when finding directories | |
modules.ffuf_shortnames.wordlist_extensions | str | Specify wordlist to use when making extension lists | |
modules.filedownload.extensions | list | File extensions to download | ['bak', 'bash', 'bashrc', 'conf', 'cfg', 'crt', 'csv', 'db', 'sqlite', 'doc', 'docx', 'exe', 'ica', 'indd', 'ini', 'jar', 'key', 'pub', 'log', 'markdown', 'md', 'msi', 'odg', 'odp', 'ods', 'odt', 'pdf', 'pem', 'pps', 'ppsx', 'ppt', 'pptx', 'ps1', 'raw', 'rdp', 'sh', 'sql', 'swp', 'sxw', 'tar', 'tar.gz', 'zip', 'txt', 'vbs', 'wpd', 'xls', 'xlsx', 'xml', 'yml', 'yaml'] |
modules.filedownload.max_filesize | str | Cancel download if filesize is greater than this size | 10MB |
modules.fingerprintx.version | str | fingerprintx version | 1.1.4 |
modules.gitlab.api_key | str | Gitlab access token | |
modules.gowitness.idle_timeout | int | Skip the current gowitness batch if it stalls for longer than this many seconds | 1800 |
modules.gowitness.output_path | str | Where to save screenshots | |
modules.gowitness.resolution_x | int | Screenshot resolution x | 1440 |
modules.gowitness.resolution_y | int | Screenshot resolution y | 900 |
modules.gowitness.social | bool | Whether to screenshot social media webpages | True |
modules.gowitness.threads | int | How many gowitness threads to spawn (default is number of CPUs x 2) | 0 |
modules.gowitness.timeout | int | Preflight check timeout | 10 |
modules.gowitness.version | str | Gowitness version | 2.4.2 |
modules.httpx.in_scope_only | bool | Only visit web resources that are in scope. | True |
modules.httpx.max_response_size | int | Max response size in bytes | 5242880 |
modules.httpx.probe_all_ips | bool | Probe all the ips associated with same host | False |
modules.httpx.store_responses | bool | Save raw HTTP responses to scan folder | False |
modules.httpx.threads | int | Number of httpx threads to use | 50 |
modules.httpx.version | str | httpx version | 1.2.5 |
modules.iis_shortnames.detect_only | bool | Only detect the vulnerability and do not run the shortname scanner | True |
modules.iis_shortnames.max_node_count | int | Limit how many nodes to attempt to resolve on any given recursion branch | 50 |
modules.masscan.ping_first | bool | Only portscan hosts that reply to pings | False |
modules.masscan.ping_only | bool | Ping sweep only, no portscan | False |
modules.masscan.ports | str | Ports to scan | |
modules.masscan.rate | int | Rate in packets per second | 600 |
modules.masscan.top_ports | int | Top ports to scan (default 100) (to override, specify 'ports') | 100 |
modules.masscan.use_cache | bool | Instead of scanning, use the results from the previous scan | False |
modules.masscan.wait | int | Seconds to wait for replies after scan is complete | 5 |
modules.nmap.ports | str | Ports to scan | |
modules.nmap.skip_host_discovery | bool | skip host discovery (-Pn) | True |
modules.nmap.timing | str | -T<0-5>: Set timing template (higher is faster) |
T4 |
modules.nmap.top_ports | int | Top ports to scan (default 100) (to override, specify 'ports') | 100 |
modules.ntlm.try_all | bool | Try every NTLM endpoint | False |
modules.nuclei.batch_size | int | Number of targets to send to Nuclei per batch (default 200) | 200 |
modules.nuclei.budget | int | Used in budget mode to set the number of requests which will be allotted to the nuclei scan | 1 |
modules.nuclei.concurrency | int | maximum number of templates to be executed in parallel (default 25) | 25 |
modules.nuclei.directory_only | bool | Filter out 'file' URL event (default True) | True |
modules.nuclei.etags | str | tags to exclude from the scan | |
modules.nuclei.mode | str | manual | technology | severe | budget. Technology: Only activate based on technology events that match nuclei tags (nuclei -as mode). Manual (DEFAULT): Fully manual settings. Severe: Only critical and high severity templates without intrusive. Budget: Limit Nuclei to a specified number of HTTP requests | manual |
modules.nuclei.ratelimit | int | maximum number of requests to send per second (default 150) | 150 |
modules.nuclei.retries | int | number of times to retry a failed request (default 0) | 0 |
modules.nuclei.severity | str | Filter based on severity field available in the template. | |
modules.nuclei.silent | bool | Don't display nuclei's banner or status messages | False |
modules.nuclei.tags | str | execute a subset of templates that contain the provided tags | |
modules.nuclei.templates | str | template or template directory paths to include in the scan | |
modules.nuclei.version | str | nuclei version | 3.2.0 |
modules.oauth.try_all | bool | Check for OAUTH/IODC on every subdomain and URL. | False |
modules.paramminer_cookies.http_extract | bool | Attempt to find additional wordlist words from the HTTP Response | True |
modules.paramminer_cookies.skip_boring_words | bool | Remove commonly uninteresting words from the wordlist | True |
modules.paramminer_cookies.wordlist | str | Define the wordlist to be used to derive cookies | |
modules.paramminer_getparams.http_extract | bool | Attempt to find additional wordlist words from the HTTP Response | True |
modules.paramminer_getparams.skip_boring_words | bool | Remove commonly uninteresting words from the wordlist | True |
modules.paramminer_getparams.wordlist | str | Define the wordlist to be used to derive headers | |
modules.paramminer_headers.http_extract | bool | Attempt to find additional wordlist words from the HTTP Response | True |
modules.paramminer_headers.skip_boring_words | bool | Remove commonly uninteresting words from the wordlist | True |
modules.paramminer_headers.wordlist | str | Define the wordlist to be used to derive headers | |
modules.robots.include_allow | bool | Include 'Allow' Entries | True |
modules.robots.include_disallow | bool | Include 'Disallow' Entries | True |
modules.robots.include_sitemap | bool | Include 'sitemap' entries | False |
modules.secretsdb.min_confidence | int | Only use signatures with this confidence score or higher | 99 |
modules.secretsdb.signatures | str | File path or URL to YAML signatures | https://raw.githubusercontent.com/blacklanternsecurity/secrets-patterns-db/master/db/rules-stable.yml |
modules.sslcert.skip_non_ssl | bool | Don't try common non-SSL ports | True |
modules.sslcert.timeout | float | Socket connect timeout in seconds | 5.0 |
modules.telerik.exploit_RAU_crypto | bool | Attempt to confirm any RAU AXD detections are vulnerable | False |
modules.url_manipulation.allow_redirects | bool | Allowing redirects will sometimes create false positives. Disallowing will sometimes create false negatives. Allowed by default. | True |
modules.vhost.force_basehost | str | Use a custom base host (e.g. evilcorp.com) instead of the default behavior of using the current URL | |
modules.vhost.lines | int | take only the first N lines from the wordlist when finding directories | 5000 |
modules.vhost.wordlist | str | Wordlist containing subdomains | https://raw.githubusercontent.com/danielmiessler/SecLists/master/Discovery/DNS/subdomains-top1million-5000.txt |
modules.wafw00f.generic_detect | bool | When no specific WAF detections are made, try to perform a generic detect | True |
modules.anubisdb.limit | int | Limit the number of subdomains returned per query (increasing this may slow the scan due to garbage results from this API) | 1000 |
modules.bevigil.api_key | str | BeVigil OSINT API Key | |
modules.bevigil.urls | bool | Emit URLs in addition to DNS_NAMEs | False |
modules.binaryedge.api_key | str | BinaryEdge API key | |
modules.binaryedge.max_records | int | Limit results to help prevent exceeding API quota | 1000 |
modules.bucket_file_enum.file_limit | int | Limit the number of files downloaded per bucket | 50 |
modules.builtwith.api_key | str | Builtwith API key | |
modules.builtwith.redirects | bool | Also look up inbound and outbound redirects | True |
modules.c99.api_key | str | c99.nl API key | |
modules.censys.api_id | str | Censys.io API ID | |
modules.censys.api_secret | str | Censys.io API Secret | |
modules.censys.max_pages | int | Maximum number of pages to fetch (100 results per page) | 5 |
modules.chaos.api_key | str | Chaos API key | |
modules.credshed.credshed_url | str | URL of credshed server | |
modules.credshed.password | str | Credshed password | |
modules.credshed.username | str | Credshed username | |
modules.dehashed.api_key | str | DeHashed API Key | |
modules.dehashed.username | str | Email Address associated with your API key | |
modules.dnscommonsrv.max_event_handlers | int | How many instances of the module to run concurrently | 10 |
modules.dnscommonsrv.top | int | How many of the top SRV records to check | 50 |
modules.docker_pull.all_tags | bool | Download all tags from each registry (Default False) | False |
modules.docker_pull.output_folder | str | Folder to download docker repositories to | |
modules.fullhunt.api_key | str | FullHunt API Key | |
modules.git_clone.api_key | str | Github token | |
modules.git_clone.output_folder | str | Folder to clone repositories to | |
modules.github_codesearch.api_key | str | Github token | |
modules.github_codesearch.limit | int | Limit code search to this many results | 100 |
modules.github_org.api_key | str | Github token | |
modules.github_org.include_member_repos | bool | Also enumerate organization members' repositories | False |
modules.github_org.include_members | bool | Enumerate organization members | True |
modules.github_workflows.api_key | str | Github token | |
modules.github_workflows.num_logs | int | For each workflow fetch the last N successful runs logs (max 100) | 1 |
modules.hunterio.api_key | str | Hunter.IO API key | |
modules.ip2location.api_key | str | IP2location.io API Key | |
modules.ip2location.lang | str | Translation information(ISO639-1). The translation is only applicable for continent, country, region and city name. | |
modules.ipneighbor.num_bits | int | Netmask size (in CIDR notation) to check. Default is 4 bits (16 hosts) | 4 |
modules.ipstack.api_key | str | IPStack GeoIP API Key | |
modules.leakix.api_key | str | LeakIX API Key | |
modules.massdns.max_depth | int | How many subdomains deep to brute force, i.e. 5.4.3.2.1.evilcorp.com | 5 |
modules.massdns.max_mutations | int | Max number of smart mutations per subdomain | 500 |
modules.massdns.max_resolvers | int | Number of concurrent massdns resolvers | 1000 |
modules.massdns.wordlist | str | Subdomain wordlist URL | https://raw.githubusercontent.com/danielmiessler/SecLists/master/Discovery/DNS/subdomains-top1million-5000.txt |
modules.passivetotal.api_key | str | RiskIQ API Key | |
modules.passivetotal.username | str | RiskIQ Username | |
modules.pgp.search_urls | list | PGP key servers to search | ['https://keyserver.ubuntu.com/pks/lookup?fingerprint=on&op=vindex&search=<query>', 'http://the.earth.li:11371/pks/lookup?fingerprint=on&op=vindex&search=<query>'] |
modules.securitytrails.api_key | str | SecurityTrails API key | |
modules.shodan_dns.api_key | str | Shodan API key | |
modules.trufflehog.concurrency | int | Number of concurrent workers | 8 |
modules.trufflehog.only_verified | bool | Only report credentials that have been verified | True |
modules.trufflehog.version | str | trufflehog version | 3.75.1 |
modules.urlscan.urls | bool | Emit URLs in addition to DNS_NAMEs | False |
modules.virustotal.api_key | str | VirusTotal API Key | |
modules.wayback.garbage_threshold | int | Dedupe similar urls if they are in a group of this size or higher (lower values == less garbage data) | 10 |
modules.wayback.urls | bool | emit URLs in addition to DNS_NAMEs | False |
modules.zoomeye.api_key | str | ZoomEye API key | |
modules.zoomeye.include_related | bool | Include domains which may be related to the target | False |
modules.zoomeye.max_pages | int | How many pages of results to fetch | 20 |
output_modules.asset_inventory.output_file | str | Set a custom output file | |
output_modules.asset_inventory.recheck | bool | When use_previous=True, don't retain past details like open ports or findings. Instead, allow them to be rediscovered by the new scan | False |
output_modules.asset_inventory.summary_netmask | int | Subnet mask to use when summarizing IP addresses at end of scan | 16 |
output_modules.asset_inventory.use_previous | bool | Emit previous asset inventory as new events (use in conjunction with -n <old_scan_name>) |
False |
output_modules.csv.output_file | str | Output to CSV file | |
output_modules.discord.event_types | list | Types of events to send | ['VULNERABILITY', 'FINDING'] |
output_modules.discord.min_severity | str | Only allow VULNERABILITY events of this severity or higher | LOW |
output_modules.discord.webhook_url | str | Discord webhook URL | |
output_modules.emails.output_file | str | Output to file | |
output_modules.http.bearer | str | Authorization Bearer token | |
output_modules.http.method | str | HTTP method | POST |
output_modules.http.password | str | Password (basic auth) | |
output_modules.http.siem_friendly | bool | Format JSON in a SIEM-friendly way for ingestion into Elastic, Splunk, etc. | False |
output_modules.http.timeout | int | HTTP timeout | 10 |
output_modules.http.url | str | Web URL | |
output_modules.http.username | str | Username (basic auth) | |
output_modules.human.console | bool | Output to console | True |
output_modules.human.output_file | str | Output to file | |
output_modules.json.console | bool | Output to console | False |
output_modules.json.output_file | str | Output to file | |
output_modules.json.siem_friendly | bool | Output JSON in a SIEM-friendly format for ingestion into Elastic, Splunk, etc. | False |
output_modules.neo4j.password | str | Neo4j password | bbotislife |
output_modules.neo4j.uri | str | Neo4j server + port | bolt://localhost:7687 |
output_modules.neo4j.username | str | Neo4j username | neo4j |
output_modules.slack.event_types | list | Types of events to send | ['VULNERABILITY', 'FINDING'] |
output_modules.slack.min_severity | str | Only allow VULNERABILITY events of this severity or higher | LOW |
output_modules.slack.webhook_url | str | Discord webhook URL | |
output_modules.splunk.hectoken | str | HEC Token | |
output_modules.splunk.index | str | Index to send data to | |
output_modules.splunk.source | str | Source path to be added to the metadata | |
output_modules.splunk.timeout | int | HTTP timeout | 10 |
output_modules.splunk.url | str | Web URL | |
output_modules.subdomains.include_unresolved | bool | Include unresolved subdomains in output | False |
output_modules.subdomains.output_file | str | Output to file | |
output_modules.teams.event_types | list | Types of events to send | ['VULNERABILITY', 'FINDING'] |
output_modules.teams.min_severity | str | Only allow VULNERABILITY events of this severity or higher | LOW |
output_modules.teams.webhook_url | str | Discord webhook URL | |
output_modules.web_report.css_theme_file | str | CSS theme URL for HTML output | https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.1.0/github-markdown.min.css |
output_modules.web_report.output_file | str | Output to file | |
output_modules.websocket.preserve_graph | bool | Preserve full chains of events in the graph (prevents orphans) | True |
output_modules.websocket.token | str | Authorization Bearer token | |
output_modules.websocket.url | str | Web URL | |
internal_modules.speculate.max_hosts | int | Max number of IP_RANGE hosts to convert into IP_ADDRESS events | 65536 |
internal_modules.speculate.ports | str | The set of ports to speculate on | 80,443 |