Snort mailing list archives
Re: Stream5: RST handling + 'STREAM5_BAD_RST' alert
From: Bram <bram-fabeg () mail wizbit be>
Date: Wed, 18 Sep 2013 21:33:08 +0200
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) 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? ...? 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.. * 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; This can lead to false positives but no attempt has been made to trigger this particular case. * false positive? 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:
- Stream5: RST handling + 'STREAM5_BAD_RST' alert Bram (Aug 23)
- Re: Stream5: RST handling + 'STREAM5_BAD_RST' alert Bram (Sep 18)
- Re: Stream5: RST handling + 'STREAM5_BAD_RST' alert Russ Combs (Sep 19)
- Re: Stream5: RST handling + 'STREAM5_BAD_RST' alert Bram (Sep 19)
- Re: Stream5: RST handling + 'STREAM5_BAD_RST' alert Russ Combs (Sep 19)
- Re: Stream5: RST handling + 'STREAM5_BAD_RST' alert Bram (Sep 19)
- Re: Stream5: RST handling + 'STREAM5_BAD_RST' alert Russ Combs (Sep 23)
- Re: Stream5: RST handling + 'STREAM5_BAD_RST' alert Russ Combs (Sep 19)
- Re: Stream5: RST handling + 'STREAM5_BAD_RST' alert Bram (Sep 18)