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
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.