Fast Flux and DNS Cache Poisoning Detection 0.2

Download dns_state.3.tar.gz

Old Snort Page


On the suggestion of Andre Ludwig, I ported the crusty old DNS preprocessor code to a newer version (2.8.3.beta), and am releasing it for general use. In it's current form I just made a few modifications for data structure changes and attached it to the excellent existing dynamic DNS preprocessor.   This set of code should detect two general types of interesting events:
If there is interest for this software, I would be happy to create more documentation than just this page.  Until that point in time this set of notes will have to do.

Details

DNS Cache Poisoning
Several excellent descriptions of this phenomena exist already so I will not go cut and paste them into here.  There are several different tests that are done here.  They are as follows:


Multiple responses to a query where the DNS server IP and query name match, but the transaction ID varies.  This alert looks like:

[**] [131:4:1] (spp_dns_session) NOID host.example.com [**]
[Priority: 3]
07/23-10:36:16.300546 10.10.10.10:53 -> 192.168.1.127:53
UDP TTL:255 TOS:0x0 ID:5312 IpLen:20 DgmLen:187
Len: 159

Multiple responses to a query where the DNS server IP, query name and transaction ID match.  This is similar to the attack above, except that there is a transaction ID match.  The alert text looks like:

[**] [131:5:1] (spp_dns_session) ID host.example.com [**]
[Priority: 3]
07/23-10:36:16.941173 10.20.20.20:53 -> 192.168.1.127:53
UDP TTL:52 TOS:0x0 ID:51123 IpLen:20 DgmLen:126
Len: 98

Unexpected responses where there is no observed question.  This is somewhat noisy, but is added to provide a site the ability to monitor this quantity over time.  The alert text looks like:

[**] [131:6:1] (spp_dns_session) DNS Response without question for x.example.com [**]
[Priority: 3]
07/23-10:36:15.839465 10.30.30.30:53 -> 192.168.1.127:53
UDP TTL:255 TOS:0x0 ID:39003 IpLen:20 DgmLen:187
Len: 159

Fast Flux Detection
Like the cache poisoning, there are many interesting and informative sites which describe DNS fast flux.  One of my favorites is the Honey Net site's "Know Your Enemy: Fast Flux Service Networks" .  The main algorithm used in this detector is based in part on a paper presented at NDSS '08 by Holz, Gorecki, Freiling and Rieck.  Their contribution to network based fast flux detection can not be emphasized enough!!

What we look for is an unusually large number of ASN records associated with a given A records lookup taken over a time window.  The running weight for a particular A record is not just a simple W = A*i + B*n (with A and B being constants, i being the number of unique IP addresses and n being the number of unique ASN's), but also incorporates the notion that fast flux networks will be spread out more evenly across address space than 'normal' content distribution networks.  With this in mind, the running weight looks more like: W = ( n / i )( A * i +  B * n ).  This does a slightly better job in detection.

Note that this will absolutely flag an number of records which by design act exactly like hostile fast flux domains.  Examples are pool.ntp.org, chat.freenode.net, ocsp.verisign.net and several more.  We expect to publish a new algorithm soon which will address a number of these problems.

Output from this preprocessor looks like:

[**] [131:7:1] FLUX mailers.gfi.com IP: 6 ASN: 6 WEIGHT: 119.160000[**]
[Priority: 3]
08/21-12:12:54.187414 216.218.202.31:53 -> 128.55.6.66:51407
UDP TTL:118 TOS:0x0 ID:51700 IpLen:20 DgmLen:488
Len: 460



Configuration
There are a number of additional configuration options available to the dns preprocessor.  They are as follows:

Option
Notes
dns_session Activates cache poisoning detection.  Not required for flux detection.
dns_state_window <time in sec>  Time window that state information is maintained before being flushed.  Default = 10 seconds.
max_noid_threshold <n> Number of DNS responses which match client IP and query name, but which disagree on session ID.  Default = 50.
max_id_threshold <n> Same as above except that session id matches as well.  Default = 50.
multiple_response <n> Look for multiple DNS responses where session id matches. Associated with max_id_threshold.  Default = 1: set to 0 to turn off.
multiple_response_timeout <time in sec> Defines window for max_id_threshold test.
rogue_response Report DNS responses which do not have an associated request. Rather noisy.  Default = off.
dns_flux Activate fast flux detector.
dns_flux_runtime_dump Dump running debug information.  Output looks something like:

pool.ntp.org IP: 1  ASN: 1 WEIGHT: 19.860000 IP: 69.36.240.252 ASN: AS8121
pool.ntp.org IP: 2  ASN: 2 WEIGHT: 39.720000 IP: 216.184.20.83 ASN: AS10381
pool.ntp.org IP: 3  ASN: 3 WEIGHT: 59.580000 IP: 216.75.55.11 ASN: AS10439
pool.ntp.org IP: 4  ASN: 4 WEIGHT: 79.440000 IP: 74.53.198.146 ASN: AS21844

flux_logfile < absolute file path > Optional logfile to dump detailed log information to.

Sample Usage:

 preprocessor dns: \
    ports { 53 } \
    enable_rdata_overflow \
        enable_experimental_types \
        dns_session \
        multiple_response \
        dns_flux \
        dns_flux_runtime_dump \
        flux_logfile /tmp/logf

Install
For now the install is a little free and loose.  For fast flux detection to work, you will have to have the MaxMind GeoIP libraries installed as well as the GeoLite ASN database.  The general GeoIP can be found here, while the GeoLite ASN is here.  Make sure that the install went correctly before proceeding.

The source tarball contains the following files:

src/dynamic-preprocessors/dns/spp_dns.c : man preprocessor source
src/dynamic-preprocessors/dns/spp_dns.h : main preprocessor header
src/dynamic-preprocessors/dns/Makefile.in : makefile prototype for new libs
src/dynamic-preprocessors/libs/dnslib.c : library functions for the new code
src/dynamic-preprocessors/libs/dnslib.h : library functions for the new code

you should just be able to untar the code in the main source root.  This was built against snort-2.8.3.beta, but this part of the source tree has been dormant as of late so the changes should work for most versions. 

The 'configure' environment will have to be modified slightly to take into consideration GeoIP by modifying environmental variables.  For example:

export LDFLAGS -L/usr/local/lib
export LIBS -lGeoIP
export CPPFLAGS -I/usr/local/include

then configure and make as usual with whatever changes are normal to your system.