DNS Hijack Monitoring

Tural Aliyev
5 min readJul 29, 2020

It doesn’t really matter how much time your developers have spent writing secure code and how many layers of security you have implemented to protect your website from being hacked and defaced. Recent incidents have demonstrated that the bad guys will simply look for and find an easier way to hurt your business.

Instead of going after vulnerabilities in the website itself, they’ll focus on a potentially weaker link in the system: the DNS registrar. All they have to do is “convince” the right person (via e-mail, fax, etc) or by guessing username/password in the management console for DNS, by hacking into a DNS hosting company, that an update to your public DNS records is legit. A few moments later, the internet won’t be looking at your website anymore.

You could use tools to monitor the content of your websites & report back when significant changes are made, but as the content of websites often changes, you’ll find yourself updating your tools quite often. Perhaps an easier approach would be to also monitor the DNS records and report when an IP address has changed.

Getting started

I decided to hack a little python script together that allows you to do that. You can get a copy of the script at https://github.com/corelan/dnshjmon or simply clone the repository:

root@krypto1:/dns# git clone https://github.com/corelan/dnshjmon.git
Cloning into 'dnshjmon'...
remote: Counting objects: 54, done.
remote: Compressing objects: 100% (37/37), done.
remote: Total 54 (delta 28), reused 43 (delta 17)
Unpacking objects: 100% (54/54), done.
root@krypto1:/dns#

Setting up the configuration

The script uses 2 configuration files:

  • a file that contains the hostnames you want to monitor, and the valid IP (one, multiple, or even CIDR notations)
  • a file that contains the configuration about how to send email reports

DNS Config file

This is a flat ascii file (dnshjmon_dns.conf) that contains the list with hostnames that need to be checked and the list with valid IPs for that hostname.

hostname=ip

You can specify multiple IP addresses and/or even use CIDR notation. Simply separate entries with a comma:

hostname=127.0.0.1,192.168.0.1/25

If you want to exclude a certain IP, prefix it with a dash

hostname=127.0.0.1,192.168.0.1/25,-192.168.0.5

You can, obviously, specify as many hostnames as you want.

You can specify an alternative path for the dns configuration file using the -d argument.

SMTP Config file

This file (dnshjmon_smtp.conf) will be created the first time you run dnshjmon.py, using an interactive wizard.

(master) root@krypto1:/dns/dnshjmon# python dnshjmon.py      __                __     __                         
.--| |.-----..-----.| |--.|__|.--------..-----..-----.
| _ || ||__ --|| || || || _ || |
|_____||__|__||_____||__|__|| ||__|__|__||_____||__|__|
|___|
[ corelanc0d3r - www.corelan.be ]

[+] Using dns config file /dns/dnshjmon/dnshjmon_dns.conf
[-] Oops, email config file /dns/dnshjmon/dnshjmon_smtp.conf doesn't exist yet
[+] Creating a new config file.
> Enter smtp mail server IP or hostname: 127.0.0.1
> Enter mail server port (default: 25):
> Enter 'From' email address: peter.ve@corelan.be
> Enter 'To' email address: peter.ve@corelan.be
> Enter mail server timeout (in seconds, default: 300):
> Does server require authentication? (yes/no, default: no):
> Does server require/support STARTTLS ? (yes/no, default: no):
[+] Saved new config file

You can specify an alternate path to the configuration file using the -s parameter.

If you want to add additional mailserver configurations or change the existing one, simply edit the conf file.

You can test if the mail configuration works correctly by using the -mail argument. By default, emails will be sent with high-priority and requesting a return-receipt.

Can I use custom nameservers (other than the ones configured on the OS level) ?

Sure you can, but you’ll need to install the python-dnspython library from www.dnspython.org. On Ubuntu / Kali, this is as easy as running apt-get install python-dnspython. On Windows, you need to extract the archive and run setup.py or, alternatively, just copy the ‘dns’ subfolder to c:\python27\lib\site-packages.

When dnshjmon detects that the library is installed, it will expose a -n argument, which allows you to specify the full path to a flat file that contains the IP address or addresses (one IP per line) of the DNS server(s) you want to use for queries.

Using the script

After setting up the configuration files, all you have to do is schedule the script to run (every half an hour, for example). When a mismatch is found, an email will be sent.

It may not be a bad idea to configure your monitoring box to use Google or OpenDNS for DNS resolution. Furthermore, if you run this script on a windows box, maybe create a little batch file that will also call ipconfig /flushdns prior to running the python script. It might be a good idea to run a git pull from time to time, as I may be adding new features some time in the future.

If all goes well, the output (on screen) will look like this:

(master) root@krypto1:/dns/dnshjmon# python dnshjmon.py     _                __     __
.--| |.-----..-----.| |--.|__|.--------..-----..-----.
| _ || ||__ --|| || || || _ || |
|_____||__|__||_____||__|__|| ||__|__|__||_____||__|__|
|___|
[ corelanc0d3r - www.corelan.be ]

[+] Using dns config file /dns/dnshjmon/dnshjmon_dns.conf
[+] Using mail config file /dns/dnshjmon/dnshjmon_smtp.conf
[+] Running DNS check
[+] Using OS DNS configuration for queries
Results:
--------
1. www.corelan.be - check OK? : true (['178.79.152.9'])
[+] Done checking, tested 1 sites, reported 0 IP mismatches

if an issue is found, you’ll see this:

(master) root@krypto1:/dns/dnshjmon# python dnshjmon.py     _                __     __
.--| |.-----..-----.| |--.|__|.--------..-----..-----.
| _ || ||__ --|| || || || _ || |
|_____||__|__||_____||__|__|| ||__|__|__||_____||__|__|
|___|
[ corelanc0d3r - www.corelan.be ]

[+] Using dns config file /dns/dnshjmon/dnshjmon_dns.conf
[+] Using mail config file /dns/dnshjmon/dnshjmon_smtp.conf
[+] Running DNS check
[+] Using OS DNS configuration for queries
Results:
--------
1. www.corelan.be - check OK? : false (['178.79.152.9'] : Record manipulated?)
[+] Done checking, tested 1 sites, reported 1 IP mismatches**************************************************
1 DNS record(s) may have been manipulated:
20131231-09:43:26: www.corelan.be resolves to 178.79.152.9, but it should be ['178.79.152.8']
**************************************************
[+] Config file appears to contain 1 mail server definitions
[+] Checking if 172.0.0.1:25 is reachable
Yup, port is open
[+] Connecting to 127.0.0.1 on port 25
[+] Connected
[+] Sending email
[+] Mail sent, disconnecting

Suppose you want to use the google DNS server 8.8.8.8 instead of the OS DNS server configuration and you have installed python-dnspython, then simply create a file (nameservers.conf or something like that) and put 8.8.8.8 in that file. Tell dnshjmon to use that file and the output will look like this:

(master) root@krypto1:/dns/dnshjmon# python dnshjmon.py -n nameservers.conf     _                __     __
.--| |.-----..-----.| |--.|__|.--------..-----..-----.
| _ || ||__ --|| || || || _ || |
|_____||__|__||_____||__|__|| ||__|__|__||_____||__|__|
|___|
[ corelanc0d3r - www.corelan.be ]

[+] Using dns config file /dns/dnshjmon/dnshjmon_dns.conf
[+] Using mail config file /dns/dnshjmon/dnshjmon_smtp.conf
[+] Running DNS check
[+] Using 1 DNS server(s) for queries:
['8.8.8.8']
Results:
--------
1. www.corelan.be - check OK? : true (['178.79.152.9'])
[+] Done checking, tested 1 sites, reported 0 IP mismatches

The script was written and tested against python 2.7 and should run out of the box on Windows, Linux and Mac OS.

--

--