Tuesday, December 1, 2009

require_3whs and the Mystery of the Four-Way Handshake

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:
http://www.breakingpointsystems.com/community/blog/tcp-portals-the-three-way-handshake-is-a-lie

Long story short, there is an acceptable method of session establishment that goes something like this:

SYN ->
<- SYN SYN/ACK ->
<- ACK

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/20

Using 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_3whs

To 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_3whs


Here 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.0
Alerts:
1:6:0 Get with standard content match and no flow check
Alerts: 1

In 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.0
Alerts:
1:3:0 Get with http_inspect method check
Alerts: 1
1:4:0 Get with standard content match and flow check
Alerts: 1
1:6:0 Get with standard content match and no flow check
Alerts: 1

We 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.

2 comments:

  1. Matt -- If I understand the post correctly, when a session is created using the "four way handshake", the stream preproc will not be able to handle it correctly unless the require_3whs option is enabled. Is that correct? Is there any negative effect by adding this option (e.g: certain legitimate sessions ignored) or is this something that we should all definitely add to our stream5 configuration as it only enhances detection. Thanks!

    ReplyDelete
  2. The only problem with this configuration is that as you start Snort, or as you restart 2.8.5 with a new config, Snort will ignore established sessions because it did not see the handshake.

    Because this is so low impact, I believe we'll be updating the recommended configuration that ships with our VRT packages.

    Hope that helps.

    ReplyDelete

Post a Comment