vhost_brute
vhost_brute is a native Go hxEASM discovery plugin for finding HTTP virtual
hosts exposed by existing WebApp endpoints.
It is a normal hxEASM plugin wrapper:
- no external scanner binary;
- no shell execution;
- no database access;
- no Asset service access;
- no graph service access;
- no worker-specific orchestration.
The worker passes the existing PluginInput.Scope to the plugin and processes
the returned PluginResult through the normal Asset pipeline.
Input
The plugin accepts webapp targets only.
Examples:
http://example.com
https://portal.example.com
https://89.208.192.24
https://89.208.192.24:8443
It ignores domain, subdomain, ip, cidr, ip_range, service, and other
scope types as direct targets.
Base domain selection
For DNS-hosted WebApps, the plugin derives the registrable domain/eTLD+1 from the WebApp hostname using public-suffix semantics:
https://portal.example.com -> example.com
https://portal.example.co.uk -> example.co.uk
For IP-hosted WebApps, the plugin uses all current domain entries present in
the existing runtime PluginInput.Scope. This is the current scan/runtime scope,
not a separate initial-scope field. It intentionally ignores subdomain, ip,
cidr, ip_range, webapp, and service entries when selecting base domains
for an IP-hosted WebApp.
Wordlist
The default wordlist is bundled into the worker image:
/app/wordlists/vhost/subdomains-top1million-20000.txt
Source:
- Project: SecLists
- Repository: https://github.com/danielmiessler/SecLists
- Upstream file:
Discovery/DNS/subdomains-top1million-20000.txt - Pinned revision:
2e3e92569043d24297ca6c35070078e5cf41651e - License: MIT
Operators may override the path with the wordlist_path plugin setting.
HTTP and HTTPS behavior
The physical network destination is always the original WebApp endpoint. The candidate hostname is used for virtual-host selection.
For HTTP:
TCP destination: original WebApp host:port
HTTP Host: candidate hostname
For HTTPS:
TCP destination: original WebApp host:port
HTTP Host: candidate hostname
TLS SNI: candidate hostname
Candidate DNS resolution is not required and is not used to choose the physical destination. A confirmed virtual host can therefore be emitted as a Subdomain Asset even if the candidate name does not resolve in public DNS.
TLS certificate verification is skipped by default for this plugin because VHost
probing commonly targets IP endpoints or shared endpoints whose certificates do
not match the physical host. The setting is tls_skip_verify=true by default and
can be changed through generic plugin settings.
Detection
The plugin does not treat HTTP 200 alone as a discovery.
For each base domain, it first sends random baseline requests such as:
hxvhost-<random>.example.com
All baseline responses must have the same bounded fingerprint. If the baseline is unstable, that base domain is skipped conservatively.
Candidate responses are compared against the stable baseline using:
- HTTP status code;
- bounded body length;
- bounded body SHA-256 hash;
- HTML title;
- redirect
Location; - body truncation flag.
The plugin reads at most 64 KiB of response body for fingerprinting. It does not store response bodies in metadata.
Redirect handling is conservative: if both the baseline and candidate are redirects with the same status and no stronger title signal, V1 does not confirm the candidate based on redirect differences alone.
Output
Confirmed VHosts are emitted as subdomain Assets only.
The plugin does not create WebApp, Domain, IP, Service, vulnerability, file, or path Assets.
Metadata includes bounded evidence such as:
parent_domain;discovered_from_webapp;target_scheme;target_host;target_port;http_status;title;location;response_hash;response_length;source = vhost_brute.
Graph relations are not created by the plugin. Existing generic graph processing
may create the normal parent Domain relation for the returned Subdomain based on
parent_domain.
Settings
| Setting | Default | Description |
|---|---|---|
wordlist_path |
/app/wordlists/vhost/subdomains-top1million-20000.txt |
Local worker path to the prefix wordlist |
concurrency |
10 |
Maximum concurrent probes inside the plugin |
rate_limit |
25 |
Maximum probe requests per second; 0 disables plugin-local rate limiting |
request_timeout |
5 |
Per-request timeout in seconds |
baseline_requests |
3 |
Random baseline probes per base domain |
tls_skip_verify |
true |
Skip TLS certificate verification while preserving candidate SNI |
vhost_brute is registered for explicit/custom profile usage, but it is not
added to built-in scan profiles by default.