Linux Firewalls - Michael Rash [44]
The iptables string match extension allows packet payload data to be searched for matching strings using the fast Boyer-Moore string search algorithm (see http://www.cs.utexas.edu/users/moore/best-ideas/string-searching). This algorithm is commonly used by intrusion detection systems, including the champion open source IDS Snort (http://www.snort.org), because of its ability to quickly match strings within payload data.
Note
String matching has been available in iptables since the 2.4 kernels, but an architectural change with respect to how packet data structures were stored within kernel memory (sk_buff structures were allowed to span non-contiguous memory) broke the string matching feature in kernels 2.6.0 through 2.6.13.5. The string match extension was rewritten for the 2.6.14 kernel, and it has been included within the kernel ever since.
Observing the String Match Extension in Action
In order to test the iptables string matching feature, we construct a simple iptables rule that uses the string match extension to verify that it functions as advertised. The following rule uses the iptables LOG target to generate a syslog message when the string "tester" is sent to a Netcat server that is listening on TCP port 5001. (We need the ACCEPT rule so that the default iptables policy from Chapter 1 will allow the establishment of the TCP connection from an external source.)
[iptablesfw]# iptables -I INPUT 1 -p tcp --dport 5001 -m string --string "tester" ❶
--algo bm -m state --state ❷ESTABLISHED -j LOG --log-prefix "tester"
[iptablesfw]# iptables -I INPUT 2 -p tcp --dport 5001 -j ACCEPT
Notice at ❶ above the --algo bm command-line argument to iptables. The string match extension is built on top of a text-searching infrastructure in the Linux kernel (located within the linux/lib directory in the kernel sources). It supports several different algorithms, including the Boyer-Moore string search algorithm (the bm above), and the Knuth-Morris-Pratt string-searching algorithm (kmp).[27]
The -m state --state ESTABLISHED command-line arguments at ❷ restrict the string match operation to packets that are part of established TCP connections, and this means that someone cannot cause the iptables rule to match on a spoofed packet from an arbitrary source address—a bidirectional connection must be established.
We'll use Netcat to spawn a TCP server that listens locally on TCP port 5001, and then we'll use it again from the ext_scanner system as a client to send the string "tester" to the server:
[iptablesfw]$ nc -l -p 5001
[ext_scanner]$ echo "tester" | nc 71.157.X.X 5001
Now we'll examine the system logfile for evidence that the string match rule generated the appropriate syslog message:
[iptablesfw]# tail /var/log/messages | grep tester
Jul 11 04:19:14 iptablesfw kernel: tester IN=eth0 OUT= MAC=00:13:d3:38:b6:e4:00:30:
48:80:4e:37:08:00 SRC=144.202.X.X DST=71.157.X.X LEN=59 TOS=0x00 PREC=0x00
TTL=64 ID=41843 DF PROTO=TCP SPT=55363 DPT=5001 WINDOW=92 RES=0x00 ACK PSH URGP=0
Notice the log prefix tester in bold above. By examining the remaining portion of the log message, we can confirm that the associated packet was sent from the ext_scanner system to our Netcat server listening on TCP port 5001.
Note
We could have achieved the same result as above by using telnet (running in line mode) as our client instead of Netcat, so that the entire string "tester" is contained within a single packet. This works well enough, but telnet has some serious limitations: It is unable to interact with UDP servers, and it is also difficult to use telnet to generate arbitrary non- printable characters.
Matching Non-Printable Application Layer Data
When running as a client, Netcat can interact with UDP servers just as easily as it can with those that listen on TCP sockets. When combined with a little Perl, Netcat can send arbitrary bytes across the wire, including ones that cannot be represented as printable ASCII characters. This feature is important because many exploits utilize non-printable bytes