Snort mailing list archives

Re: Stream5: RST handling + 'STREAM5_BAD_RST' alert


From: Russ Combs <rcombs () sourcefire com>
Date: Thu, 19 Sep 2013 15:03:53 -0400

On Wed, Sep 18, 2013 at 3:33 PM, Bram <bram-fabeg () mail wizbit be> wrote:

Was this message taken into consideration? (I received no reply)


Quoting Bram <bram-fabeg () mail wizbit be>:

 Hi,


While looking at traffic which triggered the 'STREAM5_BAD_RST' alert
 I've found some (potential) issues..


* snort_stream5_tcp.c: 'ValidRst' function:

This issue is more of a configuration question/remark and not
 necessarily a bug in the code:

First the comments before the function:
       // per rfc 793 a rst is valid if the seq number is in window
       // for all states but syn-sent (handled above).  however, we
       // validate here based on how various implementations actually
       // handle a rst.

The question however is how the stream5 streamprocessor should be
configured?
What if it's a connection between a Linux system and a Windows system?
The code in 'ValidRST' appears to be stricter for Windows than for Linux?
What if the OS of one of the peers is unknown?
And by extension: what if the OS of both peers is unknown? (a DHCP
 client connection to a server on internet for example)


stream5_tcp bind_to and policy are available to tailor your configuration
to your networks.  You can configure stream5_tcp multiple times, once w/o
bind_to (the default) and then with specific IP addresses/networks
(non-default).  The policy from the matching configuration or default will
be used.  See here for more:

 http://manual.snort.org/node17.html#SECTION00322700000000000000


Looking at the code: this also means Windows (for example) does not
 accept all (RFC) valid RSTs?
Based on what was this code written? A windows document? Trial and error?
...?


Yes, in effect, trial and error - ie discover what the specific OS
implementations do.  Check the above for OS versions corresponding to
policy names.  We already have a bug to bring the target based support up
to date.


Either way: the message of the alert 'Reset outside window' is at the
 very least confusing..
When the sequence number is inside the window but if/when the host
 ignores the RST then (IMO) a different alert should be generated.
Right now it looks like an invalid RST packet is send/received which  is
not really the case..


Actually, that should be the case.  Do you have a pcap so I can see the
specific scenario you are referring to?  Per the RFC, a reset is valid if
in window except in the SYN-sent state.  So the message could be tweaked
but it should still be a bad RST.  Unless you have a more recent scenario
the code does not address yet.



* snort_stream5_tcp.c: 'Stream5GetWindow' function:

Second issue: this does look like a bug:

Code:
    if ( st->l_window )
    {
        // don't use the window if we may have missed scaling
        if ( !(lwssn->session_state & STREAM5_STATE_MIDSTREAM) )
            return st->l_window;
    }
    // one way zero window is unitialized
    // two way zero window is actually closed (regardless of scaling)
    else if ( TwoWayTraffic(lwssn) )
        return st->l_window;

    // ensure the data is in the window
    window = tdb->end_seq - st->r_win_base;

    if ( window <  0 )
        window = 0;

    return (uint32_t)window;


The 'window scaling' option is part of the SYN and SYN+ACK packet.
If I read the code in 'ProcessTcp' correctly then
 'STREAM5_STATE_MIDSTREAM' gets set when data is seen on the connection
 but the SYN or the SYN+ACK was not seen.

I believe the intent of the code in 'Stream5GetWindow' is to only use
 'window scaling' when the SYN and SYN+ACK were seen.
This is however not what the code appears to be doing.

Code:
        // don't use the window if we may have missed scaling
        if ( !(lwssn->session_state & STREAM5_STATE_MIDSTREAM) )
            return st->l_window;


If I read the code correctly:
- When the SYN or SYN+ACK is missing then 'lwssn->session_state &
 STREAM5_STATE_MIDSTREAM' will return a value.
- This value is then negated.
- Which means: if the 'STREAM5_STATE_MIDSTREAM' flag is set then the
 code will continue (using scaling), when it's not set it will  immediately
return 'st->l_window' (not using scaling)

I believe the code should read:
        // don't use the window if we may have missed scaling
        if ( lwssn->session_state & STREAM5_STATE_MIDSTREAM )
            return st->l_window;

The code says:

If window is non-zero then
    if the session is not midstream
        use the window
...

Which reads correctly.  If you have an example pcap, please send it along.



This can lead to false positives but no attempt has been made to  trigger
this particular case.


* false positive?


The case below is on my list ...


Attached are two dumps of the same TCP stream: one taken on the client
 and one taken on the server.
(TCP session recreated based on a SMTP session between two linux hosts.)

Config:
       config checksum_mode: all
       dynamicpreprocessor directory /usr/lib/snort_**
dynamicpreprocessor/
       preprocessor stream5_global: track_tcp yes, \
          track_udp no, \
          track_icmp no, \
          max_tcp 262144, \
          max_udp 131072
       preprocessor stream5_tcp: policy linux, detect_anomalies

       alert ( msg: "STREAM5_BAD_RST"; sid: 15; gid: 129; rev: 1;
metadata:  rule-type preproc ; )

       output alert_fast: stdout

Running it:
       $ snort -v -l /var/log -c /etc/ips/snort.conf --daq-dir /lib/daq/
-r  /tmp/client.cap 2>&1 | grep '129:'

       $ snort -v -l /var/log -c /etc/ips/snort.conf --daq-dir /lib/daq/
-r  /tmp/server.cap 2>&1 | grep '129:'
       08/23-11:14:37.257018  [**] [129:15:1] Reset outside window [**]
 [Priority: 0] {TCP} 10.11.1.2:5556 -> 10.10.1.1:5555

Looking with gdb with the 'server.cap' shows that the alert is  generated
on the first RST packet (packet 9).
Breaking in the 'ValidRST' function shows:
- tdb->end_seq = 100010
- st->r_win_base = 100020

The first check in the code checks that 'tdb->end_seq' is greater
 than/or equal to 'st->r_win_base'.
This is not the case --> alert is generated.

My guess is that this happens because the server already send an ACK  for
the data up to sequence '100020'.
The client then sends a RST with sequence '100010' and a RST with
 sequence '100020'.

This appears to be standard Linux behaviour..
When it sends a RST packet it appears to be using the 'ACK' number of
 the receiving packet as sequence number.

I'm not sure if this can be considered a false positive or not..

Looking at RFC 793 shows:
  Reset Generation

  As a general rule, reset (RST) must be sent whenever a segment arrives
  which apparently is not intended for the current connection.  A reset
  must not be sent if it is not clear that this is the case.

  There are three groups of states:

    1.  If the connection does not exist (CLOSED) then a reset is sent
    in response to any incoming segment except another reset.  In
    particular, SYNs addressed to a non-existent connection are rejected
    by this means.

    If the incoming segment has an ACK field, the reset takes its
    sequence number from the ACK field of the segment, otherwise the
    reset has sequence number zero and the ACK field is set to the sum
    of the sequence number and segment length of the incoming segment.
    The connection remains in the CLOSED state.

This appears to be what linux is doing.

The same RFC:
  Reset Processing

  In all states except SYN-SENT, all reset (RST) segments are validated
  by checking their SEQ-fields.  A reset is valid if its sequence number
  is in the window.  In the SYN-SENT state (a RST received in response
  to an initial SYN), the RST is acceptable if the ACK field
  acknowledges the SYN.


It does not seem to specify how a RST packet with a sequence number
 which is lower then the last acked segment should be handled...



Best regards,

Bram



------------------------------**------------------------------**----
This message was sent using IMP, the Internet Messaging Program.





------------------------------**------------------------------**----
This message was sent using IMP, the Internet Messaging Program.


------------------------------------------------------------------------------
LIMITED TIME SALE - Full Year of Microsoft Training For Just $49.99!
1,500+ hours of tutorials including VisualStudio 2012, Windows 8, SharePoint
2013, SQL 2012, MVC 4, more. BEST VALUE: New Multi-Library Power Pack includes
Mobile, Cloud, Java, and UX Design. Lowest price ever! Ends 9/20/13. 
http://pubads.g.doubleclick.net/gampad/clk?id=58041151&iu=/4140/ostg.clktrk
_______________________________________________
Snort-devel mailing list
Snort-devel () lists sourceforge net
https://lists.sourceforge.net/lists/listinfo/snort-devel
Archive:
http://sourceforge.net/mailarchive/forum.php?forum_name=snort-devel

Please visit http://blog.snort.org for the latest news about Snort!

Current thread: