[Snort-devel] Stream5: RST handling + 'STREAM5_BAD_RST' alert

Russ Combs rcombs at ...402...
Thu Sep 19 15:03:53 EDT 2013


On Wed, Sep 18, 2013 at 3:33 PM, Bram <bram-fabeg at ...3414...> wrote:

> Was this message taken into consideration? (I received no reply)
>
>
> Quoting Bram <bram-fabeg at ...3414...>:
>
>  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.
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.snort.org/pipermail/snort-devel/attachments/20130919/3e91a6b3/attachment.html>


More information about the Snort-devel mailing list