Tracking an Infected Host Using OSSIM / USM with Customization

December 21, 2016  |  Dmitry Shulinin

Good day everyone!

Today I want to share the experience of tracking the activity of malicious software on a host with the help of OSSIM or USM, and some customization.

Let’s look at a typical network of a small or mid-sized enterprise. For example, we have a few client PCs running Windows 7, 8, 10, and a domain controller which also acts as a DNS server for the client PCs. This network is connected to the Internet through a gateway, which also acts as a firewall and an IPS (IDS).

Now imagine one of our client PCs is infected with malware. After the infection the malware tries to communicate with some Command and Control (C&C), perhaps to send some valuable information.

The first thing the malware might do is try to resolve the name of the C&C or web-server via DNS. So the infected PC sends DNS requests to the internal DNS server. The DNS server then forwards the requests to the DNS server on the Internet. These requests travel through the gateway (which is also a firewall and IPS(IDS)). In this case, our IPS knows about those C&C and it generates an alert and blocks the request. That’s nice. Yet we still have an infected host on our network. So how can we find it? Of course we can copy the name of the C&C from the alert generated by the IPS and search the logs of our internal DNS for it. But that's not very easy, especially when there is plenty of activity and many alerts.

Here the USM/OSSIM comes into play. In the following I will describe how I was able to detect infected hosts on the network.

Summary

The logs of the IPS and internal DNS are gathered and analyzed by OSSIM/USM. When OSSIM sees an alert from the IDS it gets the name of the C&C from the message (via a custom or a pre-built plugin). OSSIM passes the name of the C&C to a script, which searches the DNS log and gets the IP of the client who made this request. The script writes the client’s IP with the C&C hostname to a log. This log is picked up by a custom plugin of OSSIM and displayed as an alert with the IP of the client’s PC. So the security admin knows which PC is infected at the moment it starts to communicate with the C&C, without manually browsing through tons of logs.

The lab environment

To test this case I built the following environment (shown in Fig.1):

  • A Linux PC acting as the gateway to the Internet with Snort onboard (10.0.1.37, LIN-GW);
  • A DNS server on Windows 2008 R2 (10.0.1.36, WIN-DNS);
  • OSSIM server (10.0.1.34, OSSIM);
  • Client PC (10.0.1.35, WIN-PC).

OSSIM lab environment including windows PCs and DNS as well as IPS

Fig.1 – Lab Environment

How it works (in detail)

In my lab I did not infect the client PC with any malware. To test this case I added a Snort signature that alerts whenever it catches a DNS request to resolve eicar.org. To test it I will issue “nslookup eicar.org” command from the client PC (WIN-PC).

This setup works in the following way (see Fig.2):

  1. WIN-PC sends a DNS request for eicar.org to the WIN-DNS;
  2. WIN-DNS forwards this DNS request to the DNS server on the Internet;
  3. The request gets intercepted by Snort running on LIN-GW;
  4. Snort creates an alert: Discovered resolve request for a (eicar.org) from (10.0.1.36);
  5. The Snort alert is received by the OSSIM via syslog and is parsed by a custom plugin (or you may be able to use a built-in one);
  6. A directive is triggered for this Snort alert on OSSIM/USM which is included in a policy;
  7. The action used in the policy executes a Python script and passes the (eicar.org) to it;
  8. The script then waits for the request for to appear in the logs of WIN-DNS server. The script extracts the IP of the PC which made the DNS request for ;
  9. The script writes the discovered IP of the client PC to a log_file;
  10. A custom plugin reads the log_file and displays the IP of the client which made the request for eicar.org in the user interface of OSSIM/USM.

* Here I have to make a remark about step 8. Of course, the DNS request from the client (WIN-PC) to the server (WIN-DNS) comes before the alert from Snort. Yet, the issue about Windows DNS server is that it writes debug logs (the logs that contain client’s requests) not in real-time but with a 10 to 40 second delay. So it is fine to “grep” the Windows log after Snort fires an alert. If I used for example BIND for my DNS server than I would have to grep some seconds of BIND’s logs in the past.

ossim lab environment including Windows PCs DNS and IPS gateway

Fig.2 – Use Case Explained

Setting up the environment

To set up the described environment we need:

  1. Snort installation forwarding logs to OSSIM server;
  2. Custom plugin for OSSIM to parse Snort events (optional);
  3. Windows 2008 R2 Server with a DNS role enabled and debug log turned on;
  4. Log forwarding from WIN-DNS to OSSIM;
  5. Custom plugin for OSSIM to parse Windows DNS logs (optional);
  6. Policy in OSSIM using a directive (directive fires on Snort signature);
  7. Script in Python that searches the WIN-DNS logs for the hostname produced by the policy;
  8. Custom plugin to parse the script output and show it in the OSSIM graphical interface.

1. Snort installation forwarding logs to OSSIM server

Snort is installed on a server running CentOS (LIN-GW). The installation is pretty straightforward and there are lots of guides on the Internet, so I will not describe it. After installing Snort, a test rule should be configured to trigger alerts on DNS requests for eicar.org. To accomplish this task a file named “malware_sites.rules“ was placed in the directory “/etc/snort/rules”. The content of the file is the following:

alert udp $HOME_NET any -> $EXTERNAL_NET 53 (msg:"DNS request for a malware site eicar.org"; content:"|05|eicar|03|org|00|"; classtype:bad-unknown; sid:2013570; rev:1;)

In short, it tells Snort to trigger an alarm anytime Snort catches a DNS request containing “eicar.org”. Snort alarms should then be passed to the OSSIM server. To configure that a file “snort.conf” in “/etc/rsyslog.d/” was created with the following content:

if $programname == 'snort' then /var/log/snort/alert

if $programname == 'snort' then @10.0.1.34

It tells rsyslog to forward the message to OSSIM server (10.0.1.34) if the message’s “programname” field equals “snort”. For the changes to take place both rsyslog and Snort should be restarted:

# service rsyslog restart

# service snort restart

Now we have Snort alerting on DNS requests for eicar.org. The alerts are then passed to the OSSIM server.

2. Custom plugin for OSSIM to parse Snort events

To get the Snort logs into OSSIM rsyslog on the OSSIM server, it should be configured to accept the logs from LIN-GW and write them to a file. The file is then analyzed by the OSSIM plugin. To configure rsyslog a file “/etc/rsyslog.d/snort.conf” was created with the following line:

if $programname == 'snort' then /var/log/snort_remote.log

Remember to restart rsyslog.

You can probably parse Snort logs with the built-in parser of OSSIM but I created a custom one. Here is the listing of “/etc/ossim/agent/plugins/snort_remote.cfg”:

[DEFAULT]
plugin_id=9011
[config]
type=detector
enable=yes
process=snort
start=no
stop=no
startup=
shutdown=
source=log
location=/var/log/snort_remote.log
create_file=false

[01-snort]
event_type=event
regexp=(?PS+s+d+s+d+:d+:d+).*DNSs+requests+fors+as+malwares+sites+(?PS+)s+[Classification:s+(?P.*?)].*?(?Pd+.d+.d+.d+):(?Pd+)s+->s+(?Pd+.d+.d+.d+):(?Pd+)
date={normalize_date($date)}
plugin_sid=1
src_ip={$srcip}
src_port={$srcport}
dst_ip={$dstip}
dst_port={$dstport}
userdata1={$request}
userdata2={$class}

And the following is the contents of “snort_remote.sql” file which inserts the info about the new plugin into the OSSIM database:

DELETE FROM plugin WHERE id = "9011";
DELETE FROM plugin_sid where plugin_id = "9011";
INSERT IGNORE INTO plugin (id, type, name, description, vendor, product_type) VALUES (9011, 1, 'snort', 'Snort', 'Snort', 25);
INSERT IGNORE INTO plugin_sid (plugin_id, sid, category_id, subcategory_id, class_id, name, priority, reliability) VALUES (9011, 1, 11, 139, NULL, 'DNS Request for malicious site eicar.org' ,1, 1);

Update the OSSIM database with the info about the new plugin:

# ossim-db < /usr/share/doc/ossim-mysql/contrib/plugins/snort_remote.sql

3. Windows 2008 R2 Server with DNS role enabled and debug log turned on

The role of DNS server should be enabled on the Windows 2008 R2 server. Also the debug log of the DNS service should be enabled and configured to log client requests to the server. There is a lot of information about this on the Internet so I will not go deep into this process. The following is sample content of the DNS log file:

11/6/2016 6:07:40 PM 0468 PACKET  0000000006069FA0 UDP Rcv 10.0.1.35       0002   Q [0001   D   NOERROR] A      (5)eicar(3)org(0)
11/6/2016 6:07:40 PM 0468 PACKET  0000000006076B10 UDP Snd 128.63.2.53     ac6e   Q [1000       NOERROR] A      (5)eicar(3)org(0)
11/6/2016 6:07:42 PM 0450 PACKET  000000000606D9C0 UDP Snd 198.41.0.4      07b9   Q [0000       NOERROR] PTR    (2)36(1)1(1)0(2)10(7)in-addr(4)arpa(0)
11/6/2016 6:07:42 PM 0468 PACKET  000000000606F6D0 UDP Rcv 10.0.1.35       0003   Q [0001   D   NOERROR] AAAA   (5)eicar(3)org(0)
11/6/2016 6:07:42 PM 0468 PACKET  00000000060730F0 UDP Snd 202.12.27.33    5827   Q [0000       NOERROR] AAAA   (5)eicar(3)org(0)
11/6/2016 6:07:44 PM 0450 PACKET  0000000006076B10 UDP Snd 198.41.0.4      ac6e   Q [0000       NOERROR] A      (5)eicar(3)org(0)

It is clear that the client PC with IP 10.0.1.35 made requests to resolve eicar.org and these requests were forwarded to the upper DNS server.

4. Log forwarding from WIN-DNS to OSSIM

After DNS logging is enabled we need to forward the logs to the OSSIM server. I use NXlog as a forwarder. NXlog is an awesome piece of software that can handle many types of logs including Windows eventlog, text files and syslog. In the described scenario NXlog is used for forwarding and pre-parsing messages from the Windows DNS debug log. NXlog is free for download and the installation of NXlog is pretty straightforward (just hit next until the end).

The configuration file of NXlog by default is “C:Program Files (x86) xlogconf xlog.conf”. The following is the configuration itself (with comments added for clarification):

# defining config files and folders
define ROOT C:Program Files (x86)
xlog 
Moduledir %ROOT%modules
CacheDir %ROOT%data
Pidfile %ROOT%data
xlog.pid
SpoolDir %ROOT%data
LogFile %ROOT%data
xlog.log

# enabling syslog extension. Without this we can’t forward logs via syslog
 
 Module xm_syslog


# Defining input source of logs

Module im_file # The input type is a text file
 File 'c:DNSlogdns.log'  # The log file itself
 SavePos TRUE # Track the last position of file
 ReadFromLast TRUE
 PollInterval 5 # Update every 5 srconds
 CloseWhenIdle TRUE

# The following line is the pre-parsing of DNS log. It turns the normal DNS log line into a more readable and easy for parsing with OSSIM format

 Exec if $raw_event =~/(d+/d+/d+s+d+:d+:d+)s+.*(Snd|Rcv)s+(d+.d+.d+.d+)s+S+s+w+s+w+s+S+s+w+s+S+s+(w+)s+(d+)(S+)(d+)/

 { 
                  $EventTime = parsedate($1); 
                  $SourceName = $3; 
                  $ProcessID = $2; 
                  $Message = $5; 
                  if $Message =~ s/(d+)/./g log_info("removed all whitespace in SourceName"); 
                }


# Defining output of logs


 Module om_udp
 Host 10.0.1.34
 Port 514
 Exec to_syslog_bsd();


# Defining route – that is which inputs should match which outputs


    Path        in => out

You can find the description of all the parameters in the configuration above on the Internet. What NXlog does using this configuration is:

  • Reads lines from file 'c:DNSlogdns.log' one by one;
  • Applies the regular expression “~/(d+/d+/d+s+d+:d+:d+)s+.*(Snd|Rcv)s+(d+.d+.d+.d+)s+S+s+w+s+w+s+S+s+w+s+S+s+(w+)s+(d+)(S+)(d+)/” to every line and extracts the following info from it – EventTime, SourceName, ProcessID, Message;
  • Forms a syslog message with the extracted EventTime, SourceName, ProcessID, Message and sends it via UDP 514 to OSSIM.

The log lines sent to OSSIM look like this:

Oct 26 00:12:33 MSSQL 10.0.1.35[Snd]: eicar.org

5. Custom plugin for OSSIM to parse Windows DNS logs

It is not necessary to set up parsing of Windows DNS logs for this precise scenario because the script that is launched by the OSSIM policy performs the search through the DNS logs. Yet it’s useful to have Windows DNS logs in OSSIM so we can do searches. To catch the logs from Windows DNS I tuned the rsyslog on OSSIM to write the logs arriving via syslog from Windows DNS to a file. The contents of “/etc/rsyslog.d/windns.conf” are the following (you can make it more granular adding filtering based on key words or program name etc):

if $fromhost-ip == '10.0.1.36' then {
        -/var/log/windns.log
        stop
}

Here is the config file “/etc/ossim/agent/plugins/windns.cfg”:

[DEFAULT]
plugin_id=9010
[config]
type=detector
enable=yes
source=log
location=/var/log/windns.log
create_file=false
process=
start=yes
stop=no
startup=
shutdown=

[translation]

Rcv=1
Snd=2
[01-windns]
event_type=event
regexp="(?PS+s+d+s+dd:dd:dd)s+(?PS+)s+(?PS+)[(?PRcv|Snd)]:s+(?PS+)"
plugin_sid={translate($type)}
date={normalize_date($date)}
device={resolv($device)}
src_ip={$source}
dst_ip={resolv($device)}
userdata1={$query}
userdata2={$type}

And here is the config file “/usr/share/doc/ossim-mysql/contrib/plugins/windns.sql”:

DELETE FROM plugin WHERE id = "9010";
DELETE FROM plugin_sid where plugin_id = "9010";
INSERT IGNORE INTO plugin (id, type, name, description, vendor, product_type) VALUES (9010, 1, 'windns', 'WinDNS', 'Microsoft', 25);
INSERT IGNORE INTO plugin_sid (plugin_id, sid, category_id, subcategory_id, class_id, name, priority, reliability) VALUES (9010, 1, 11, 139, NULL, 'WinDNS: Request' ,1, 1);
INSERT IGNORE INTO plugin_sid (plugin_id, sid, category_id, subcategory_id, class_id, name, priority, reliability) VALUES (9010, 2, 11, 139, NULL, 'WinDNS: Reply' ,1, 1);

# ossim-db < /usr/share/doc/ossim-mysql/contrib/plugins/windns.sql

6. Create a policy in OSSIM

The policy should trigger on the Snort signature and launch the script also passing the name of the malware site to it.

First we need a directive to fire on Snort events. To do this, in the OSSIM graphical interface go to “Configuration” -> “Threat Intelligence” -> “Directives”. Hit the “New directive” and create the new directive with the following parameters:

  • Name for the directive – Anything you want, I called it “DNS Request For Malicious Sites”;
  • Taxonomy – it also is up to you, I classified it like “Delivery & Attack”, “Adware infection”, “Malware infestation”;
  • Priority – I put “3”;
  • Reliability – “2”;
  • Timeout – “None”;
  • Occurrence – “1”;
  • From – “any”;
  • To – “any”;
  • Data source – “9011” – this is the plugin_id which handles the SNORT logs;
  • Event type – sid “1”.

The created directive should look like this (Fig.3).

OSSIM directive for SNORT events to track infected PC

Fig.3. – OSSIM directive for SNORT events

Secondly we need an action that will be triggered by the directive we've created. In the OSSIM graphical interface go to “Configuration” -> “Threat Intelligence” -> “Actions”. Hit “New”. The “Name” and the “Description” is totally up to you. I named it “ET DNS Query”. The Type of the action should be “Execute an external program”, condition – “any”. The command should point to the script, for example “/usr/share/ossim/scripts/tail.py USERDATA1”. When finished hit the “Save” button. This action launches the script and passes the info found in the USERDATA1 field of the event.

Finally the policy puts the directive and the action together. To create the policy go to “Configuration” -> “Threat Intelligence” -> “Policy”. Hit “New” in the “Policies for events generated in server” section. Give the policy a name you like. I named it “DNS requests for eicar.org”. In the “Policy conditions” -> “Event types” choose the created directive “DNS Request For Malicious Sites”. Switch to “Policy consequence” section and add the action you created (“ET DNS Query” for me). When finished hit the “Update policy” button. The policy is ready.

7. Python script to search the Windows DNS logs

The directive that is triggered by Snort alert launches a script that searches the DNS log for the hostname from the alert. Here is the listing of the script:

#!/usr/bin/python
from sh import tail
import sys
import syslog
log_file="/var/log/windns.log"

try:
   for line in tail ("-f", log_file, _iter=True):
      if sys.argv[1] in line and "[Snd]" in line:
         syslog.openlog('malware_request', 0, syslog.LOG_LOCAL5)
         syslog.syslog((sys.argv[1] + ' Source:' + (line.split()[4]).split("[")[0]))
         break
         time.sleep(2)

except:
   cleanup_stop_thread();
   sys.exit()

This script takes hostname as an argument and waits for this hostname to appear in the DNS log. As soon as it finds the hostname it gets the IP of the client who issued the request. The script then passes this info to rsyslog. Rsyslog on the OSSIM writes it to a file. Log lines produced by the script look like this:

Nov 27 20:02:00 alienvault malware_request: eicar.org Source:10.0.1.35

8. Custom plugin to parse the script output

One last thing to do is create a custom plugin to parse the output of the script. Following are the configurations of the plugin. The /etc/ossim/agent/plugins/alert_event.cfg:

[DEFAULT]
plugin_id=9012
[config]
type=detector
enable=yes
source=log
location=/var/log/malware_requests.log
create_file=false
process=
start=yes
stop=no
startup=
shutdown=

[01-malware_alert]

event_type=event
regexp="(?PS+s+d+s+dd:dd:dd)s+(?PS+)s+malware_request:s+(?PS+)s+Source:(?PS+)"
plugin_sid=1
date={normalize_date($date)}
device={resolv($device)}
src_ip={$source}
dst_ip={resolv($device)}
userdata1={$query}

DELETE FROM plugin WHERE id = "9012";

DELETE FROM plugin_sid where plugin_id = "9012";

INSERT IGNORE INTO plugin (id, type, name, description, vendor, product_type) VALUES (9012, 1, 'alert_event', 'Custom', 'Plugin', 25);

INSERT IGNORE INTO plugin_sid (plugin_id, sid, category_id, subcategory_id, class_id, name, priority, reliability) VALUES (9012, 1, 11, 139, NULL, 'Alert Event: DNS request for malware site' ,1, 1);

Update the OSSIM database with the info about the new plugin:

# ossim-db < /usr/share/doc/ossim-mysql/contrib/plugins/alert_event.sql

Also remember to turn on all the plugins that were created. To do this connect to the OSSIM via SSH. Go to “Configure sensor” – “Configure data source plugins”. Put a tick next to the names of the created plugins: alert_event, snort_remote, windns. Hit “OK”, then “Back” and finally select “Apply all changes” and “OK”. The sensor will restart and turn on the selected plugins.

Conclusion

The environment we created allows us to track hosts trying to resolve the hostnames of malware sites. It doesn’t stick only to detecting “eicar.org”. It can find any hostname passed to the script by the policy action. So it can be used in conjunction with other directives.

Finally, the following screenshots show how the Snort alerts, Windows DNS logs and generated alerts look in OSSIM.

snort alerts being passed to ossim

Fig.4. – SNORT alerts

windows dns alerts in snort

Fig.5. – Windows DNS logs

ossim alerts with infected hosts detected with customization

Fig.6. – OSSIM alerts with client IP found (10.0.1.35)

I wish you all the best in your customization of OSSIM/USM.

Share this with others

Get price Free trial