Gobuster
Virtual Host Enumeration
You can find a more detailed analysis on the functionality of virtual hosts here, whereas below is a very succinct overview of the configuration.
Example Virtual Host Configs
Nginx Virtual Hosts Example
/etc/nginx/sites-available/example.com.conf
server {
listen 80;
server_name example.com www.example.com;
root /var/www/website;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
- Listen on
tcp/80 - Matches on
Host: example.comorHost: www.example.comheader from client - Serves files out of
/var/www/website
/etc/nginx/sites-available/blog.example.com.conf
server {
listen 80;
server_name blog.example.com;
root /var/www/blog;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
- Listen on
tcp/80 - Matches on
Host: blog.example.comheader from client - Serves files out of
/var/www/blog
/etc/nginx/sites-available/stage.example.com.conf
server {
listen 80;
server_name stage.example.com;
root /var/www/staging;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
- Listen on
tcp/80 - Matches on
Host: stage.example.comheader from client - Serves files out of
/var/www/staging
Apache Virtual Hosts Example
/etc/apache2/sites-available/example.com.conf
<VirtualHost *:80>
ServerName example.com www.example.com
ServerAdmin webmaster@localhost
DocumentRoot /var/www/website
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
- Listen on
tcp/80 - Matches on
Host: example.comorHost: www.example.comheader from client - Serves files out of
/var/www/website
/etc/apache2/sites-available/blog.example.com.conf
<VirtualHost *:80>
ServerName blog.example.com
ServerAdmin webmaster@localhost
DocumentRoot /var/www/blog
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
- Listen on
tcp/80 - Matches on
Host: blog.example.comheader from client - Serves files out of
/var/www/blog
/etc/apache2/sites-available/stage.example.com.conf
<VirtualHost *:80>
ServerName stage.example.com
ServerAdmin webmaster@localhost
DocumentRoot /var/www/staging
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
- Listen on
tcp/80 - Matches on
Host: stage.example.comheader from client - Serves files out of
/var/www/staging
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 also know blog.exapmle.com exists.
In the case of the diagram at the virtual host explainer, we don't know that stage.example.com exists. How would we discover this?
gobuster -- and other tools like wfuzz and ffuf -- have a means of enumerating hosts, either by specifying a mode in the application or by fuzzing the Host: header manually.
# Run gobuster in VirtualHost enumeration mode
gobuster vhost -k --domain 'example.com' --append-domain \
-u https://10.6.6.100 -w /usr/share/seclists/Discovery/DNS/namelist.txt \
-t 100 -o vhost.txt
In vhost mode, gobuster is going to go one-by-one through each word in the word list and craft a HTTP request that would look something like this:
GET / HTTP/1.1
Host: [wordlist-item].example.com
User-Agent: gobuster/x.x
Content-Length: xx
Accept: */*
X-Custom-Header-Example: blah
Note: Pay specific attention to the Host: header
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...... server may respondHTTP 200, VirtualHost exists[wordlist-item2].example.com...... server may respondHTTP 200, VirtualHost exists[wordlist-item3].example.com...... server may respondHTTP 200, VirtualHost exists[wordlist-item4].example.com...... server may respondHTTP 200, VirtualHost exists[wordlist-item5].example.com...... server may respondHTTP 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.
Directory and File Enumeration
Serving Files From a Web Server
Example Nginx Server Config
/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 Block
- 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
Example Apache Server Config
/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>
- Server Block
- 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
Retrieving Files
- Use DNS to resolve
www.example.comto an IP address - Open a TCP connection to the IP address of the web server on
TCP/80 - Send an HTTP request to the remote server
GET / HTTP/1.2
Host: www.example.com
X-Custom-Header: custom_value
Data sent to web server over TCP port 80
The web server receives the HTTP data and inspects the Host header.
If you look at the example server configurations above, you'll see the Host: header matches the ServerName or server_name directive. This is how the server knows which configurations to use.
- The web site for
www.example.comis being served out of/var/www/example.comon the server. - When you send
HTTP GET /to the server, the server understands you are requesting the site index sends you the/var/www/example.com/index.htmlpage.
Enumeration
We know the domain www.example.com exists and we know this is the web server for the Example Corp. If we go to http://www.example.com in our web browser, we are served the index file index.html.
- We don't know what other files and directories -- if any -- are being served by this web server?
- How would we discover this?
site='http://www.example.com'
wordlist='/usr/share/seclists/Discovery/Web-Content/big.txt'
gobuster dir -u "$site" -w "$wordlist" -x html,php
This command causes gobuster to do the following...
GET /[wordlist-item1].......... Server respondsHTTP 200, the file existsGET /[wordlist-item1].html..... Server respondsHTTP 404, file is not foundGET /[wordlist-item1].php...... Server respondsHTTP 200, the file existsGET /[wordlist-item2].......... Server respondsHTTP 301 /[wordlist-item2]/, this is a directoryGET /[wordlist-item2].html...... Server respondsHTTP 200, the file existsGET /[wordlist-item2].php...... Server respondsHTTP 404, file is not found
Parameter and Input Fuzzing
Serving Files From a Web Server
Example Nginx Web Server Config
/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 Block
- 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
Example Apache Web Server Config
/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>
- Server Block
- 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
Example PHP Code
/var/www/example.com/test.php
<?php
if (isset($_GET['page'])) {
$page = $_GET['page'];
if (empty($page)) {
$page = 'hello_word.txt';
}
$base_directory = './pages/';
$file_path = $base_directory . $page;
if (file_exists($file_path)) {
include($file_path);
} else {
echo "Error: Page not found!";
}
}
?>
If a user navigates to http://www.example.com/test.php and they do not pass a parameter, the script prints nothing to the page. If the user passes a ?page parameter and no input, it will default to ./pages/hellow_world.txt.
As a user, we do not have the luxury of seeing the source code like this. We may know that a test.php file exists if we enumerated it using brute-force (e.g. gobuster dir), but we have no way of knowing the script will accept a ?page parameter, since we cannot read the source code.
Fuzzing Parameters
payload='testing123'
wordlist='/usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt'
gobuster fuzz -u "http://www.example.com/test.php?FUZZ=${payload}" -w $wordlist
- This is causing
gobusterto do the following:GET /test.php?[wordlist-item1]=testing123GET /test.php?[wordlist-item2]=testing123GET /test.php?[wordlist-item3]=testing123
Fuzzing Inputs
Through your efforts in the section above, you discovered the ?page parameter. Now, you want to fuzz and see what kinds of inputs are parsed.
paramName='page'
wordlist='/usr/share/seclists/Fuzzing/LFI/LFI-LFISuite-pathtotest.txt'
gobuster fuzz -u "http://www.example.com/test.php?${paramName}=FUZZ" -w $wordlist
- This is causing
gobusterto do the following:GET /test.php?page=[wordlist-item1]GET /test.php?page=[wordlist-item2]GET /test.php?page=[wordlist-item3]