Alerting on IOCs using Suricata

In our previous post, we talked about Why you should use Suricata IDS to alert on IOCs, Suricata has a relatively new feature called Datasets, that allows you to alert on a Indicators of Compromise (IOCs), such as malicious domains and IPs.

This feature works in a very simple way, you need to create a file with the lists of the Indicators in Base64 encoded format for string data (eg: domains) and hex notation for hashes (eg: sha265 malicious file hash) and a Suricata Rule to utilize that Indicators list.

In this post I will explain how to utilize the Datasets feature of Suricata to alert on DNS Queries to malicious domains obtained from ThreatFox API.

Preparing the IOCs file

The first thing to do is to download the list of IOCs from the ThreatFox API using a simple curl command that will save the data in a file named iocs_list.json:

curl -X POST -d '{ "query": "get_iocs", "days": 90 }' > iocs_list.json

then we filter the json data for domain IOCs, we will use jq linux command for this and save the output in domains.text:

cat iocs_list.json | jq -c -r '.data[] | select( .ioc_type == "domain") | .ioc' > domains.text

finally, we will encode the domains in base64 format as required by Suricata

while IFS= read -r line; do echo -n $line | base64 -w 1000; done < domains.text > domains_iocs.list

now that we have our IOCs list ready in domains_iocs.list, lets copy it to our suricata rules directory

cp domains_iocs.list /etc/suricata/rules/ && chown suricata:suricata /etc/suricata/rules/domains_iocs.list

Creating the Suricata IDS Rule

To alert on DNS Queries to any of the malicious domains in domains_iocs.list, we need to create an IDS Rule, that will compare the dns.query keyword value with the domains in domains_iocs.list and generate an alert when it finds a match.

The Rule is:

alert dns $HOME_NET any -> any any (msg:"DNS Query to Malicious FQDN"; dns.query; dataset:isset, domains_iocs, type string, load /etc/suricata/rules/domains_iocs.list, memcap 10mb, hashsize 1024; classtype: trojan-activity; sid:1000000; rev:1;)

In the above example, we chose do define the DataSet in the rule rather than suricata.yaml, this will make suricata reload the datasets when we reload the IDS Rules, if you choose to define the DataSet in suricata.yaml, you will have to update the indicators one-by-one using dataset-add & dataset-remove Unix Socket Commands.

We then place the above rule in a new rules file named iocs.rule and configure suricata to load it by adding iocs.rules to the list of rules files

echo 'alert dns $HOME_NET any -> any any (msg:"DNS Query to Malicious FQDN"; dns.query; dataset:isset, domains_iocs, type string, load /etc/suricata/rules/domains_iocs.list, memcap 10mb, hashsize 1024; classtype: trojan-activity; sid:1000000; rev:1;)' > /etc/suricata/rules/iocs.rules

Here is the suricata.yaml configuration section, notice that we changed the default rules path to /etc/suricata/rules since we placed iocs.rules file there

default-rule-path: /etc/suricata/rules

  - suricata.rules
  - iocs.rules

Then we proceed to run suricata and make it listen to traffic in our testing VM

suricata -c /etc/suricata/suricata.yaml -i enp0s3

Verifying that Alerting works

Now that we have suricata running and listening to traffic from/to our testing VM, we are going to verify that our IOCs alerting actually works by sending a dns query to one of the domains listed in our domains_iocs.list file.

To do this lets get the first domain:

cat /etc/suricata/rules/domains_iocs.list | head -n 1 | base64 -d

and then make a dns query to it using nslookup command, you will need bind-utils package installed to get this command

[[email protected] ~]# nslookup

Non-authoritative answer:

By inspecting /var/log/suricata/eve.json for alerts, we can see that suricata generated the following alert:

    "timestamp": "2021-10-08T23:21:45.862793+0400",
    "flow_id": 1107584459811401,
    "in_iface": "enp0s3",
    "event_type": "alert",
    "src_ip": "",
    "src_port": 46647,
    "dest_ip": "",
    "dest_port": 53,
    "proto": "UDP",
    "tx_id": 0,
    "alert": {
        "action": "allowed",
        "gid": 1,
        "signature_id": 1000000,
        "rev": 1,
        "signature": "DNS Query to Malicious FQDN",
        "category": "A Network Trojan was detected",
        "severity": 1
    "dns": {
        "query": [
                "type": "query",
                "id": 42375,
                "rrname": "",
                "rrtype": "AAAA",
                "tx_id": 0
    "app_proto": "dns",
    "flow": {
        "pkts_toserver": 1,
        "pkts_toclient": 0,
        "bytes_toserver": 81,
        "bytes_toclient": 0,
        "start": "2021-10-08T23:21:45.862793+0400"

as we can see, Suricata successfully alerted on the malicious domain, this features can easily scale to alert on million of IOCs that you would otherwise need to write tens of thousands rules for them to get the same results.

How IDSTower can help?

IDSTower not only will automatically setup & configure those features in Suricata, it will also Integrate with Threat Intelligence Feeds to download IOCs and push them to Suricata, all with a single click!

If you are interested to learn more on how IDSTower can help you enhance your network security operations, please take a look at the Features that IDSTower offers.