cipherdyne.org

Michael Rash, Security Researcher



Intrusion Detection and iptables    [Summary View]

IDS signature matching with iptables, psad, and fwsnort

IDS signature matching with iptables, psad, and fwsnort The UK's Unix & Open Systems User Group has re-printed an article I wrote originally for the December, 2007 security issue of USENIX ;login: Magazine The article is entitled "IDS signature matching with iptables, psad, and fwsnort" and concentrates on how to use the iptables infrastructure in the Linux kernel as a source of intrusion detection data. That is, iptables offers many features (such as application layer string matching) that allow a significant fraction of Snort rules to be converted into iptables rules, and fwsnort automates the conversion process. The end result is an iptables policy that is looking for evidence of malicious traffic. Also covered in the article is the concept of log analysis with an emphasis on passive OS fingerprinting. The completeness of the iptables logging format - which even includes the options portion of the TCP header when the --log-tcp-options argument is given on the iptables command line when building a LOG rule - allows psad to run the same algorithm that p0f uses to passively fingerprint remote operating systems.

In other news, Carla Schroder has written an article on psad for Enterprise Networking Planet. She recommends running psad alongside Snort, which falls nicely within the principle of defense-in-depth in order to maintain a strong defensive stance. Also, Noah Schiffman has written an article on port knocking for Network World. He mentions the usage of port knocking within some malware applications as an authentication mechanism, and he also touches on Single Packet Authorization.

Thwarting Distributed SSH Brute Force Attempts

Thwarting Distributed SSH Brute Force Attempts The SANS Internet Storm Center has an interesting diary entry that discusses a set of distributed brute force attempts against SSHD originating from a specific Class C subnet 58.147.10.0/24. According to the diary entry, a random selection of IP addresses within this subnet (which is owned by an organization in Thailand) are probing for listening SSH daemons on the open Internet, but each IP address is limiting the number of probes to two. Presumably this is to fly beneath the radar of any threshold-based detection mechanisms that might automatically block the attempts to communicate with SSHD.
     After rummaging around in my iptables logfiles, I noticed the following two log entries that show exactly two SYN packets from the IP 58.147.10.209 and destined for one of my systems:
Jun  3 14:55:06 minastirith kernel: DROP IN=eth0 OUT= \
MAC=00:13:d3:38:b6:e4:00:90:1a:a0:1c:ec:08:00 SRC=58.147.10.209 \
DST=71.N.N.N LEN=60 TOS=0x00 PREC=0x00 TTL=44 ID=11651 DF PROTO=TCP \
SPT=57473 DPT=22 WINDOW=5840 RES=0x00 SYN URGP=0 \
OPT (020405780402080A7CCF5BC50000000001030302)
Jun  3 14:55:09 minastirith kernel: DROP IN=eth0 OUT= \
MAC=00:13:d3:38:b6:e4:00:90:1a:a0:1c:ec:08:00 SRC=58.147.10.209 \
DST=71.N.N.N LEN=60 TOS=0x00 PREC=0x00 TTL=44 ID=11653 DF PROTO=TCP \
SPT=57473 DPT=22 WINDOW=5840 RES=0x00 SYN URGP=0 \
OPT (020405780402080A7CCF677D0000000001030302)
These two packets date back to June of last year, so the 58.147.10.0/24 network has apparently been active for quite some time. So, beyond the whois information mentioned in the ISC diary entry, can we tell anything more about our friend at 58.147.10.209? Because I always use the --log-tcp-options command line argument when building my iptables LOG rules, we have nice hex dumps included in the log messages above that represent the options portion of the TCP header. Having this information is necessary in order to passively fingerprint the remote TCP stack with p0f. The psad project re-implements the p0f algorithm over iptables log messages - p0f requires raw packet data acquired via libpcap - so what does psad have to say about the remote TCP stack?
[minastirith]# psad -A -m /var/log/messages --restrict-ip 58.147.10.209
[+] p0f(): 58.147.10.209 len: 60, frag_bit: 1, ttl: 44, win: 5840
[+] MSS: 1400, SACK, Timestamp: 2093964229, NOP, Win Scale: 2,
    Could not match 58.147.10.209 against any p0f signature.
Oh well, that is unfortunate. So, p0f does not seem to have a fingerprint that can characterize the remote TCP stack. I also looked through the passive OS fingerprinting database included with the ettercap project, but no luck there either. This was a manual process though because psad does not yet support the format of the fingerprints in ettercap, but this will be supported in the next release.
     In the meantime, the discussion in the diary entry advocates limiting the set of IP addresses that are allowed to talk to the SSH daemon, but ends with a comment stating that this is not always possible. I agree with this comment, and this is highlighted whenever you administer a system and you need access to SSHD from unpredictable source addresses (such as when travel is involved). A robust solution is to deploy Single Packet Authorization with a default-drop packet filter. Why let arbitrary source IP addresses communicate with your SSH daemon?

iptables vs. Check Point Firewalls

iptables vs. Check Point Firewalls In October, 2003, I wrote an article entitled "Firewalls: Doing it Yourself" for Information Security Magazine. It looks like the original link to the article has been taken down, so I have mirrored it here for anyone who would like to read it. This article is now four years old, and needs to be updated to cover new features in firewalls provided both by the Linux community (iptables) and by Check Point Software Technologies. A few things stand out in my mind since writing the original article:
  • It appears as though Vyatta is providing an open source routing stack as a competitor to Cisco's products, and this is serious competition to the Zebra project mentioned in the article. Zebra is no longer actively developed as it has been reincarnated as the Quagga Routing Suite.
  • These days, application layer inspection in firewall products is much more important as the number of application security vulnerabilities shows no sign of letting up, and high profile incidents of everything from phishing attacks, client side exploits, and identity theft continue to make the news. The iptables string match extension is a strong open source answer to providing application layer inspection for iptables firewalls.
  • Proprietary intrusion prevention systems (such as the Enterasys Dragon IDS/IPS - disclaimer: I work for Enterasys) are building in features that place more emphasis on filtering policies; a job that is typically done with a firewall or other filtering device that is designed to enforce policy.
  • The open source community has continued to make meteoric strides in the last four years, and now purchasing support for open source software is easier with large corporate backers than it was four years ago. Also, open source software is now understood much better by non-techies as an infrastructure that can greatly assist just about any organization, and this applies to security software as well as more traditional software.

Trailing Spaces and iptables LOG Prefixes

Trailing Spaces and iptables LOG Prefixes The iptables firewall offers verbose logging capabilities that generate syslog messages for IP packets, and these log messages include the header field values for nearly every interesting field in both the network and transport layer headers. The iptables logging function is implemented by two piece of code; one is the iptables userland binary that accepts a rule specified by the user with the LOG target, and the other is the in-kernel code that generates the appropriate klogd message when a packet matches a LOG rule within the kernel. The userland code that handles LOG rules is implemented by the file iptables/extensions/libipt_LOG.c in the iptables sources, and the kernel code that implements the LOG target is implemented by the file linux/net/ipv4/netfilter/ipt_LOG.c in the kernel sources.

A useful feature is that iptables LOG rules accept up to a 29-character string that is set by the user in order to add descriptive information to a log message when a packet triggers a LOG match. This is used by many open source projects to make iptables logs more effective when packets are logged. For example, fwsnort creates log prefixes such as "[1] REJ SID2180 ESTAB" when the Snort rule ID 2180 "P2P BitTorrent announce request" is detected by the fwsnort iptables policy. This prefix contains the rule number (1 in this case), shows that the TCP connection was terminated with a RST (indicated by the REJ string), and the original signature match took place over an established TCP connection (indicated by ESTAB).

This is all fine, but there is one minor wrinkle that affects many open source projects based around iptables: the LOG target does not enforce a trailing space character on log prefixes. This results in an unfortunate situation where the user can cause iptables to create log messages that break its own notion of tokens that define the shape of the log messages. For example, here is an iptables rule along with its resulting log message when a TCP SYN packet is sent to port 5001:
# iptables -I INPUT 1 -p tcp --dport 5001 -j LOG --log-prefix "TEST"

Aug 28 22:04:43 minastirith kernel: TESTIN=eth0 OUT= \
MAC=00:13:d3:38:b6:e4:00:13:46:c2:60:44:08:00
SRC=192.168.10.3 DST=192.168.10.1 LEN=60 TOS=0x10 PREC=0x00 \
TTL=63 ID=56577 DF PROTO=TCP SPT=53479 DPT=5001 WINDOW=5840 \
RES=0x00 SYN URGP=0
Note the "TESTIN=eth0" string above. This string only exists because neither the ipt_LOG.c code distributed with the Linux kernel nor the libipt_LOG.c distributed with iptables adds a trailing space after the "TEST" string. If the rule had been built with "--log-prefix "TEST " (note the trailing space), then the log message would not break its own syntax.

Patches to enforce this behavior for this have been proposed before on the Netfilter development list, but they have not been accepted. The reason given is that the Netfilter maintainers don't want to break any parsers that are already coded to handle log prefixes without the space.

I understand this concern, but I respectfully submit that most major open source projects that build iptables policies add in the space already, and any parser that is worth its salt would therefore have to handle both cases. That is, parsers have to handle log prefixes that contain the trailing space and prefixes that omit it. In addition, all three of the shorewall, ipcop, and fwbuilder projects build in the trailing space to the log prefixes they generate, so parsers are already more likely to handle prefixes with the space than without it because these are popular projects for building iptables policies.

From now on, I will maintain a patch as a part of the psad project that modifies the iptables binary such that if the last character in a log prefix is not a space, then the code will add one automatically. A similar strategy could be implemented in the kernel, but it seems that a less invasive and a more easily deployed solution is to patch the iptables userland binary. A patch that implements this for iptables-1.3.8 has been checked into the psad source tree, and you can download it here. You can apply it as follows, and then recompile and install iptables:
$ cd iptables-1.3.8
$ wget -O iptables-1.3.8_LOG_prefix_space.patch \
http://trac.cipherdyne.org/trac/psad/browser/psad/trunk/patches\
/iptables-1.3.8_LOG_prefix_space.patch?format=txt
$ patch -p0 < iptables-1.3.8_LOG_prefix_space.patch
patching file extensions/libipt_LOG.c
With this patch, all of your existing iptables scripts will function exactly as they always have; no additional space is added for any iptables log prefix that already has a trailing space - only those that are missing the space will be changed. It is my hope that the Netfilter project will incorporate this patch into iptables.

Enhancing Inline IPS Performance with Kernel String Matching

Digg Speeding_up_snort_inline_IPS Enhancing Inline IPS Performance The iptables QUEUE and NFQUEUE targets are used by both open source and commercial Intrusion Prevention Systems. These targets allow a userspace process (the IPS in this case) to acquire packet data from the Linux kernel via a netlink socket and set verdicts on whether packets should be forwarded only after the IPS has sent the packets through its detection engine. This can provide a effective means from protecting other systems from attack (subject to the usual concerns over false positives).

Using iptables provides a flexible means for placing a QUEUE rule within an existing iptables policy. For example, if you are not running a DNS server behind an iptables firewall, then you can use the DROP target against any attempts to communicate with a DNS server before sending such packets to a userspace IPS - which would needlessly place additional load on the CPU when such traffic can just be dropped from within the kernel directly before it ever hits the QUEUE rule:
# iptables -A FORWARD -p udp --dport 53 -j DROP
# iptables -A FORWARD -j QUEUE
This is a nice consequence, but is only possible in this case because there is no internal DNS server to attack in the first place. What about using facilities provided by iptables to reduce the packet load that is queued to a userspace IPS for servers that do exist? Say, for a web server?

An IPS such as snort_inline can be deployed with a large signature set, and most Snort signatures use the content or uricontent keywords to search packet application layer data for malicious content. In the context of snort_inline, usually the QUEUE or NFQUEUE rule is the default rule in the FORWARD chain - this ensures that snort_inline inspects all packets before they are forwarded through the system. So, you could say the iptables policy has a "default QUEUE stance".

However, by using the iptables string match extension and an iptables policy built by fwsnort, we can change the "default QUEUE stance" to "only QUEUE packets that match a Snort content field". The resulting performance gain can be substantial as we will see below. Fwsnort accomplishes this by parsing the Snort signature set that is deployed in snort_inline, and then building an iptables policy that makes heavy use of the string match extension to ACCEPT all packets in the FORWARD chain that do not match any of the content fields in the signature set, and QUEUE those that do. In general, this greatly reduces the number of packets that have to be queued to snort_inline since (usually) most traffic is not malicious.

As a simple example, consider the following Snort signature:
alert tcp any any -> any any (msg:"fwsnort download"; \
content:"fwsnort/download"; classtype:web-application-attack; \
sid:12325678; rev:1;)
This signature is for illustration purposes only and is written just to force snort_inline to inspect all TCP packets for the string "fwsnort/download". With this signature deployed in snort_inline on one of my systems (an old PIII with 100Mb Ethernet interfaces running the 2.6.20.3 kernel), I measured the following throughput with netperf. This test used a default QUEUE rule in iptables, so every TCP packet is queued to snort_inline:
# netperf -v 2 -L 192.168.50.1 -H 192.168.50.2
TCP STREAM TEST from 192.168.50.1 (192.168.50.1) port 0 AF_INET \
to 192.168.50.2 (192.168.50.2) port 0 AF_INET
Recv   Send    Send
Socket Socket  Message  Elapsed
Size   Size    Size     Time     Throughput
bytes  bytes   bytes    secs.    10^6bits/sec

 87380  16384  16384    10.02      60.07

Alignment      Offset         Bytes    Bytes       Sends Bytes   Recvs
Local  Remote  Local  Remote  Xfered   Per                Per
Send   Recv    Send   Recv             Send (avg)         Recv (avg)
  8       8      0       0 7.524e+07  16384.33      4592 1444.75 52076

Maximum
Segment
Size (bytes)
  1448
The throughput number above indicates that netperf was able to achieve 60.07 Mb/sec over the life of the 10 second test. Now, let's use fwsnort to convert the Snort signature into an equivalent iptables rule, and deploy it:
# fwsnort --snort-sid 12325678 --QUEUE
[+] Parsing Snort rules files...
[+] Found sid: 12325678 in test.rules
    Successful translation.

[+] Logfile: /var/log/fwsnort.log
[+] Snort rule set directory for rules to be queued to userspace:
    /etc/fwsnort/snort_rules_queue
[+] iptables script: /etc/fwsnort/fwsnort.sh
# /etc/fwsnort/fwsnort.sh
[+] Adding test rules.
    Rules added: 2
[+] Finished.
Now, executing the netperf throughput test generates the following result:
# netperf -v 2 -L 192.168.50.1 -H 192.168.50.2
TCP STREAM TEST from 192.168.50.1 (192.168.50.1) port 0 AF_INET \
to 192.168.50.2 (192.168.50.2) port 0 AF_INET
Recv   Send    Send
Socket Socket  Message  Elapsed
Size   Size    Size     Time     Throughput
bytes  bytes   bytes    secs.    10^6bits/sec

 87380  16384  16384    10.01      94.11

Alignment      Offset         Bytes    Bytes       Sends  Bytes  Recvs
Local  Remote  Local  Remote  Xfered   Per                Per
Send   Recv    Send   Recv             Send (avg)         Recv (avg)
    8       8      0       0 1.178e+08  16384.74   7189   1440.01 81798

Maximum
Segment
Size (bytes)
  1448
So, in this test we achieved 94.11 Mb/sec sustained throughput - that's about a 57% speed increase!

This may sound good, but as always there are some tradeoffs. First, because this strategy causes iptables to only selectively queue packets to userspace, snort_inline does not have the opportunity inspect an entire stream. This implies that the stream preprocessor needs to be disabled since otherwise signatures with the flow keyword will never match. Secondly, because the preliminary signature match is performed by iptables, taking into account application layer encodings (such as URL encoding used in web servers) is not possible. This results in a reduced ability to detect attacks. In some cases however, performance requirements may override these considerations. Also, some attacks do not need to bother with attempts at obfuscation because the target environment is so rich.

Significant work needs to be performed to validate this as a viable strategy for increasing IPS performance, but these preliminary results are encouraging. On a final note, this strategy is applicable to any IPS that makes use of the iptables queuing mechanism - not just snort_inline.

Also, thanks are in order to Hank Leininger of KoreLogic Security for suggesting the combination of the QUEUE target and string matching as a way to speed up inline Snort implementations at a talk I gave about Linux Firewalls at ShmooCon 2007. I implemented the --QUEUE and --NFQUEUE targets in fwsnort-1.0 as a result of meditating on this for a while.

Pablo Neira Ayuso Added to Netfilter Core Team

Pablo Neira Ayuso Added to Netfilter Core Team The Netfilter Project has added a new core team member, Pablo Neira Ayuso according to the following email which was posted by Yasuyuki Kozaka to the Netfilter development mailing list:

The Netfilter Core Team is proud to announce the addition of Pablo Neira Ayuso as a new member. He has repeatedly demonstrated high insight and coding standards, and has already been responsible for several parts of the codebase, especially ctnetlink, conntrack and conntrackd. By joining the Core Team, Pablo will definitely help advance the development of the Netfilter project to a higher level.

Welcome Pablo!

This is an excellent development as he is technical editor for my upcoming book "Linux Firewalls: Attack Detection and Response".

Visualizing Honeynet Project iptables Log Data

Visualizing Honeynet iptables Data Security visualization is becoming increasingly important as mountains of security data generated by security software and devices continues to grow. Raffael Marty has launched the security visualization portal secviz.org where people can upload graphs of security data and discuss what they mean. A key piece of software that can be used to generate link graphs of security data is the AfterGlow project, which accepts CSV-formatted input. With the 2.0 release of psad, I have added several --CSV command line arguments so that psad can generate output that is compatible with AfterGlow. By combining this capability with psad's forensics mode, it is possible to generate some interesting graphs of iptables log data provided by the Honeynet Project. This data is part of the Scan 34 challenge made to the security community in which live data from a Honeynet is analyzed for evidence of malicious activity and compromises. By visualizing some of this data with psad and AfterGlow, it is easy to see outbound SSH and IRC connections originating from one of the Honeynet systems (indicating a successful compromise), and the graph of the Nachi worm is eye catching. If you run iptables on a Linux system, you too can use psad and AfterGlow to create graphs of your iptables log files. You might turn up some interesting relationships w.r.t. how your systems communicate on the network, and how they are attacked.

Linux Kernel String Match Bugfix

I have finally gotten my name into the ChangeLog for the Linux Kernel by fixing an initialization bug in the kernel portion of the Netfilter string match extension. This fix appears in kernel version 2.6.18, and here is the ChangeLog entry:
commit 3ffaa8c7c0f884171a273cd2145b8fbbf233ba22
Author: Michael Rash <mbr@cipherdyne.org>
Date:   Tue Aug 22 00:45:22 2006 -0700

    [TEXTSEARCH]: Fix Boyer Moore initialization bug

    The pattern is set after trying to compute the prefix table, which tries
    to use it. Initialize it before calling compute_prefix_tbl, make
    compute_prefix_tbl consistently use only the data from struct ts_bm
    and remove the now unnecessary arguments.

    Signed-off-by: Michael Rash <mbr@cipherdyne.org>
    Signed-off-by: Patrick McHardy <kaber@trash.net>
    Signed-off-by: David S. Miller <davem@davemloft.net>

Netfilter String Match 64-bit Bugfix

Netfilter String Match 64-bit Bugfix The 2.6.16.6 release of the Linux kernel fixes a bug in the "textsearch" (linux/lib/textsearch.c) portion of the kernel when running on 64-bit processors, compliments of Pablo Neira Ayuso. The Netfilter string match extension depends on the textsearch infrastructure, so if you are running fwsnort on a 64-bit processsor then you will need to upgrade to at least the 2.6.16.6 kernel.

The Netfilter String Match Extension is back!

The Netfilter String Match Extension is back! The Fwsnort project translates Snort rules into equivalent Netfilter rules in the Linux kernel, and relies heavily on the Netfilter string match extension to match application layer data against malicious content strings. The string match extension is available once again with the release of the 2.6.14 Linux kernel (it was not available in any 2.6.x kernel until now). If you want to be able to run a decent percentage of Snort rules directly within the Linux kernel without having to run Snort at all, download Fwsnort!