munotes®

Practical 18: Intrusion Detection System

Get access to whole semester resourcesSemester Pass

Chapter Twenty-Three

Syllabus topic Module 2, "Intrusion Detection System: Set up and configure an intrusion detection system (IDS) to monitor network traffic and detect potential security breaches or malicious activities."

Pages 177 to 183 of 206

Aim

To set up an intrusion detection system, to write and read rules, to watch it detect a real attack in real traffic, to produce a false positive and tune it away, and to record what it cannot see.

What you need to know before you start

A firewall decides what may pass. An intrusion detection system looks at what did pass and says whether any of it was an attack. It stops nothing; it tells you. The variant that also blocks is an intrusion prevention system, and the difference is one of placement: an IDS sits beside the traffic, an IPS sits in it.

NIST SP 800-94 divides them two ways, and both divisions are examinable.

By what they watch:

WatchesSeesMisses
Network-based, NIDStraffic on a linkeverything crossing that linkanything encrypted, and anything that never crosses it
Host-based, HIDSone machine's files, logs and callswhat actually happened on that hostanything on any other host

By how they decide:

Signature detection looks for a known pattern. It is exact, it explains itself, and it cannot find an attack nobody has written a rule for.

Anomaly detection learns what normal looks like and reports departures from it. It can find something new, and it produces far more false alarms, because unusual and malicious are not the same thing.

Snort, which this practical uses, is a network-based signature system.

Step 1: two hosts and some traffic to look at

$ ip netns add attacker
$ ip netns add server
$ ip link add vA type veth peer name vS
$ ip link set vA netns attacker
$ ip link set vS netns server
$ ip -n attacker addr add 10.8.0.1/24 dev vA
$ ip -n server addr add 10.8.0.2/24 dev vS
$ ip -n attacker link set vA up
$ ip -n server link set vS up
$ ip netns exec attacker ping -c 1 -W 2 10.8.0.2 2>/dev/null | tail -2
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.000/0.000/0.000/0.000 ms

Now generate a mixture of traffic and record it: two pings, one request that is an attack, one that merely looks like one, and one that is the same attack in disguise.

#!/bin/bash
# Put a listener on the server so the attacker has something to talk to,
# start a capture, then send four things across the wire.
# NOTE: setsid, and a timeout on everything: a capture left running holds the
# terminal, and a capture that never fills its packet count waits for ever.
setsid timeout 25 ip netns exec server nc -l -k -p 8080 >/dev/null 2>&1 </dev/null &
sleep 1
setsid --wait timeout 18 ip netns exec server tcpdump -n -i vS -c 40 -w /root/traffic.pcap "icmp or tcp" >/dev/null 2>&1 </dev/null &
TD=$!
sleep 2
# 1. ordinary pings
ip netns exec attacker ping -c 2 -i 0.3 10.8.0.2 >/dev/null 2>&1
# 2. a directory traversal: the attack
printf 'GET /admin/../../etc/passwd HTTP/1.0\r\n\r\n' | timeout 5 ip netns exec attacker nc -w 3 10.8.0.2 8080 >/dev/null 2>&1
# 3. an ordinary page whose name happens to contain the word passwd
printf 'GET /help/reset-passwd HTTP/1.0\r\n\r\n' | timeout 5 ip netns exec attacker nc -w 3 10.8.0.2 8080 >/dev/null 2>&1
# 4. the same attack as 2, with the path written in base64
printf 'GET /YWRtaW4vLi4vLi4vZXRjL3Bhc3N3ZA== HTTP/1.0\r\n\r\n' | timeout 5 ip netns exec attacker nc -w 3 10.8.0.2 8080 >/dev/null 2>&1
sleep 1
wait $TD 2>/dev/null
munotes.in177

Practical 18: Intrusion Detection System

$ bash grab.sh
$ ls -l /root/traffic.pcap | awk '{print $9}'
/root/traffic.pcap
$ tcpdump -n -r /root/traffic.pcap 2>/dev/null | wc -l
28
$ tcpdump -n -r /root/traffic.pcap 2>/dev/null | head -2
11:38:22.600432 IP 10.8.0.1 > 10.8.0.2: ICMP echo request, id 43, seq 1, length 64
11:38:22.600512 IP 10.8.0.2 > 10.8.0.1: ICMP echo reply, id 43, seq 1, length 64

Step 2: write the rules

A Snort rule has two parts: a header saying which packets to look at, and options in brackets saying what to look for and what to call it.

alert tcp any any -> 10.8.0.2 8080 (msg:"Possible directory traversal"; content:"../"; sid:1000002; rev:1;)
  ^     ^   ^   ^   ^         ^     ^                                   ^                ^          ^
  |     |   |   |   |         |     the message the alert carries       what to look for |          revision
  |     |   |   |   |         destination port                                           rule id
  |     |   |   |   destination address
  |     |   |   direction: -> one way, <> both
  |     |   source address and port; `any` matches all
  |     protocol: tcp, udp, icmp or ip
  action: alert, log, pass, drop (drop only in inline mode)

Every field in that diagram is a likely question. Two more that matter: sid must be unique, and numbers from 1,000,000 upward are reserved for rules you write yourself; rev is the revision, raised whenever you change a rule so that logs can be matched to the version that produced them.

$ printf 'alert icmp any any -> 10.8.0.2 any (msg:"ICMP ping to the server"; itype:8; sid:1000001; rev:1;)\nalert tcp any any -> 10.8.0.2 8080 (msg:"Possible directory traversal"; content:"../"; sid:1000002; rev:1;)\nalert tcp any any -> 10.8.0.2 8080 (msg:"Password file mentioned"; content:"passwd"; sid:1000003; rev:1;)\n' > local.rules
$ cat local.rules
alert icmp any any -> 10.8.0.2 any (msg:"ICMP ping to the server"; itype:8; sid:1000001; rev:1;)
alert tcp any any -> 10.8.0.2 8080 (msg:"Possible directory traversal"; content:"../"; sid:1000002; rev:1;)
alert tcp any any -> 10.8.0.2 8080 (msg:"Password file mentioned"; content:"passwd"; sid:1000003; rev:1;)
munotes.in178

Practical 18: Intrusion Detection System

itype:8 is the ICMP type for an echo request, so the first rule sees pings going out and not the replies coming back.

Step 3: run it, and read the alerts

$ snort -q -A console -c local.rules -r /root/traffic.pcap -k none 2>&1 | sed 's/^[0-9/:.-]* *//'
[**] [1:1000001:1] ICMP ping to the server [**] [Priority: 0] {ICMP} 10.8.0.1 -> 10.8.0.2
[**] [1:1000001:1] ICMP ping to the server [**] [Priority: 0] {ICMP} 10.8.0.1 -> 10.8.0.2
[**] [1:1000003:1] Password file mentioned [**] [Priority: 0] {TCP} 10.8.0.1:33074 -> 10.8.0.2:8080
[**] [1:1000002:1] Possible directory traversal [**] [Priority: 0] {TCP} 10.8.0.1:33074 -> 10.8.0.2:8080
[**] [1:1000003:1] Password file mentioned [**] [Priority: 0] {TCP} 10.8.0.1:33082 -> 10.8.0.2:8080

Five alerts, and every one of them tells a story.

Two ICMP alerts, one per ping. The rule matched the echo requests and not the replies, exactly as itype:8 says it should.

One directory traversal alert, sid 1000002, on the connection carrying /admin/../../etc/passwd. That is the detection the practical is for: a real attack pattern found in real traffic by a rule you wrote.

Two "Password file mentioned" alerts, sid 1000003, and there is the problem. One is the attack. The other is the request for /help/reset-passwd, which is an ordinary page. The rule looks for the six letters passwd anywhere in the packet, and a legitimate URL contains them.

That second one is a false positive, and it is the commonest failure of a signature system. An analyst who sees a hundred of those a day stops reading them, and then the real one goes past unread. NIST SP 800-94 is blunt about this: tuning is not an optional refinement, it is what makes the system usable.

And one thing is missing from the list. The fourth request, the same attack with its path written in base64, raised nothing at all.

Step 4: tune the rule

The fix for the false positive is to make the pattern more specific: not the word, the whole path.

$ printf 'alert tcp any any -> 10.8.0.2 8080 (msg:"Password file access"; content:"/etc/passwd"; sid:1000004; rev:1;)\n' > tuned.rules
$ snort -q -A console -c tuned.rules -r /root/traffic.pcap -k none 2>&1 | sed 's/^[0-9/:.-]* *//'
[**] [1:1000004:1] Password file access [**] [Priority: 0] {TCP} 10.8.0.1:33074 -> 10.8.0.2:8080
$ snort -q -A console -c local.rules -r /root/traffic.pcap -k none 2>&1 | grep -c 1000003
2
$ snort -q -A console -c tuned.rules -r /root/traffic.pcap -k none 2>&1 | grep -c 1000004
1

Two alerts became one, and the one that remains is the attack. That is the whole of tuning, and the measurement, two against one, is what belongs in the observation table.

Note what tuning costs. The new rule would miss an attacker who wrote /etc/./passwd, or /etc//passwd, or who encoded a character. A narrower rule has fewer false positives and more false negatives, and choosing between them is a judgement about the site, not a fact about the rule.

munotes.in179

Practical 18: Intrusion Detection System

Step 5: what an IDS cannot see

Three limits, and the chapter has already demonstrated two of them.

Anything nobody has written a rule for. Signature detection finds known patterns. An attack nobody has seen goes past.

Anything transformed. The base64 request in step 3 is byte for byte a different string and raised nothing, and it is the same attack. Real evasion uses URL encoding, case changes, inserted null bytes and fragmentation, and it is why Snort has preprocessors that normalise traffic before the rules see it. A rule written against raw bytes with no normalisation is a rule that is trivially avoided.

Anything encrypted. This is the big one, and Practical 17 is the reason. A rule matching content:"/etc/passwd" sees that string only if it is on the wire in the clear. Send the same request over HTTPS and the IDS sees a TLS record and nothing else.

$ printf 'alert tcp any any -> any 443 (msg:"Traffic to a TLS port"; sid:1000005; rev:1;)\n' > tls.rules
$ snort -q -A console -c tls.rules -r /root/traffic.pcap -k none 2>&1 | sed 's/^[0-9/:.-]* *//' | wc -l
0

So the honest position, and the one to write in the journal: as more of the web moved to TLS, a network IDS lost most of its view. The answers used in practice are to terminate TLS at a proxy and inspect there, which raises its own problems, or to move the detection onto the host, where the data is in the clear because that is where it is used.

Step 6: clean up

$ ip netns delete attacker
$ ip netns delete server
$ ip netns list | wc -l
0

Procedure

  1. Create two namespaces joined by a veth pair and confirm they can reach each other.
  2. Put a listener on the server and capture traffic while sending: two pings, a directory traversal, a legitimate page whose name contains a suspicious word, and the same attack encoded.
  3. Write three rules: one ICMP, one for the traversal pattern, one for a word.
  4. Run Snort over the capture and read every alert, naming the rule that produced it.
  5. Identify the false positive and say which request caused it.
  6. Write a tuned rule, run it, and count the alerts before and after.
  7. Confirm that the encoded request raised nothing, and say why.
  8. Say what an IDS cannot see, and what is done about it.
  9. Delete the namespaces.

Observations

MeasuredValue
Hosts10.8.0.1 attacker, 10.8.0.2 server, two namespaces
Traffic generated2 pings, 3 HTTP requests
Rules written3, sids 1000001 to 1000003
Total alerts from those rules5
ICMP alerts2, one per echo request, replies not matched
Directory traversal alerts1, on the request containing ../
"Password file mentioned" alerts2, of which one is a false positive
The false positivethe request for /help/reset-passwd
Alerts from the tuned rule1
The base64-encoded attackno alert at all
Traffic to port 443 in the capturenone
munotes.in180

Practical 18: Intrusion Detection System

Result

Snort 2.9.20 was set up as a network intrusion detection system over a link between two hosts created as network namespaces. Three rules were written and read field by field, and run against a capture of five exchanges. They produced five alerts: two on the ICMP echo requests, one on a directory traversal in an HTTP request, and two on the word passwd, of which one was raised by a legitimate request for a page called /help/reset-passwd and was therefore a false positive. A tuned rule matching the whole path /etc/passwd instead of the word reduced those two alerts to one, the real attack. The same attack sent with its path written in base64 raised no alert at all, which demonstrates that a signature matching raw bytes is defeated by a trivial transformation, and the chapter records that an IDS sees nothing inside encrypted traffic.

Where marks are lost

Confusing detection with prevention. An IDS reports. An IPS blocks, and sits in the path rather than beside it.

A sid below 1,000,000. Those are reserved for the distributed rule sets. Use 1000001 upward for your own.

Not raising rev when you change a rule. Then a log cannot be matched to the rule that produced it.

Reporting only that a rule fired. An examiner wants the false positive too, and the tuning that removed it.

Writing a rule so broad that it fires on ordinary traffic. Two alerts and one of them wrong, as here, is a system that will be ignored within a week.

Writing a rule so narrow that a space defeats it. Tuning trades false positives for false negatives. Say which way you traded.

Claiming an IDS sees encrypted traffic. It sees that a TLS connection happened and nothing inside it.

Testing on traffic you made and nothing else. Say plainly that the capture is your own, on your own two hosts.

For the journal

Aim; IDS against IPS, and network-based against host-based, and signature against anomaly, as three short comparisons; the two hosts and how they were made; the capture script and what each of the four exchanges is; the annotated rule with every field named; the three rules; the five alerts with the rule that produced each; the false positive identified by the request that caused it; the tuned rule and the count before and after; the encoded request that raised nothing; the note on encrypted traffic; the clean-up; the observation table; the result.

munotes.in181

Practical 18: Intrusion Detection System

Quick revision

  • An IDS detects and reports; an IPS sits in the path and blocks.
  • Network-based watches a link; host-based watches one machine.
  • Signature detection finds known patterns; anomaly detection finds departures from normal and raises more false alarms.
  • A Snort rule is a header and options: action, protocol, source, direction, destination, then msg, content, sid, rev.
  • sid above 1,000,000 for your own rules; raise rev on every change.
  • itype:8 is an ICMP echo request.
  • A false positive is an alert on ordinary traffic. Here, content:"passwd" matched /help/reset-passwd.
  • Tuning narrows the pattern: two alerts became one, and the one left is the attack.
  • Narrower rules mean fewer false positives and more false negatives.
  • The same attack in base64 raised nothing. Normalise before matching, or be evaded.
  • An IDS cannot see inside TLS. Terminate at a proxy, or detect on the host.

Questions you must be able to answer

1. What is the difference between an IDS and an IPS? An IDS watches a copy of the traffic and reports what it finds. An IPS sits in the path of the traffic and can drop it. The detection is the same; the placement and the authority differ.

2. What are the two ways of deciding that something is an attack? Signature detection, which matches known patterns and is exact but blind to anything new; and anomaly detection, which learns normal behaviour and reports departures, which can find new attacks and raises far more false alarms.

3. Read out the parts of the rule you wrote. Action alert, protocol tcp, source any address and any port, direction one way, destination 10.8.0.2 port 8080, then the options: the message, the content to match, a unique sid and a revision.

4. Why must sid be above 1,000,000? Because lower numbers are reserved for the published rule sets, and a collision means two different rules with the same identity in your logs.

5. Your rule fired on /help/reset-passwd. What is that called and why did it happen? A false positive. The rule matched the six letters passwd anywhere in the packet, and an ordinary page name contains them.

6. How did you tune it, and what did it cost? By matching the whole path /etc/passwd instead of the word, which took the alerts from two to one. It costs coverage: the new rule misses /etc/./passwd or an encoded form of the same path.

7. The same attack in base64 raised no alert. Is that a bug? No. The rule matches bytes, and base64 is different bytes. It is why an IDS normalises traffic with preprocessors before the rules see it, and why a rule against raw bytes is easy to evade.

munotes.in182

Practical 18: Intrusion Detection System

8. What does an IDS see of an HTTPS session? That a TLS connection was made, to which address, when, and how much passed. Nothing of the contents.

9. So what is done about encryption? Either terminate TLS at a proxy and inspect there, which means the proxy holds everybody's traffic in the clear, or move the detection onto the host, where the data is already decrypted.

10. You get a hundred alerts a day and one is real. What is the problem and what is the fix? The problem is that nobody will read the hundredth one. The fix is tuning: narrow the rules that fire on ordinary traffic, measure the count before and after, and accept that some coverage is traded for it.

munotes.in183

The rest of this subject

These notes are cut from the University's printed syllabus. Open the syllabus itself for the same subject.

Issue
Done!