Tomas' Labroratory

Script for Verifying Authoritative Name Servers

As organizations tighten their web server security, attackers are looking for new weak links.  One of these weak links are DNS hosting companies and domain registrars.   Even though your own security may be top notch, are you sure that your domain registrar is equally bullet proof?   If the hacker can convince your registrar to change name servers to those under the hacker's control, the hacker can start doing all kinds of nasty stuff. Other than shopping around for DNS hosting companies and registrars that have strong security practices including (but not limited to) two-factor authentication, what else can be done? Monitoring; If you can quickly detect that someone has made an unauthorized change to your name servers or other DNS records, you can minimize the damage by acting quickly and taking control back away from them. Below is a script that will check your DNS records against a while list of allowed entries:

<?php
 
 //Change this:
 //Domain you wish to verify
 $domain = "www.somedomain.com";
 //Valid DNS hosts for your domain (detect change at registrar)
 $authWhitelist= array("ns1.somednshost.com","ns2.somednshost.com");
 //Valid A records (detect change at DNS host)
 $aRecordWhitelist= array("11.22.33.44","55.66.77.88");
 
 require_once 'Net/DNS2.php';
 
 function lookupAuthorities($domain,$server)
 {
  $serverIP = gethostbyname($server);
 
  $resolver = new Net_DNS2_Resolver( array('nameservers' => array($serverIP)) );
 
  $resp = $resolver->query($domain, 'A');
  //print_r($resp);
 
  $servers= array();
 
  foreach($resp->authority as &$record)
  {
  //keep for later
  $name = $record->name;
 
  array_push($servers,$record->nsdname);
  }
 
  $result = (object) [
  'name' => $name,
  'servers' => $servers,
  ];
 
  return $result;
 }
 
 function lookupAuthoritativeNameservers($domain)
 {
  $authorities =lookupAuthorities($domain,"a.root-servers.net");
 
  if($authorities->name != $domain)
  {
  $authorities = lookupAuthorities($domain,$authorities->servers[0]);
  }
  return $authorities->servers;
 
 }
 
 function lookupARecords($domain,$authNameserver)
 {
  $serverIP = gethostbyname($authNameserver);
 
  $resolver = new Net_DNS2_Resolver( array('nameservers' => array($serverIP)) );
 
  $resp = $resolver->query($domain, 'A');
  //print_r($resp);
 
  $servers= array();
 
 
  foreach($resp->answer as &$record)
  {
 
 
  array_push($servers,$record->address);
  }
 
 
  return $servers;
 
 }
 
 
 
 $authServers = lookupAuthoritativeNameservers($domain);
 
 $authDiff=array_diff($authServers,$authWhitelist);
 
 $aRecords = lookupARecords($domain,$authServers[0]);
 
 $aRecordDiff = array_diff($aRecords,$aRecordWhitelist);
 
 
 if(count($authDiff)>0 || count($aRecordDiff)>0)
 {
  echo ($domain . " Fail (See offending entries below)\n");
  if(count($authDiff)>0) print_r($authDiff);
  if(count($aRecordDiff)>0) print_r($aRecords);
 
 }
 else
 {
  echo($domain . " Pass\n");
 }
 
 
 ?>

Script will return "Pass" if everything is ok.  If any of the results is not specified on the white list script will show "Fail" including a list of all offending entries. You can either run this as a cron job and include an email notification by tweaking this script, or you can check it periodically by a tool such as PRTG.