VirtualHost Enumeration
VirtualHosts Examples
In the diagram above, this is the valid way to use virtual hosts. You create the virtual host configuration on the web server and then create the DNS record for the virtual host and point it at the web server IP address.
However, the point of virtual host enumeration is to discover virtual host configurations on the web server where a DNS record has not been created. For this, you'd use your local /etc/hosts
once you find the virtual host using the methodology below.
NGINX
/etc/nginx/sites-available/example.com.conf
server {
listen 80;
server_name www.example.com;
root /var/www/example.com;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
server {
listen 80;
server_name dev.example.com;
root /var/www/my-test-server;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
Server Block 1
-
- Listens on
TCP/80
- Answer any HTTP request with
HOST: www.example.com
- Serve the contents out of
/var/www/example.com
- Home page (index) is
/var/www/example.com/index.html
- When hitting the server name, try files in:
/var/www/example.com/
+user/requested/resource
- Listens on
Server Block 2
-
- Listens on
TCP/80
- Answer any HTTP request with
HOST: dev.example.com
- Serve the contents out of
/var/www/my-test-server
- Home page (index) is
/var/www/my-test-server/index.html
- When hitting the server name, try files in:
/var/www/my-test-server/
+user/requested/resource
- Listens on
Apache
/etc/apache2/sites-available/example.com.conf
<VirtualHost *:80>
ServerName www.example.com
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
<VirtualHost *:80>
ServerName dev.example.com
ServerAdmin webmaster@localhost
DocumentRoot /var/www/my-test-server
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Server Block 1
-
- Listens on
TCP/80
- Answer any HTTP request with
HOST: www.example.com
- Serve the contents out of
/var/www/example.com
- Home page (index) is
/var/www/example.com/index.html
- When hitting the server name, try files in:
/var/www/example.com/
+user/requested/resource
- Listens on
Server Block 2
-
- Listens on
TCP/80
- Answer any HTTP request with
HOST: dev.example.com
- Serve the contents out of
/var/www/my-test-server
- Home page (index) is
/var/www/my-test-server/index.html
- When hitting the server name, try files in:
/var/www/my-test-server/
+user/requested/resource
- Listens on
Enumeration
Given the domain: example.com
, we know www.example.com
exists, and probably is the production web server for the domain example.com
We don't know that dev.example.com
exists. How would we discover this?
GoBuster
gobuster
(and other tools like wfuzz
) have a Virtual Host enumeration mode.
# Set some variables
target='https://10.6.6.100'
base_domain="example.com"
wordlist="/usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt"
# Run gobuster in VirtualHost enumeration mode
gobuster vhost -k --domain $base_domain --append-domain -u $target -w $wordlist
In vhost
mode, gobuster
is going to do the following:
GET / HTTP/1.1
Host: [wordlist-item].example.com
User-Agent: gobuster/x.x
Content-Length: xx
Accept: */*
X-Custom-Header-Example: blah
The server is going to look at the value of the Host:
header and determine if it has a virtual host configuration for that hostname. And if it does, respond accordingly.
[wordlist-item1].example.com
...... if server respondsHTTP 200
, VirtualHost exists[wordlist-item2].example.com
...... if server respondsHTTP 200
, VirtualHost exists[wordlist-item3].example.com
...... if server respondsHTTP 200
, VirtualHost exists[wordlist-item4].example.com
...... if server respondsHTTP 200
, VirtualHost exists[wordlist-item5].example.com
...... if server respondsHTTP 200
, VirtualHost exists- etc, etc.
You may also need to filter based on --exclude-length
as server responses such as HTTP 200
may not be a good indicator and may lead to false positives.