This post appeared originally in our sysadvent series and has been moved here following the discontinuation of the sysadvent microsite
In a recent sysadvent article I described how to configure BIND with a Response Policy Zone. Using an RPZ can efficiently thwart outbound network traffic based on one’s own preferences, and it can be extended to import and/or subscribe to externally provided DNS zones.
Configuring BIND
My local BIND server has been configured with two RPZs. One is
maintained manually, mostly for reaching internal resources behind a
NAT firewall by their official DNS names. The other one is a dedicated
malware RPZ, automatically updated once a day from the freely
available files provided by the Malware Domain
Blocklist (note their terms of
use). When downloaded,
the list of domains associated with malicious activity is converted to
an RPZ compatible zone file. The resulting file is saved as
/etc/bind/db.malware
. Below are the first few lines of this file
after conversion.
$TTL 60
@ IN SOA primary-dns.example.com. root.example.com. (
2015120911 ; serial
3H ; refresh
1H ; retry
1W ; expiry
1H) ; minimum
IN NS primary-dns.example.com.
IN NS secondary-dns.example.com.
jnvzpp.sellclassics.com IN A 127.0.0.1
IN AAAA ::1
iebar.t2t2.com IN A 127.0.0.1
IN AAAA ::1
27simn888.com IN A 127.0.0.1
IN AAAA ::1
74203s040.edusite.ru IN A 127.0.0.1
IN AAAA ::1
adfrut.cl IN A 127.0.0.1
IN AAAA ::1
byxlujke.ru IN A 127.0.0.1
IN AAAA ::1
; [...]
The malware zone
BIND allows up to 32 different Response Policy Zone files, so I’ve
separated the two, naming the manual zone “rpz” and the malware
domains zone “malware”. Configuring them is done in named.conf
or a
supporting file (for instance /etc/named.conf.local
if you’re on a
Debian based platform).
zone "rpz" {
; manually maintained zone
type master;
file "/etc/bind/db.rpz";
};
zone "malware" {
; automatically updated zone
type master;
file "/etc/bind/db.malwaredomains";
};
Both zones are added to the response-policy {}
clause. Add
this inside the options {}
section in named.conf
(or
/etc/bind/named.conf.options
on Debian and derivatives).
options {
response-policy {
zone "rpz";
zone "malware";
};
};
Log configuration
The zones defined in the above response-policy {}
setting will
automatically log to the rpz category. In Debian, logging is
configured in /etc/bind/named.conf.local
.
logging {
; Define a logging target (channel)
channel named-rpz {
file "/var/log/bind/rpz.log" versions 3 size 250k;
severity info;
};
; Direct every rpz event to the defined channel
category rpz {
named-rpz;
};
};
Paydirt!
When properly configured, requests for domains in the malware zone are
logged in the RPZ log file, suffixed with the zone reference, namely
malware
. The following extract shows successful logging of a request
for a domain listed in the malware zone.
client 127.0.0.1#53547 (byxlujke.ru): rpz QNAME Local-Data rewrite
byxlujke.ru via byxlujke.ru.malware
Requests picked up by the other RPZ file, simply named “rpz”, will
have a .rpz
suffix.
Adding OSSEC to the mix
After testing that attempts to reach malware sites are indeed logged by the DNS server, I set up OSSEC to tail BIND’s malware query log. For this I had to write a decoder and define logging rules in OSSEC, shown below. Both of these could probably be drastically improved by someone more fluent in OSSEC. That said, I haven’t seen a single false positive - yet…
OSSEC master
The log parsing takes place on the OSSEC master. There are two files to modify, and one to add.
Add the following content to /var/ossec/etc/local_decoder.xml
:
<decoder name="malware-dns">
<prematch>^client </prematch>
</decoder>
<decoder name="malware-dns-lookup">
<parent>malware-dns</parent>
<regex offset="after_parent">^(\.+)#\d+ \((\.+)\): \.+.malware$</regex>
<order>srcip, extra_data</order>
</decoder>
Add a new file /var/ossec/rules/malware_dns_rules.xml
with the
following content:
<group name="syslog,bind">
<!-- Malware DNS Log Types -->
<!-- level=0 for not generating alerts by default -->
<rule id="110201" level="0">
<decoded_as>malware-dns</decoded_as>
<description>Malware DNS group</description>
</rule>
<!-- Malware DNS Event Chains -->
<!-- Fire an alert (level=8) if the log line ends with "malware" -->
<rule id="110202" level="8">
<if_sid>110201</if_sid>
<match>malware$</match>
<description>Malware DNS lookup</description>
</rule>
</group>
Last step on the OSSEC master is to include the above rules file. Add
an <include> line in /var/ossec/etc/ossec.conf
:
<ossec_config>
[...]
<rules>
[...]
<include>malware_dns_rules.xml</include>
</rules>
[...]
</ossec_config>
OSSEC agent
The name of the file to tail needs to be defined on every OSSEC
agent. The configuration file for this is
/var/ossec/etc/ossec.conf
.
<ossec_config>
[...]
<localfile>
<log_format>syslog</log_format>
<location>/var/log/bind/rpz.log</location>
</localfile>
</ossec_config>
Testing the parser
If everything has been set up correctly, OSSEC parsing should work as
expected. To be on the safe side, test the parser with OSSEC’s
ossec-logtest
.
root@server:~# /var/ossec/bin/ossec-logtest
2015/12/09 08:49:48 ossec-testrule: INFO: Reading local decoder file.
2015/12/09 08:49:48 ossec-testrule: INFO: Started (pid: 2772).
ossec-testrule: Type one log per line.
client 127.0.0.1#3558 (byxlujke.ru): rpz QNAME Local-Data rewrite
byxlujke.ru via byxlujke.ru.malware
**Phase 1: Completed pre-decoding.
full event: 'client 127.0.0.1#3558 (byxlujke.ru): rpz QNAME
Local-Data rewrite byxlujke.ru via byxlujke.ru.malware'
hostname: 'server'
program_name: '(null)'
log: 'client 127.0.0.1#3558
(byxlujke.ru): rpz QNAME Local-Data rewrite byxlujke.ru via
byxlujke.ru.malware'
**Phase 2: Completed decoding.
decoder: 'malware-dns'
srcip: '127.0.0.1'
extra_data: 'byxlujke.ru'
**Phase 3: Completed filtering (rules).
Rule id: '110202'
Level: '8'
Description: 'Malware DNS lookup'
**Alert to be generated.
The result
Now, if someone (or something) on my network is trying to reach a resource on a domain registered as affiliated with malware, OSSEC will react and alert by email, raise an alarm in your SIEM, or whatever else you want OSSEC to do.
Below is a sample email alert from OSSEC, when attempting to browse a malware domain from a client.
OSSEC HIDS Notification.
2015 Dec 09 15:07:06
Received From: server->/var/log/bind/rpz.log
Rule: 110202 fired (level 8) -> "Malware DNS lookup"
Portion of the log(s):
client 192.168.42.42#52162 (byxlujke.ru):
rpz QNAME Local-Data rewrite byxlujke.ru via byxlujke.ru.malware
And an extract from OSSEC’s alert log:
** Alert 1449670026.3728841: mail - syslog,bind
2015 Dec 09 15:07:06 server->/var/log/bind/rpz.log
Rule: 110202 (level 8) -> 'Malware DNS lookup'
Src IP: 192.168.42.42
client 192.168.42.42#52162 (byxlujke.ru): rpz QNAME Local-Data rewrite byxlujke.ru via byxlujke.ru.malware
The irony of insecure security software
It can probably be understood from my previous blog post that if it was up to me, I’d avoid products like CrowdStrike - but every now and then I still have to install something like that. It’s not the idea of “security software” per se that I’m against, it’s the actual implementation of many of those products. This post lists up some properties that should be fulfilled for me to happy to install such a product.