Skip to content

Scanning for Subdomains.

Organisations will often have several elements to their web presence. They can segregate these using subdomains, allowing a logical separation of content.

A subdomain is any site that is a sub part of a top level domain. For example:

  • github.coventry.ac.uk is the GitHub subdomain, of the coventry.ac.uk
  • mail.coventry.ac.uk is the old mail subdomain for coventry.ac.uk
  • coventry.aula.education is the Coventry subdomain of aula.education

This could be for things like having a public server, and a testing server with different versions of the page. Identifying and mapping subdomains is important to give us insight into the full functionality of a site.

Important Note for the Labs

When we are working in the labs (or in a CTF) we can have issues with subdomains. Usually a DNS service would map the name of a site we give to an IP address, which is then used for the connection.

However, if we are accessing a box using an IP (or something on shared hosting like Zaphod), our request is going to go to the default domain on the system.

We can work around this on a Linux system by using "poor mans DNS".
Linux systems have an /etc/hosts file, mapping IP addresses to domain names. Adding an entry to this will let us access the server by name, thus bypassing the DNS issue.

Example

For example, lets get our linux box to map 127.0.0.1 to hacking.evil

First add a new entry to the hosts file, using a text editor (you will need to be root)

sudo nano /etc/hosts

Add the relevant entry

# Host addresses
127.0.0.1  localhost
127.0.1.1  dan-parrot
::1        localhost ip6-localhost ip6-loopback
ff02::1    ip6-allnodes
ff02::2    ip6-allrouters
127.0.0.1  hacking.evil

We can now use hacking.evil to refer to the 127.0.0.1 address.

For example: When we use ping, see how the address is mapped across.

$ping hacking.evil
PING hacking.evil (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.052 ms
64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.051 ms
64 bytes from localhost (127.0.0.1): icmp_seq=3 ttl=64 time=0.055 ms
^C
--- hacking.evil ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2023ms
rtt min/avg/max/mdev = 0.051/0.052/0.055/0.001 ms

Subdomain Fuzzing

When scanning for public facing subdomains, we can look for *.domain.com where * is the subdomain we are looking for. In this case the scanner will make a DNS request for the subdomain, if there is a record the subdomain exists, and the result positive.

Note

We are going to want to use a different wordlist here. Seclists DNS lists has a collection of common domain names we can use.

Example

We can search for subdomains of example.org using the top 5000 subdomains list with the following commands:

Wit Gobuster, we ask to scan in dns mode, and supplly example.org using the -d flag

gobuster dns -w subdomains-top1million-5000.txt -d example.org
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Domain:     example.org
[+] Threads:    10
[+] Timeout:    1s
[+] Wordlist:   subdomains-top1million-5000.txt
===============================================================
2021/08/26 16:50:16 Starting gobuster in DNS enumeration mode
===============================================================
Found: www.example.org
Progress: 255 / 4990 (5.11%)^C

One really nice feature of gobuster here, is the -i flag.
This will give us IP addresses for the subdomains we have found

With FFUF we simply add the FUZZ parameter to the URL where the subdomain would be.

$ffuf -w subdomains-top1million-5000.txt -u http://FUZZ.example.org
 /'___\  /'___\           /'___\       
/\ \__/ /\ \__/  __  __  /\ \__/       
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
 \ \_\   \ \_\  \ \____/  \ \_\       
  \/_/    \/_/   \/___/    \/_/       

v1.3.1 Kali Exclusive <3
________________________________________________

:: Method           : GET
:: URL              : http://FUZZ.example.org
:: Wordlist         : FUZZ: subdomains-top1million-5000.txt
:: Follow redirects : false
:: Calibration      : false
:: Timeout          : 10
:: Threads          : 40
:: Matcher          : Response status: 200,204,301,302,307,401,403,405
________________________________________________

www                     [Status: 200, Size: 1256, Words: 298, Lines: 47]
...

Virtual Host Fuzzing

Virtual Hosting (VHOST's) are where we have multiple web services running on the same server. This allows us to do things like have subdomains without requiring a whole server infrastructure for them.

As the virtual hosts have the same IP address, so we need some way of differentiating between the services we are looking for. Recall from the HTTP Lessons, a standard HTTP 1.1 request looks like this. The host we use as part of the request, tells the server which virtual host we are expecting an answer from.

dang@DESKTOP-KJDVQ2J:~$ ncat -v -C cueh.coventry.ac.uk 80
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Connected to 194.66.34.56:80.
GET / HTTP/1.1
host: cueh.coventry.ac.uk

Often the machines in a VHOST will be public facing, and therefore have a global DNS entry, meaning we can find them with the DNS based scan used above. However, in some situations, a server may have a mixture of public and "private" vhosts.
These may be machines that are part of an intranet, where the organisations own internal DNS servers take care of the routing, for example a development server used to test a site before it goes live. If we can find the subdomain used for this, we can bypass any DNS requirements to "find" the site, and make a request directly to the IP address.

Important

This is a pretty common problem in things like CTF's (and these kind of demos). As the machines tend to be stashed on private VPN's, its unusual for them to have a public DNS record. This means that our DNS based subdomain enumeration wont work, like it would in a "real" engagement, and we are forced to use VHOST enumeration.

VHOST Enumeration

First we modify the /etc/hosts file to map the base domain to the servers IP address. (This may not be necessary, as some scanners can use IP addresses for VHOST scanning)

cat /etc/hosts

192.168.1.1  target.org

I find Gobusters VHOST scanning to be much easier to use, as it has a dedicated mode for vhost scanning that usually eliminates the need to filter the results

$gobuster vhost -u http://target.org -w subdomains-top1million-5000.txt

FFUF doesn't (yet) have a dedicated VHOST scanning mode.

Instead we need to send a custom header with the host string as part of the fuzzing parameters.

$ffuf -u http://target.org/ -H “Host: FUZZ.target.org” -w subdomains-top1million-5000.txt

Depending on the server, we may get a lot of false positives. This is where the server returns an error page (or the default www page) when the vhost cannot be found.

Summary

In this article we have looked at discovering subdomains on a network. These may contain extra functionality that could be exploited, or give development versions of a site. So once identified we would continue our mapping process.

In the lab session we will practice scanning for VHOSTS.

Back to top