04 July, 2009
Although the media blitz surrounding the
Conficker worm
has died down, the worldwide computing infrastructure that the worm has cobbled
together still exists and remains under the control of its masters. The resulting
botnet is an impressive demonstration of distributed computing control and
recoverability. Many organizations - from companies to governments - would be
envious of such automation. Most likely the botnet is being used as a money making
machine by renting out "botnet time" to criminals who then use it for their own purposes.
New Scientist has a
good summary of the Conficker saga, and includes a discussion of
its switch from HTTP to a peer-to-peer module for communications and updates. Even
though Conficker has perhaps not yet been used to issue DoS attacks against high
profile sites, it has had measurable impacts such as leaving Manchester
unable to
issue parking tickets and Microsoft announcing a
$250,000 bounty
on the Conficker authors. On the defense side, the
Conficker Working Group has produced some nice
infection
distribution maps and Nmap added
Conficker scan detection
based on an excellent
paper
written by Tillmann Werner and Felix Leder.
In the context of iptables and fwsnort, the goal is to give Linux systems the ability
to detect and interfere network traffic associated with Conficker (at least as much
as possible), and this process starts with Snort rules from the
Emerging Threats
rule set. There are currently six active Snort rules designed to detect Conficker in
the Emerging Threats set, and an additional four that have been commented out. The six
active rules so far detect the Conficker.A and Conficker.B variants, but hopefully more
rules will become available as better detection techniques are developed.
Now, how does fwsnort do with translating the six Emerging Threats rules? Let's
find out with the command below. This uses the
--include-regex feature
to restrict fwsnort to just those rules that contain the string "conficker", and
we also add the new
--include-perl-trigger argument (to be released in
fwsnort-1.0.7) that builds a perl command to mimic the application layer data
in each Snort rule. By combining this perl command with netcat, it is possible
to test whether the iptables policy built by fwsnort properly detects attacks.
Finally, we also use the
--ipt-reject argument to have iptables drop any
packet that matches the Conficker signatures and reset the connection at the
same time:
# fwsnort --include-regex conficker --include-re-caseless --snort-rfile /etc/fwsnort/snort_rules/emerging-all.rules --include-perl-triggers --ipt-reject | tail -n 4
[+] Generated iptables rules for 3 out of 6 signatures: 50.00%
[+] Logfile: /var/log/fwsnort.log
[+] iptables script: /etc/fwsnort/fwsnort.sh
Ok, so three out of the six signatures (I'm using 'signature' and 'rule'
interchangeably in this blog post) converted properly to iptables rules.
Those that did not convert contain elements such as
pcre and
threshold
that are not currently supported by fwsnort.
Below is an example of one Snort signature that did convert correctly. This is
rule ID
2009201, and it detects shellcode directed at TCP/445 from Conficker.B:
alert tcp $EXTERNAL_NET any -> $HOME_NET 445 (msg:"ET CURRENT_EVENTS Conficker.b Shellcode"; flow:established,to_server; content:"|e8 ff ff ff ff c2|_|8d|O|10 80|1|c4|Af|81|9MSu|f5|8|ae c6 9d a0|O|85 ea|O|84 c8|O|84 d8|O|c4|O|9c cc|Ise|c4 c4 c4|,|ed c4 c4 c4 94|&<O8|92|\;|d3|WG|02 c3|,|dc c4 c4 c4 f7 16 96 96|O|08 a2 03 c5 bc ea 95|\;|b3 c0 96 96 95 92 96|\;|f3|\;|24 |i|95 92|QO|8f f8|O|88 cf bc c7 0f f7|2I|d0|w|c7 95 e4|O|d6 c7 17 cb c4 04 cb|{|04 05 04 c3 f6 c6 86|D|fe c4 b1|1|ff 01 b0 c2 82 ff b5 dc b6 1f|O|95 e0 c7 17 cb|s|d0 b6|O|85 d8 c7 07|O|c0|T|c7 07 9a 9d 07 a4|fN|b2 e2|Dh|0c b1 b6 a8 a9 ab aa c4|]|e7 99 1d ac b0 b0 b4 fe eb eb|"; reference:url,www.honeynet.org/node/388; reference:url,doc.emergingthreats.net/2009201; reference:url,www.emergingthreats.net/cgi-bin/cvsweb.cgi/sigs/CURRENT_EVENTS/CURRENT_Conficker; classtype:trojan-activity; sid:2009201; rev:4;)
Here is the equivlent iptables command built by fwsnort and included in the
/etc/fwsnort/fwsnort.sh script. Note the usage of the
FWSNORT_FORWARD_ESTAB
chain which is reserved for packets that are part of established TCP connections:
$IPTABLES -A FWSNORT_FORWARD_ESTAB -p tcp --dport 445 -m string --hex-string "|e8ffffffffc2|_|8d|O|1080|1|c4|Af|81|9MSu|f5|8|aec69da0|O|85ea|O|84c8|O|84d8|O|c4|O|9ccc|Ise|c4c4c4|,|edc4c4c494|&<O8|923bd3|WG|02c3|,|dcc4c4c4f7169696|O|08a203c5bcea953bb3c096969592963bf33b24|i|9592|QO|8ff8|O|88cfbcc70ff7|2I|d0|w|c795e4|O|d6c717cbc404cb|{|040504c3f6c686|D|fec4b1|1|ff01b0c282ffb5dcb61f|O|95e0c717cb|s|d0b6|O|85d8c707|O|c0|T|c7079a9d07a4|fN|b2e2|Dh|0cb1b6a8a9abaac4|]|e7991dacb0b0b4feebeb|" --algo bm -m comment --comment "sid:2009201; msg:ET CURRENT_EVENTS Conficker.b Shellcode; classtype:trojan-activity; reference:url,www.honeynet.org/node/388; rev:4; FWS:1.0.6;" -j LOG --log-ip-options --log-tcp-options --log-prefix "[3] DRP SID2009201 ESTAB "
Because the pattern in the above signature is longer than 128 bytes, we'll increase
the value of the
MAX_STRING_LEN variable to 256 in the /etc/fwsnort/fwsnort.conf
file. With that done, let's execute the
/etc/fwsnort/fwsnort.sh script now and
see how iptables handles such traffic on the wire:
# /etc/fwsnort/fwsnort.sh
[+] Adding emerging-all rules:
iptables v1.4.1.1: STRING too long `|e8ffffffffc2|_|8d|O|1080|1|c4|Af|81|9MSu|f5|8|aec69da0|O|85ea|O|84c8|O|84d8|O|c4|O|9ccc|Ise|c4c4c4|,|edc4c4c494|&<O8|923bd3|WG|02c3|,|dcc4c4c4f7169696|O|08a203c5bcea953bb3c096969592963bf33b24|i|9592|QO|8ff8|O|88cfbcc70ff7|2I|d0|w|c795e4|O|d6c717cbc404cb|{|040504c3f6c686|D|fec4b1|1|ff01b0c282ffb5dcb61f|O|95e0c717cb|s|d0b6|O|85d8c707|O|c0|T|c7079a9d07a4|fN|b2e2|Dh|0cb1b6a8a9abaac4|]|e7991dacb0b0b4feebeb|'
Try `iptables -h' or 'iptables --help' for more information.
Ok, that is disappointing. It turns out that iptables currently enforces a 128-byte
maximum on all strings supplied to the string match extension for inspecting payload
data. Normally this is not a problem since the individual patterns in most Snort
rules are typically less than 128 bytes, but in this case we'd like to work around
this limitation. To do so requires that we patch and recompile the
xt_string
kernel module (assuming xt_string is configured as a module) with the following
patch:
# git diff
diff --git a/include/linux/netfilter/xt_string.h b/include/linux/netfilter/xt_string.h
index 8a6ba7b..afc60a2 100644
--- a/include/linux/netfilter/xt_string.h
+++ b/include/linux/netfilter/xt_string.h
@@ -1,7 +1,7 @@
#ifndef _XT_STRING_H
#define _XT_STRING_H
-#define XT_STRING_MAX_PATTERN_SIZE 128
+#define XT_STRING_MAX_PATTERN_SIZE 256
#define XT_STRING_MAX_ALGO_NAME_SIZE 16
enum {
@@ -15,7 +15,7 @@ struct xt_string_info
u_int16_t to_offset;
char algo[XT_STRING_MAX_ALGO_NAME_SIZE];
char pattern[XT_STRING_MAX_PATTERN_SIZE];
- u_int8_t patlen;
+ u_int16_t patlen;
union {
struct {
u_int8_t invert;
With the new xt_string module loaded let's execute the fwsnort.sh script once
again:
# /etc/fwsnort/fwsnort.sh
[+] Adding emerging-all rules:
Rules added: 12
[+] Finished.
Ah, that's better. The fwsnort iptables policy loaded properly in the running
kernel. Now, let's use the perl trigger command along with netcat to send data
across the wire that should match the signature. The trigger itself can be
found in the
/etc/fwsnort/fwsnort.sh script. First, we fire up a netcat
server on TCP port 445 on a target system which is protected by another system
running the fwsnort iptables policy, and then with the perl trigger we send
bytes that match the Conficker.B shell code signature across the wire to the
target. The complete perl command is listed below even though it certainly is
obtuse looking. You can see how the bytes it is printing match the content
strings in the original signature:
[target]# nc -l -p 445
[attacker]$ perl -e 'print "\xe8\xff\xff\xff\xff\xc2_\x8dO\x10\x801\xc4Af\x819MSu\xf58\xae\xc6\x9d\xa0O\x85\xeaO\x84\xc8O\x84\xd8O\xc4O\x9c\xccIse\xc4\xc4\xc4,\xed\xc4\xc4\xc4\x94&<O8\x92\x3b\xd3WG\x02\xc3,\xdc\xc4\xc4\xc4\xf7\x16\x96\x96O\x08\xa2\x03\xc5\xbc\xea\x95\x3b\xb3\xc0\x96\x96\x95\x92\x96\x3b\xf3\x3b\x24i\x95\x92QO\x8f\xf8O\x88\xcf\xbc\xc7\x0f\xf72I\xd0w\xc7\x95\xe4O\xd6\xc7\x17\xcb\xc4\x04\xcb{\x04\x05\x04\xc3\xf6\xc6\x86D\xfe\xc4\xb11\xff\x01\xb0\xc2\x82\xff\xb5\xdc\xb6\x1fO\x95\xe0\xc7\x17\xcbs\xd0\xb6O\x85\xd8\xc7\x07O\xc0T\xc7\x07\x9a\x9d\x07\xa4fN\xb2\xe2Dh\x0c\xb1\xb6\xa8\xa9\xab\xaa\xc4]\xe7\x99\x1d\xac\xb0\xb0\xb4\xfe\xeb\xeb"' |nc 10.1.1.1 445
The fwsnort iptables policy has reset the connection, and the following iptables
log message was also produced:
Jul 4 13:23:18 fwsnort kernel: [10966.350782] [2] REJ SID2009201 ESTAB IN=lo OUT= MAC=AB:00:00:AB:00:00:AB:00:00:AB:00:00:08:00 SRC=192.168.10.1 DST=10.1.1.1 LEN=244 TOS=0x00 PREC=0x00 TTL=64 ID=5976 DF PROTO=TCP SPT=49053 DPT=445 WINDOW=513 RES=0x00 ACK PSH URGP=0 OPT (0101080A0028B05B0028B058)
Of course, the best defense against Conficker is to patch Windows systems against
the MS08-067 vulnerability, and to use Nmap to scan for systems that are already
infected. Those that are should be completely reimaged.