Snort mailing list archives
Stream5: RST handling + 'STREAM5_BAD_RST' alert
From: Bram <bram-fabeg () mail wizbit be>
Date: Fri, 23 Aug 2013 11:40:41 +0200
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 = 100020The 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.
Attachment:
client.cap
Description:
Attachment:
server.cap
Description:
------------------------------------------------------------------------------ Introducing Performance Central, a new site from SourceForge and AppDynamics. Performance Central is your source for news, insights, analysis and resources for efficient Application Performance Management. Visit us today! http://pubads.g.doubleclick.net/gampad/clk?id=48897511&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)
