Monday, February 6, 2012

A Different Approach to Network Intrusion Detection

There are many Intrusion Detection Systems out there. What exactly should an Intrusion Detection System or Solution do? Well that one’s sort of self explanatory, it should detect intrusions. There are host based intrusion detection solutions and there are network based IDS solutions. Host based IDS try to determine malicious processes and inter-process behavior from the perspective of a host. Network IDS solutions attempt to see malicious activity from analyzing network traffic. Network Based IDS has a particularly broad view, but is prone to false positives (falsely identifying benign traffic as malicious) and false negatives (not identifying malicious traffic). Additionally, more and more network traffic is being encrypted, thus hiding malicious payloads from IDS sensors. So in addition to the initial cost of purchasing an IDS solution, they require a lot of tuning to get useable results.

This post is about a different approach to network intrusion detection. It is certainly not meant to replace traditional IDS solutions, but can be added alongside existing solutions. This solution looks for traffic that shouldn’t exist at all. If traffic is seen using this method, it should be investigated. This stray traffic is either a result of a configuration error, or a malicious process. In addition to producing few false positives, the cost of this solution is next to nothing.

To implement this solution, a network administrator would basically black hole all address ranges that are known not to be in use and direct the traffic to a host that can capture these packets. The RFC1918 range should be a safe bet. Additionally any public IP address space that is owned by the organization, but not in use could also be used. Let’s look at an example organization’s IP address usage to understand how this might work

ACME Organization

Routing Protocol (IGP): EIGRP (summarization disabled)

IP Addresses (Internal)—

192.168.1.0/24
192.168.50.0/24
192.168.60.0/24
192.168.70.0/24
192.168.80.0/24
10.1.1.0/30
10.1.1.4/30
10.1.1.8/30
10.1.1.12/30

Public Addresses Owned: 192.0.2.0/24
Public Addresses Used: 192.0.2.1-250

In the ACME organization, we should only see IP traffic destined to IPv4 addresses in the above RFC1918 address ranges, the used public address range, and any other public IP address that are not owned by this organization. If traffic appears on the network destined to other RFC1918 address it is certainly out of place and should be investigated. Additionally packets containing a destination IP addresses 192.0.2.0 or 192.0.2.251-255 are also out of place and should be looked at.

So how do we easily capture this traffic for investigation? It is actually quite simple if we think about how routers work and how packets are converted into frames as they are handed back down the OSI model. The first concept we should revisit is the longest match rule that is used by the route table. If a router has a route to 192.168.0.0/16 and another to 192.168.50.0/24, a packet to 192.168.50.12 would match the route to 192.168.50.0/24. A packet to 192.168.33.5 would match 192.168.0.0/16. We can leverage this and inject some routes into our network. So let’s take this concept and apply it to a simple network.

Network Diagram

6-3-2011 12-36-27 AM.png

In the above diagram, we have a “deflection router”. This router is located just behind the firewall, but could be located anywhere in the network (as long as summary routes aren’t overriding the routes that we are about to inject). The first thing we need to do is to deflect packets going to unused RFC1918 ranges out the Ethernet interface connected to our “Sniffer Host”. To do this, we’ll set up an IP address for that interface, and create some routes.

Router(config)#interface fa0/1
Router(config-if)#ip address 10.1.1.13 255.255.255.252
Router(config-if)#no shut
Router(config)#ip route 10.0.0.0 255.0.0.0 10.1.1.14
Router(config)#ip route 172.16.0.0 255.240.0.0 10.1.1.14
Router(config)#ip route 192.168.0.0 255.255.0.0 10.1.1.14
Next we will create routes that will divert the unused public addresses.

Router(config)#ip route 192.0.2.0 255.255.255.255 10.1.1.14
Router(config)#ip route 192.0.2.251 255.255.255.255 10.1.1.14
Router(config)#ip route 192.0.2.252 255.255.255.252 10.1.1.14
Notice, I’m routing the traffic to these unknown address ranges to 10.1.1.14. Does 10.1.1.14 have to exist on “sniffer host”? Not exactly. Actually I might not even want IP bound to the sniffer hosts’ interface. This will help protect the sniffer host itself from being attacked. However, if I take this approach, I must somehow coerce the router to forward the frame anyway. Typically, the router will do an ARP lookup or request to figure out what destination MAC address to use on the frame it has to build. We can trick the router into doing this by creating a static ARP entry. In this diagram, we are directly connecting a host to the router via crossover cable so the host will receive all frames produced by that interface (we just need to remember to put the sniffer’s NIC into promiscuous mode when we start to capture traffic).

Router(config)#arp 10.1.1.14 abcd.abcd.abcd arpa

Now the router understands the egress interface for these packets based on the route statements and the interface that is connected to the 10.1.1.12/30 network. The static arp entry gives the router the information that it needs to “frame” the packets. As long as the interface is up and the router doesn’t have more specific routes to a destination, it will send these packets to the sniffer host.

Earlier I pointed out that this router is in the path to the firewall but it could be located anywhere in the network. Keep in mind that if summary routes are being used, that may need to be evaluated. If this router isn’t already in the path of all packets (aka the default gateway), the routes can be injected into the IGP. This might look something like the following.
Router(config)#router eigrp 1
Router(config-rtr)#redistribute static

Now all we need to do is connect the Sniffer Host to our router via a crossover cable and start our favorite sniffer program. We don’t even need an IP address or the IP Protocol bound on the sniffing interface. A good technique for capturing traffic might to be using dumpcap (part of the Wireshark package) to capture anything destined to MAC address abcd.abcd.abcd and storing it in a file. For example, create a directory called “c:\caps” and enter the following command.
C:\Program Files\Wireshark>dumpcap.exe -i 2 -b duration:86400 -b filesize:50000 files:1000 -f "ether host ab:cd:ab:cd:ab:cd" -w c:\caps\badtraffic.pcap

The above command uses dumpcap to capture traffic on interface 2. The interface number is entered following the “-i” parameter. To determine the interface numbers use for a system, use the following command “dumpcap –D” (case sensitive). The parameters following the “-b” parameters are the ring buffer options. These tell dumpcap when to create a new file. In this case, a new file would be created at least once every 24 hours, the files would never exceed 50MB, and 1000 files would be retained. This should keep space consumption below 50GB. The string following “-f” limits the capture to the frames that contain the MAC address abcd.abcd.abcd (from the static arp). Finally “-w” directs dumpcap to save this contents to a file in the c:\caps directory. The filenames will be based on badtraffic.pcap but will also include a timestamp in the filename.

Now that we have this in place, we can easily test it. To do so, simply ping an address from an RFC1918 address space that is not in use. For the ACME network, we could ping 192.168.254.200. It is a good idea to test this from various points in the network. These packets should make it to our capture file. Double clicking the capture files should open it in Wireshark. We can now investigate the file for any signs of configuration errors or reconnaissance against our internal network. While this is not a comprehensive IDS solution, it is a good way to see when an internal host has been infected with something that it is trying to propagate to other internal hosts.