|
IDS vendors have made tremendous gains in defeating IDS evasion techniques within the past two years, especially where string matching and string obfuscation is concerned. Evasion techniques that are network based are not as easy for an IDS to defend against as string obfuscation techniques. These network level evasion techniques were first brought to the forefront in the landmark 1998 research paper "Insertion, Evasion and Denial of Service: Eluding Network Intrusion Detection" by Thomas Ptacek and Timothy Newsham[1]. The paper details specific network level problems specifically with fragmentation and session re-assembly. Recently tools such as Whisker by RainForestPuppy[2] and Nessus[3] the vulnerability scanner have implemented session splicing techniques. Many techniques outlined by Ptacek and Newsham are common to both fragmentation and session splicing. Session splicing, because it involves a session is useful only when the payload can be delivered over multiple packets where fragmentation can be used with all protocols. This paper will focus on IDS evasion using session splicing timeouts and to a lesser degree rule alerting and first exit problems that session splicing can create.
The basic premise behind session splicing is to deliver the payload over multiple packets thus defeating simple pattern matching without session reconstruction. This payload can be delivered in many different manners and even spread out over a long period of time. Currently, Whisker and Nessus have session splicing capabilities, and other tools exist in the wild (see detect #1 from the detects section). I have created a perl script splicer.pl that I will use to demonstrate many of these techniques. A trademark of a spliced session is a continuous stream of small packets. The network trace below shows a standard spliced session. For readability, this request has been abbreviated removing bytes nine thru 31.
At first this may seem easy to defend against by just checking for abnormally small packets. However, this is not the case because these are packets with the ACK flag set and packets with the ACK flag set are normally very small and contain no payload. This makes detection under normal traffic more difficult. For testing and comparison, a lab was constructed that contains three hosts on the same broadcast domain. The initial setup of the lab was as follows using Snort, Cisco Secure IDS and a Windows 2000 web server running Entercept 2.01 host IDS agent. A full description of the Cisco IDS log format and signatures used in these examples can be found in Appendix B. It should be noted that all request returned a page of some sort from the web server.
Several different requests were sent using the splicer.pl tool. Tables depict the request, which is the web request, splice size in bytes and timing in seconds with the associated logs from the devices. These attacks were sent from the ip 64.194.107.85. Note: organization specific information has been X out in the Cisco IDS logs. Detecting Session splicing with string matching IDS is very challenging. It is not possible to create signatures that just look for small packets with the ACK flag set since this occurs abundantly in normal traffic. Signatures must look do some payload comparison. Snort has several signatures to detect the tool Whisker session splices.
The first signature looks for 0x20 (a space) in the first 2 bytes of a packet with ack flags set and directed toward the defined variable $HTTP_SERVERS. The second signature looks for 0x09 (tab) within the first six bytes of a packet with ACK flags set directed toward the defined variable $HTTP_SERVERS. These signatures catch the default Whisker session splicing usage usage fine. However, these rules can be evaded by splicing the session differently. The tool splicer.pl allows different values to be specified for the payload size to be delivered. It should be pointed out that splicer.pl is written for HTTP traffic, however the basic premise of session splicing extends into all TCP protocols.
What we can ascertain from the initial test is that the Cisco IDS has no default check for generic Whisker style (1 byte) session splicing if there is not a malicious payload associated with the request. Snort generated four alerts associated with two signatures, one of which is associated with Whisker and one signature that is a custom generic splicing signature that I developed, which will be detailed later. To avoid the standard Whisker signatures an attacker can increase the size of the spliced packets as demonstrated below.
This successfully defeats Snorts Whisker based evasion signatures. To write a signature to detect this evasion technique, it is required that the IDS look for smaller packets with the ACK flag set and some content. There must be some content associated with the packet otherwise the signature will trigger on all associated ACK packets. The generic splicing rule below will work.
This particular signature detects any URI with a content of "H" and a dsize of less than 17 bytes. This should catch any web request that does not conform to "$METHOD / HTTP/1.0\r\n\" where $METHOD is equivalent to any HTTP method. The "H" was chosen because it is necessary in the HTTP request. This is still quite easy to evade by padding the URI with self referencing "./"directories, using a tab delimiter (Apache) or a space (IIS and Apache) and Nulls (IIS). This example will use the ida overflow URL since it does not require a specific URL for the attack to be successful. The Snort signature for the ida overflow is as follows
This signature looks for the URI content of ida? with a size of 240 bytes. There are a couple methods that can evade this. One method is to splice the payload into requests that are larger, such as 18 bytes, thus evading the string match. Now this signature could be re-written to only look for ida? and not require a length of 240 bytes. This signature will then trigger on normal traffic and create false alarms. Since this attack does not require a specific URI to be requested, an attacker could front load the request with bogus data to create a longer URI. To make this work we need to calculate the amount of characters needed to have the “H” fall into an 18 byte slice. We needed four bytes at the front of our request so the request ends up looking like the request below.
Notice that Cisco Secure IDS successfully detects the true attack with a signature which depicts the true threat. Snort detects ida access, but does not trigger the attack signature that it should. Even though Snort alerts this alert appears less threatening than it really is. Session splicing signatures for string matching IDS devices are proven inadequate. Sessions must be re-assembled before comparison or else they will fail. Several different attacks were sent to the victim host for testing purposes. In these examples, a malicious Unicode request was sent to the victim host. This signature was chosen because it’s almost identical on Cisco and Snort. Cisco detects three signatures 3215, 5114 and 3216. These are all associated with general Unicode activity. Signature 5114 detects Unicode characters while signatures 3215 and 3216 detect the “/../” activity. Using 1 byte session splices, Snort only detected the previously mentioned session splicing signatures. This is an example of Snort’s use of first exit rules.
Using larger slices, we can evade the splicing signatures but are picked up by Snort’s normal signatures. Cisco alerts to the true attack.
The next attempt both IDS devices alert fine. This attack uses two byte splices and slightly delayed time sequences of one second. I think some assumptions can now be made. Both Snort and Cisco have some session re-assembly capabilities. Snort, however will alert differently for the same attack depending on techniques used. This has to do with how Snort determines which rule it will alert on.
The next example the HTTP portion of the request was padded to avoid triggering the generic splicing rule. The splices remain at 2 bytes. The time between splices was moved to 20 seconds. Snort appears to time out some of the request because this time a different alert is received. Snort must have been able to only re-assemble a portion of the attack.
In a default configuration, Snort appears to time out requests after a certain amount of time. Cisco is still seeing the alerts. The following request still uses two byte splices, but the time between splices is increased to 45 seconds.
Increasing the time further will eventually evade Cisco Secure IDS.
In basic session splicing attacks where the hosts reside on the same broadcast domain it is possible to evade the IDS by not using the default one byte splice and delaying the attack significantly. The reason different Snort signatures will trigger, which can make an attack seem less threatening is because of Snort’s first exit rule. I suspected the problem was in the way rules were passed through the detection engine for comparison. I posted an email to Snort-Devel mail list and received this response from Martin Roesch the founder of Snort. If you want the single-byte detects for the real scripts that are being accessed, turn off the rule that's going off, that's Snort's "first exit" engine doing it's job. If you want to extend the tracking time for a session, increase the default timeout value for the stream4 preprocessor: preprocessor stream4: timeout 3600, detect_scans This helps explain why different Snort rules would trigger under different circumstances. I did some basic testing with turning of the session splicing rules and setting the timeout longer. Snort does a better job off detecting the true attack without the evasion signatures. However, the early exit rule still causes a Unicode cmd.exe attack to be seen as scripts access, and other attacks such as .ida to be misdiagnosed depending on how the splices fall and their timing. Whether these methods are successful when an IDS employs session re-assembly is somewhat host and application dependent. In testing, Apache on RedHat sessions, time out in six minutes while IIS on Windows 2000 doesn’t appear to timeout in any reasonable amount of time. This timeout of six minutes by Apache makes time based evasion more difficult when the host is on the same broadcast domain as the victim. To remove the broadcast domain, the web server was given a new IP behind a router one additional hop from the sensors.
The victim host and IDS devices are now not on the same broadcast domain. The victim host is also now one extra hop away. To help expedite the test, a simple custom signature was created on both IDS devices to alarm on the URL foo.htm. This was done to avoid triggering any alarms on the Entercept HIDS agent and to avoid any first exit rules.
To test that re-assembly was working well, and there were no other problems prohibiting proper alarming, a quick test was run sending 6 byte splices quickly. Both devices alarmed properly without a problem.
Both the devices alerted on the custom signatures while using basic session splicing techniques. The Cisco device alerted on a signature 3000 which is a TCP connection and signature 30001 which is the custom foo.htm signature. This proves session re-assembly is working correctly on both devices. The following evasion technique takes advantage of inherent network problems as described by Newsham and Ptacek[1] and Vern Paxson and Mark Handley in their paper “Network Intrusion Detection: Evasion, Traffic Normalization, and End-to End Protocol Semantics”[4]. The following test was done.
Several different session splicing evasion techniques have been demonstrated with varying degrees of success. Most of the techniques that are available with fragmentation can be used to some degree with splicing. The following table summarizes some of the similarities between fragmentation and splicing and denotes whether I had any success in limited testing.
The reality is that many network level problems still exist and are very difficult for devices to handle without traffic normalization unless the device uses “bifurcating analysis”[4] techniques which means that if an IDS detects traffic which has possible multiple interpretations it will apply all interpretations to the analysis and alarm if any match a signature. Still, the use of session splicing timeouts presents a unique problem for the IDS. If a host operating system will keep the session alive for a very long period of time, than the IDS must do the same. IDS designers recently have made tremendous strides in defeating string matching evasion techniques; now network level techniques are being addressed. [1] Ptacek, Thomas and Newsham, Timothy Insertion, Evasion, and Denial of Service: Eluding Network Intrusion Detection January, 1998. URL: http://secinf.net/info/ids/idspaper/idspaper.html [2] Puppy, Rain Forest A look at whisker’s anti-IDS tactics December 24, 1999. URL: http://www.wiretrip.net/rfp/pages/whitepapers/whiskerids.html [3] Arboi, Michel and Deraison, Renaud Using Nessus’s NIDS evasion features 2002, URL: http://www.nessus.org/doc/nids.html [4] Handley, Mark Paxson, Vern and Kreibich, Christian Network Intrusion Detection: Evasion, Traffic Normalization, and End-to-End Protocol Semantics May 22, 2001. URL: http://www.icir.org/vern/papers/norm-usenix-sec01-html [5] Song, Dug Fragroute, April, 2002. URL: http://www.monkey.org/~dugsong/fragroute/ #!/usr/bin/perl use Socket; use Getopt::Std; require 'getopts.pl'; getopts('h:t:s:r:'); if (!$opt_h || !$opt_t || !$opt_r) { &usage(); exit 1; } sub usage { print "\tUSAGE: splicer -h print "\t************Notes***********\n"; print "\t***Apache times out a unfinished request in 6 minutes\n"; print "\t***IIS doesn't appear to have such a timeout\n"; print "\t***If no splice size is specified it will send 1 byte at a time\n\n"; } if ($opt_s == NULL) { $opt_s=1; } $host=$opt_h; $size=$opt_s; $req="GET $opt_r HTTP/1.0\r\n"; $time=$opt_t; $header="Host: $host\r\nUser-Agent: Session-Splice\r\n\r\n"; @greq=(split//,$req); socket(SERVER, PF_INET, SOCK_STREAM, getprotobyname('tcp')); $addr = sockaddr_in(80, inet_aton($host)); connect(SERVER, $addr); select(SERVER); $|=1; select(STDOUT); $i=0; # Send packet foreach $char (@greq) { chomp $char; if ($i == $size) { push(@new,$char); print SERVER @new; select(undef,undef,undef,$time); $i = 0; $i++; $#new=-1; } else { push(@new,$char); $i++; } } print SERVER "$header"; # Parse our requesr do { $line = <SERVER> } until ($line =~ /^\r\n/); @output = <SERVER>; close (SERVER) ; print "@output\n"; |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||