A Practical Application of dnstwist

A Practical Application of dnstwist

The Problem

Phishing remains one of the top methods for a malicious actor to gain access to a target environment. A vital component of a realistic phishing campaign is a familiar-looking domain address. Using a technique known as "domain squatting," an attacker may register cousin domains of the target or of vendors known to do business with the target.

What's a cousin domain? A cousin domain is simply a domain that appears visually similar to another domain. For example, a cousin domain of evanottinger.com might be evan0ttinger.com.

Note the numerical zero in the place of the letter 'o' in the second domain.

The Opportunity

Knowing that this is a likely attack vector, how can we use this knowledge to our advantage? What if we monitor DNS records for the cousin domains of domains that we own!?

We can first take a baseline of all of the registered cousin domains of the domains that we own. Then, we can check at regular intervals for any newly registered cousin domains. If we find that someone has registered a cousin domain for one of the domains that we're monitoring, this could be an early indication that a threat actor is preparing to launch a phishing campaign against us, our clients, or vendors with whom we do business.

The Solution

Enter dnstwist. I recently completed SEC530: Defensible Security Architecture and Engineering: Implementing Zero Trust for the Hybrid Enterprise--and earned the accompanying certification, GDSA--at the SANS Institute as part of their master's program. During the course, the instructors introduced dnstwist as a tool for monitoring lookalike domains for a given domain name.

dnstwist is a command-line tool written by elceef. Directions for installing and operating dnstwist can be found at the GitHub repository, linked at the beginning of this section. Once installed, a list of cousin registered cousin domains can be found by running the command $ dnstwist --registered domain.name. You can run this command at regular intervals and compare the outputs to determine if any new cousin domains are registered. This is great, but it is also manual. I don't know about you, but around here, we hate manual.


How can we automate this? One solution would be to leverage bash scripting, a simple SQLite database, and an inexpensive hashing algorithm--say, MD5.

The following steps are being performed on an Ubuntu distribution of Linux. If you're using any variant of Debian, the steps are likely the same--but otherwise you may have to research the commands for the distribution of your choice.

To implement this, I've written a script called ProjectLandlord that can be found on my GitHub.

First, let's make sure we have the dependencies installed:

$ sudo apt install sqlite3
$ sudo apt install mailutils

# I am assuming you have Python3 and Pip installed
$ pip install dnstwist[full]

Next, we can clone the repository:

$ git clone https://github.com/evanottinger/ProjectLandlord.git
$ cd ./ProjectLandlord

And run the script:

$ ./script.sh example.com
[+] Creating table for example.com...
[!] Rent's due! The Landlord is going to work.
[>] Running dnstwist and parsing output...this will take some time.

Note that the longer the domain name, the longer the script will take to run (and consequently, the larger the database file will be).

Once this is done, you will have a nice database of all of your domain's cousin domains, as well as fingerprints of their current DNS records, shown below.

Note: In the above screenshot, many of the records are 0a1f21a3417389e0c0a13392c79a7a89. This is the md5sum output of -, which is the designator for no records. On my domain, evanottinger.com, I have various records set, which is why my fingerprint is different.

This script can then be added to a system's crontab to be run on a schedule. This way, the moment someone registers a cousin of your domain, you'll have an early warning that a phishing campaign might be imminent. You can then act on this information however you or your organization sees fit.

Next Steps

It's a good start, but I'll admit this script isn't very robust. I would consider this (at the time of this writing) to be a v0.1.0. Some improvements I'd like to implement are:

  • Extract SQL queries from the commands. This will prevent duplication of any queries that might be run multiple times and make the code more readable.

  • Implement SMS or Email alerting.

  • Extract the processes into functions. Again, to improve the readability and maintainability of the code.

  • Pass command-line options into dnstwist.

  • Accept a list of multiple domain names.

  • Extract the database name into a configuration variable.

  • A more robust database, like PostgreSQL, would be nice.

I'm sure I'll think of more improvements as I work on the project. In the meantime, thank you for reading, and happy defending.