Passive DNS
Passive DNS describes an historical database of DNS resolutions. I’ve written a previous post on Using Passive DNS for Incident Response, more specifically combining it with Moloch.
If you run your own corporate -internal- nameservers it makes sense to monitor what domains have been queried and what results were returned in the past. You can use the collection of internal queries for future incident response. You can use this collected information to cross-check with information that you gathered from intelligence feeds or for example via your internal MISP instance.
Using Bro for passive DNS
There are different ways for gathering passive DNS data. The method I describe is via Bro. Bro is network analysis framework that can be extended with different plugins.
The bulk of information in this article comes from a post Building Your Own Passive DNS Collection System, I added some additional configuration notes.
Prepare the system
I installed Bro on an Ubuntu 12 (note that the this is not the latest Ubuntu) version. Bro requires some additional packages that can be easily installed.
sudo apt-get update sudo apt-get upgrade sudo apt-get install cmake make gcc g++ flex bison sudo apt-get install libpcap-dev libgeoip-dev libssl-dev python-dev zlib1g-dev libmagic-dev swig2.0
Next thing we have to do is download Bro, import the GPG key of Bro and verify the package. The GPG verification step is optional but assures you that you have a legitimate version of Bro, you verify the package signature that was signed with the Bro GPG key.
wget https://www.bro.org/downloads/bro-2.4.1.tar.gz wget -O bro.key "http://pgp.mit.edu:11371/pks/lookup?op=get&search=0x33F15EAEF8CB8019" gpg --import bro.key wget https://www.bro.org/downloads/bro-2.4.1.tar.gz.asc gpg --verify bro-2.4.1.tar.gz.asc bro-2.4.1.tar.gz
The last command should return output containing
gpg: Signature made Sun Sep 6 21:44:21 2015 CEST using RSA key ID 6F9AD2A2 gpg: Good signature from "The Bro Team <info@bro.org>"
Now extract the Bro package, run the configure file and build the package. Note the prefix argument, this defines where Bro will be installed on your system.
tar zxvf bro-2.4.tar.gz ./configure --prefix=/nsm/bro make sudo make install
Bro needs to watch a network interface in order to get the necessary data. Defining what interface to monitor is done in a configuration file node.cfg.
vi /nsm/bro/etc/node.cfg interface=eth2
Database
In order to store the passive DNS data we will also need a database. We’ll use mysql. I assume you already have mysql installed. If not you can do this via
sudo apt-get install mysql-server python-mysqldb
If you already have mysql installed you need to add an extra database, preferably with a dedicated user. Log in to mysql and create the database and user.
create user 'pdns'@'localhost' identified by 'pdns'; create database pdns; grant all privileges on pdns.* to 'pdns'@'localhost'; flush privileges;
Get the pdns package
The next step is getting the pdns module for Bro and installing it. First we need to prepare the system. I assume you already have pip installed (if not, install it as ‘python-pip’). Next install the bottle package.
pip install bottle
Continue with installing SQLAlchemy
sudo apt-get install python-sqlalchemy
The pdns package is available from Github. Once downloaded it has to be moved inside the Bro folder.
git clone https://github.com/JustinAzoff/bro-pdns.git mv bro-pdns /nsm/bro/share/bro/site/
We now have to make Bro aware of the new module and the configuration settings. Open the configuration file local.bro and add the database connection.
vi /nsm/bro/share/bro/site/local.bro @load ./bro-pdns redef PDNS::uri = "mysql://pdns@localhost/pdns";
Starting Bro
Now that all the configuration is done it is time to start Bro.
/nsm/bro/bin/broctl [BroControl] > install [BroControl] > start [BroControl] > status Getting process status ... Getting peer status ... Name Type Host Status Pid Peers Started bro standalone localhost running 18624 0 05 Sep 23:10:46
The above indicates that Bro was successfully installed and started. You can exit the Bro console with quit.
DNS logging in Bro
The first thing you now have to do is check the Bro logs for the DNS queries that were captured on the monitored interface. You can do this easily with a tail of the log.
tail -f /nsm/bro/logs/current/dns.log
The next step is to use the Bro module for pdns to parse the DNS logs.
BRO_PDNS_DB=mysql://pdns:pdns@localhost/pdns /nsm/bro/share/bro/site/bro-pdns/bro_pdns.py process /nsm/bro/logs/current/dns.log 241
The number returned (241) is the number of records processed.
If you now use mysql to look what’s inside the database you will have an overview of the data that was gathered.
mysql> select * from dns; +---------------------------------+------+------------------------------+-------+--------+---------------------+---------------------+ | query | type | answer | count | ttl | first | last | +---------------------------------+------+------------------------------+-------+--------+---------------------+---------------------+ | be.archive.ubuntu.com | - | 91.189.88.161 | 3 | 26 | 2016-09-05 23:20:27 | 2016-09-05 23:20:27 | | be.archive.ubuntu.com | - | 91.189.88.162 | 3 | 26 | 2016-09-05 23:20:27 | 2016-09-05 23:20:27 | | block.dropbox.com | - | 108.160.173.65 | 1 | 30 | 2016-09-05 23:17:45 | 2016-09-05 23:17:45 |
The mysql interface is not a very convenient way to look at the data. There’s a web interface that you can use that returns JSON. Start the interface with
BRO_PDNS_DB=mysql://pdns:pdns@localhost/pdns /nsm/bro/share/bro/site/bro-pdns/bro_pdns.py serve
and then query for a record via curl
curl http://localhost:8081/dns/www.cudeso.be {"records": [{"count": 2, "last": "2016-09-05 23:11:04", "ttl": 3600, "answer": "92.243.8.142", "query": "www.cudeso.be", "type": "-", "first": "2016-09-05 23:11:04"}]}
Conclusion
The above process describes how to gather passive DNS data from the DNS queries in your environment but it still has some rough edges.
The processing of the logs is not something that you’d like to do manually. So ideally you run the process from cron. You can put it in a cron job. One note on delay. If you do a query on a machine with less resources it might take some time (1 / 2 seconds) before it shows up in the DNS log of Bro. This is something to take into account if you are doing live debugging. You should allow Bro the necessary time to process the request and output the log file.
The JSON output is ideal for further processing, it’s an easy to parse format. If you are using MISP you should be aware of its MISP module feature (see https://github.com/MISP/misp-modules) where you can enrich information of attributes in MISP with external information. One of the next steps that you could take is write a module that queries your local passive DNS database to check if a domainname attribute from MISP is seen in your queries.