268 lines
9.8 KiB
ReStructuredText
268 lines
9.8 KiB
ReStructuredText
=======
|
||
dns.log
|
||
=======
|
||
|
||
The Domain Name System (DNS) log, or :file:`dns.log`, is one of the most
|
||
important data sources generated by Zeek. Although recent developments in
|
||
domain name resolution have challenged traditional methods for collecting DNS
|
||
data, :file:`dns.log` remains a powerful tool for security and network
|
||
administrators.
|
||
|
||
Those interested in getting details on every element of the :file:`dns.log`
|
||
should refer to :zeek:see:`DNS::Info`.
|
||
|
||
Throughout the sections that follow, we will inspect Zeek logs in JSON format.
|
||
|
||
Inspecting the :file:`dns.log`
|
||
==============================
|
||
|
||
To inspect the :file:`dns.log`, we will use the same techniques we learned
|
||
earlier in the manual. First, we have a JSON-formatted log file, either
|
||
collected by Zeek watching a live interface, or by Zeek processing stored
|
||
traffic. We use the :program:`jq` utility to review the contents.
|
||
|
||
.. code-block:: console
|
||
|
||
zeek@zeek:~/zeek-test/json$ jq . -c dns.log
|
||
|
||
::
|
||
|
||
{"ts":1591367999.306059,"uid":"CMdzit1AMNsmfAIiQc","id.orig_h":"192.168.4.76","id.orig_p":36844,"id.resp_h":"192.168.4.1","id.resp_p":53,"proto":"udp","trans_id":8555,"query":"testmyids.com","qclass":1,"qclass_name":"C_INTERNET","qtype":28,"qtype_name":"AAAA","rcode":0,"rcode_name":"NOERROR","AA":false,"TC":false,"RD":true,"RA":false,"Z":0,"rejected":false}
|
||
|
||
{"ts":1591367999.305988,"uid":"CMdzit1AMNsmfAIiQc","id.orig_h":"192.168.4.76","id.orig_p":36844,"id.resp_h":"192.168.4.1","id.resp_p":53,"proto":"udp","trans_id":19671,"rtt":0.06685185432434082,"query":"testmyids.com","qclass":1,"qclass_name":"C_INTERNET","qtype":1,"qtype_name":"A","rcode":0,"rcode_name":"NOERROR","AA":false,"TC":false,"RD":true,"RA":true,"Z":0,"answers":["31.3.245.133"],"TTLs":[3600],"rejected":false}
|
||
|
||
As before, we could see each field printed on its own line:
|
||
|
||
.. code-block:: console
|
||
|
||
zeek@zeek:~/zeek-test/json$ jq . dns.log
|
||
|
||
::
|
||
|
||
{
|
||
"ts": 1591367999.306059,
|
||
"uid": "CMdzit1AMNsmfAIiQc",
|
||
"id.orig_h": "192.168.4.76",
|
||
"id.orig_p": 36844,
|
||
"id.resp_h": "192.168.4.1",
|
||
"id.resp_p": 53,
|
||
"proto": "udp",
|
||
"trans_id": 8555,
|
||
"query": "testmyids.com",
|
||
"qclass": 1,
|
||
"qclass_name": "C_INTERNET",
|
||
"qtype": 28,
|
||
"qtype_name": "AAAA",
|
||
"rcode": 0,
|
||
"rcode_name": "NOERROR",
|
||
"AA": false,
|
||
"TC": false,
|
||
"RD": true,
|
||
"RA": false,
|
||
"Z": 0,
|
||
"rejected": false
|
||
}
|
||
{
|
||
"ts": 1591367999.305988,
|
||
"uid": "CMdzit1AMNsmfAIiQc",
|
||
"id.orig_h": "192.168.4.76",
|
||
"id.orig_p": 36844,
|
||
"id.resp_h": "192.168.4.1",
|
||
"id.resp_p": 53,
|
||
"proto": "udp",
|
||
"trans_id": 19671,
|
||
"rtt": 0.06685185432434082,
|
||
"query": "testmyids.com",
|
||
"qclass": 1,
|
||
"qclass_name": "C_INTERNET",
|
||
"qtype": 1,
|
||
"qtype_name": "A",
|
||
"rcode": 0,
|
||
"rcode_name": "NOERROR",
|
||
"AA": false,
|
||
"TC": false,
|
||
"RD": true,
|
||
"RA": true,
|
||
"Z": 0,
|
||
"answers": [
|
||
"31.3.245.133"
|
||
],
|
||
"TTLs": [
|
||
3600
|
||
],
|
||
"rejected": false
|
||
}
|
||
|
||
As emphasized in the :file:`conn.log` material, what an analyst derives from
|
||
any log is a function of the questions that he or she is trying to ask of it.
|
||
The :file:`dns.log` captures application-level name resolution activity,
|
||
assuming that traffic is not encrypted, as is the case with DNS over HTTPS
|
||
(DoH) or DNS over TLS (DoT). Applications mainly use DNS to resolve names to IP
|
||
addresses, IP addresses to names, and certain other functions. Intruders use
|
||
DNS for the same purposes, but may also subvert the protocol to carry
|
||
command-and-control traffic, obfuscated or encrypted payload data, or other
|
||
unwanted functions. DNS is a suitable protocol for these nefarious activities
|
||
because administrators tend to allow it throughout their purview, as it is
|
||
necessary for normal network operation.
|
||
|
||
In brief, when looking at the :file:`dns.log`, analysts will primarily want to
|
||
know who is asking a question, what is the nature of the question, who answered
|
||
the question, and how was the question answered.
|
||
|
||
Understanding the Second :file:`dns.log` Entry
|
||
==============================================
|
||
|
||
Let’s use this framework to parse the two log entries. We will start with the
|
||
second entry. For reference, that entry is the following:
|
||
|
||
::
|
||
|
||
{
|
||
"ts": 1591367999.305988,
|
||
"uid": "CMdzit1AMNsmfAIiQc",
|
||
"id.orig_h": "192.168.4.76",
|
||
"id.orig_p": 36844,
|
||
"id.resp_h": "192.168.4.1",
|
||
"id.resp_p": 53,
|
||
"proto": "udp",
|
||
"trans_id": 19671,
|
||
"rtt": 0.06685185432434082,
|
||
"query": "testmyids.com",
|
||
"qclass": 1,
|
||
"qclass_name": "C_INTERNET",
|
||
"qtype": 1,
|
||
"qtype_name": "A",
|
||
"rcode": 0,
|
||
"rcode_name": "NOERROR",
|
||
"AA": false,
|
||
"TC": false,
|
||
"RD": true,
|
||
"RA": true,
|
||
"Z": 0,
|
||
"answers": [
|
||
"31.3.245.133"
|
||
],
|
||
"TTLs": [
|
||
3600
|
||
],
|
||
"rejected": false
|
||
}
|
||
|
||
According to this log entry, ``192.168.4.76`` asked ``192.168.4.1`` for the A
|
||
record of the host ``testmyids.com``, and received the answer ``31.3.245.133``.
|
||
There are more details in the log, but those are the key elements an analyst
|
||
should be able to extract.
|
||
|
||
Understanding the First :file:`dns.log` Entry
|
||
=============================================
|
||
|
||
Let’s take a look at the first :file:`dns.log` entry. For reference, that entry
|
||
is the following:
|
||
|
||
::
|
||
|
||
{
|
||
"ts": 1591367999.306059,
|
||
"uid": "CMdzit1AMNsmfAIiQc",
|
||
"id.orig_h": "192.168.4.76",
|
||
"id.orig_p": 36844,
|
||
"id.resp_h": "192.168.4.1",
|
||
"id.resp_p": 53,
|
||
"proto": "udp",
|
||
"trans_id": 8555,
|
||
"query": "testmyids.com",
|
||
"qclass": 1,
|
||
"qclass_name": "C_INTERNET",
|
||
"qtype": 28,
|
||
"qtype_name": "AAAA",
|
||
"rcode": 0,
|
||
"rcode_name": "NOERROR",
|
||
"AA": false,
|
||
"TC": false,
|
||
"RD": true,
|
||
"RA": false,
|
||
"Z": 0,
|
||
"rejected": false
|
||
}
|
||
|
||
According to this log entry, ``192.168.4.76`` asked ``192.168.4.1`` for the
|
||
AAAA record of the host ``testmyids.com``, and did not receive an answer.
|
||
|
||
This is technically true, but it is not the whole story. If we augment stock
|
||
Zeek with an additional script available from the project, we get a bit more
|
||
information.
|
||
|
||
Specifically, we can enable a new script,
|
||
:doc:`/scripts/policy/protocols/dns/auth-addl.zeek`.
|
||
|
||
We can invoke the script using this syntax:
|
||
|
||
.. code-block:: console
|
||
|
||
zeek@zeek:~/zeek-test/json2$ zeek -C LogAscii::use_json=T protocols/dns/auth-addl.zeek -r ../tm1t.pcap
|
||
|
||
The end result shows more information for the first :file:`dns.log` entry:
|
||
|
||
.. code-block:: console
|
||
|
||
zeek@zeek:~/zeek-test/json2$ cat dns.log | head -1
|
||
|
||
.. literal-emph::
|
||
|
||
{"ts":1591367999.306059,"uid":"CQsafSKqmlOyqrgC6","id.orig_h":"192.168.4.76","id.orig_p":36844,"id.resp_h":"192.168.4.1","id.resp_p":53,"proto":"udp","trans_id":8555,"query":"testmyids.com","qclass":1,"qclass_name":"C_INTERNET","qtype":28,"qtype_name":"AAAA","rcode":0,"rcode_name":"NOERROR","AA":false,"TC":false,"RD":true,"RA":false,"Z":0,"rejected":false,**"auth":["ns59.1and1.co.uk"]**}
|
||
|
||
The bolded ``auth`` item in the log entry shows that ``ns59.1and1.co.uk`` is the
|
||
authoritative name server that is designated to answer questions about the AAAA
|
||
record for ``testmyids.com``.
|
||
|
||
There are more details in the log, but those are the key elements an analyst
|
||
should be able to extract.
|
||
|
||
The ``uid`` and Other Fields
|
||
============================
|
||
|
||
Note the ``uid`` field in both log entries is ``CMdzit1AMNsmfAIiQc``. This is
|
||
the same UID value that appeared in the :file:`conn.log` entry for a DNS
|
||
record. That means the DNS activity in the :file:`conn.log` and the DNS
|
||
activity in this :file:`dns.log` entry are the same.
|
||
|
||
You could have used the UID in the :file:`conn.log` to search for the
|
||
corresponding records in the :file:`dns.log` using this UID. For example:
|
||
|
||
.. code-block:: console
|
||
|
||
zeek@zeek:~/zeek-test/json$ grep CMdzit1AMNsmfAIiQc dns.log
|
||
|
||
::
|
||
|
||
{"ts":1591367999.306059,"uid":"CMdzit1AMNsmfAIiQc","id.orig_h":"192.168.4.76","id.orig_p":36844,"id.resp_h":"192.168.4.1","id.resp_p":53,"proto":"udp","trans_id":8555,"query":"testmyids.com","qclass":1,"qclass_name":"C_INTERNET","qtype":28,"qtype_name":"AAAA","rcode":0,"rcode_name":"NOERROR","AA":false,"TC":false,"RD":true,"RA":false,"Z":0,"rejected":false}
|
||
|
||
{"ts":1591367999.305988,"uid":"CMdzit1AMNsmfAIiQc","id.orig_h":"192.168.4.76","id.orig_p":36844,"id.resp_h":"192.168.4.1","id.resp_p":53,"proto":"udp","trans_id":19671,"rtt":0.06685185432434082,"query":"testmyids.com","qclass":1,"qclass_name":"C_INTERNET","qtype":1,"qtype_name":"A","rcode":0,"rcode_name":"NOERROR","AA":false,"TC":false,"RD":true,"RA":true,"Z":0,"answers":["31.3.245.133"],"TTLs":[3600.0],"rejected":false}
|
||
|
||
Note the matching ``uid`` fields in the :file:`dns.log` entries. In this simple
|
||
example, these are the only two entries in the :file:`dns.log`. Extrapolate
|
||
this technique to logs with billions of records and you will appreciate the
|
||
value!
|
||
|
||
Remember that a single :file:`conn.log` entry summarized all of the DNS traffic
|
||
associate with the “connection” bearing UID ``CMdzit1AMNsmfAIiQc``. Zeek
|
||
treated the 4 packets associated with this conversation as a connection because
|
||
they shared the same source and destination IP addresses and ports, and
|
||
occurred over the UDP protocol. The single :file:`conn.log` entry had the
|
||
timestamp ``1591367999.305988``, which is also the timestamp of the first
|
||
:file:`dns.log` entry.
|
||
|
||
Zeek’s DNS protocol analyzer created two log entries because it recognized two
|
||
different DNS exchanges. The first involved a query and response for
|
||
IPv6-related information, i.e., a AAAA record for ``testmyids.com``. The second
|
||
involved a query and response for IPv4-related information, i.e., an A record
|
||
for ``testmyids.com``. It is interesting to note that the DNS resolver on the
|
||
``192.168.4.76`` system requested IPv6 information first, and then IPv4.
|
||
|
||
Conclusion
|
||
==========
|
||
|
||
Zeek’s :file:`dns.log` is a critical log that offers a great deal of
|
||
information on how systems are interacting with the Internet and each other. In
|
||
the next section we will look at other core Internet protocols.
|