Skip to main content

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.com or Host: www.example.com header 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.com header 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.com header 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.com or Host: www.example.com header 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.com header 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.com header 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 respond HTTP 200, VirtualHost exists
    • [wordlist-item2].example.com ...... server may respond HTTP 200, VirtualHost exists
    • [wordlist-item3].example.com ...... server may respond HTTP 200, VirtualHost exists
    • [wordlist-item4].example.com ...... server may respond HTTP 200, VirtualHost exists
    • [wordlist-item5].example.com ...... server may respond HTTP 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

    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

      Retrieving Files

      When you navigate to http://www.example.com in your browser, the following happens

      1. Use DNS to resolve www.example.com to an IP address
      2. Open a TCP connection to the IP address of the web server on TCP/80
      3. 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.com is being served out of /var/www/example.com on 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.html page.

      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 responds HTTP 200, the file exists
        • GET /[wordlist-item1].html ..... Server responds HTTP 404, file is not found
        • GET /[wordlist-item1].php ...... Server responds HTTP 200, the file exists
        • GET /[wordlist-item2] .......... Server responds HTTP 301 /[wordlist-item2]/, this is a directory
        • GET /[wordlist-item2].html...... Server responds HTTP 200, the file exists
        • GET /[wordlist-item2].php ...... Server responds HTTP 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
        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
        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 gobuster to do the following:
          • GET /test.php?[wordlist-item1]=testing123
          • GET /test.php?[wordlist-item2]=testing123
          • GET /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 gobuster to do the following:
          • GET /test.php?page=[wordlist-item1]
          • GET /test.php?page=[wordlist-item2]
          • GET /test.php?page=[wordlist-item3]