So, Tod Beardsley over at Breakingpoint Labs decided to kick around RFC793 some, and came across the "simultaneous connection". You can read the RFC at http://www.faqs.org/rfcs/rfc793.html, check around page 32 or look for the phrase "Simultaneous initiation". However, for a slightly more user-friendly description, check out Tod's blog entry at Breakpoint:
Long story short, there is an acceptable method of session establishment that goes something like this:
SYN -> <- syn ack -> <- ack< pre>Or, as I call it, the 4-way handshake. In Tod's testing, he found that this connection method worked on Ubuntu, OSX and Windows XP. This essentially reverses the flow of the connection establishment, but functionally does not change how data is transfered. We caught the link to this on Twitter, and scheduled some testing time. But we got tied up, and the folks over at Malware Forge posted their research:http://malforge.com/node/20Using some Python-fu, they found that it was possible to bypass Snort detection when a malicious server was modified to accept incoming sessions using the simultaneous connection method. The VRT verified this and worked on narrowing down the root cause, and then kicked it over to the dev team.Enter Russ Combs, stream reassembly guru here at Sourcefire. He told us that Snort had a configuration option that would ensure that the four-way handshake didn’t impact the Stream5 preprocessor’s ability to correctly tag a stream and the subsequent direction of traffic.The modification is to add the following value to your "preprocessor stream5_tcp:" line: require_3whsTo be clear, in the testing I'm going to show below, here are my values:(failed test)preprocessor stream5_tcp: policy first, use_static_footprint_sizes(passed test)preprocessor stream5_tcp: policy first, use_static_footprint_sizes, require_3whsHere are the contents of my local.rules file I used in testing:alert tcp $HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS (msg:"Get with http_inspect method check"; flow: to_server, established; content:"GET"; http_method; sid: 3;)alert tcp $HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS (msg:"Get withstandard content match and flow check"; flow: to_server, established; content:"GET"; http_method; sid: 4;)alert tcp $HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS (msg:"Get with standard content match and no flow check"; content:"GET"; sid: 6;)Here is the output I got when I ran the test, (failed tests first and Using the fake.pcap from http://malforge.com/node/20):Snort Test Suite v.0.3.0Alerts:1:6:0 Get with standard content match and no flow check Alerts: 1In this case, we only alerted on the standard content match without flow enforcement. This indicates that stream5 has incorrectly interpreted the stream. Remember that both the flow keywords, as well as the http_method modifier require stream5 to have properly marked a stream in order to function.Here are the test results after I added the require_3whs:Snort Test Suite v.0.3.0Alerts:1:3:0 Get with http_inspect method check Alerts: 11:4:0 Get with standard content match and flow check Alerts: 11:6:0 Get with standard content match and no flow check Alerts: 1We now correctly alert on checks in both the http_inspect preprocessor and the flow direction. So, if you’re concerned about this evasion case, make the appropriate modifications, and then get to testing.