[Snort-users] Snort DoS Fallacies

Ferguson, Justin (IARC) FergusonJ at ...13492...
Tue Sep 13 07:49:14 EDT 2005


Hello,

The recent advisory from the Snort team in regards to the DoS in the
PrintTCPOptions() function of log.c is incorrect in a couple regards.

Firstly, and most importantly- You _do not_ have to be running snort with
-v, there are several execution path's in snort that leads to the function
PrintTCPOptions(), excerpts from relevant code are below:

First, let's us realize how the code gets to PrintTCPOptions().

PrintTCPOptions() is called by PrintTCPHeader(), which in turn is called by
PrintIPPKT(), see below for relevant code snippets-- The line numbers are
from the current CVS version of snort pulled down aprox. 1 hour ago.


snort/src/log.c
315 PrintIPPkt()
[...]
337 if(!p->frag_flag)
338 {
339 switch(p->iph->ip_proto)
340 {
341 case IPPROTO_TCP:
342 if(p->tcph != NULL)
343 {
344 PrintTCPHeader(fp, p);
345 }

snort/src/log.c
934 PrintTCPHeader()
[...]
962 /* dump the TCP options */
963 if(p->tcp_option_count != 0)
964 {
965 PrintTcpOptions(fp, p);
966 }

So we see here that, if someone is to call PrintIPPacket(), and the packet
is not a fragment, and its protocol is TCP then we call TCPHeader() and once
inside of PrintTCPHeader(), if the option_count is not 0, then we call
PrintTCPOptions.

Now a quick grep(1) of the source tree reveals several possible ways to end
up at PrintIPPkt(), relevant source below:

First, if we are using the option -A fast:

snort/src/output-plugins/spo_alert_fast.c
134 AlertFast()
[...]
146 if(msg != NULL)
147 {
[...]
208 if(p && data->packet_flag)
209 {
210 fputc('\n', data->file);
211
212 if(p->iph)
213 PrintIPPkt(data->file, p->iph->ip_proto, p);


Second, if we are logging in ASCII mode (a lot of people):

snort/src/output-plugins/spo_log_ascii.c
112 LogAscii()
[...]
137 if(p)
138 {
139 if(p->iph)
140 PrintIPPkt(log_ptr, p->iph->ip_proto, p);


Also, in the frag3 preprocessor, also I'm not sure what the point of
defining DEBUG_FRAG3 at compile time would be (at least in this code
segment), as the execution flow is exactly the same:

snort/src/preprocessors/spp_frag3.c
2929 Frag3Rebuild()
[...]
3117 #ifdef DEBUG_FRAG3
[...]
3122 if (DEBUG_FRAG & GetDebugLevel())
3123 {
[...]
3126 PrintIPPkt(stdout, defrag_pkt->iph->ip_proto, defrag_pkt);
[...]
3129 }
3130 #endif
[...]
3133 PrintIPPkt(stdout, defrag_pkt->iph->ip_proto, defrag_pkt);

It can also be called in the stream4 preprocessor, if a few debugging
conditions are met:

snort/src/preprocessors/stream4.c
4682 BuildPacket()
[...]
4841 #ifdef DEBUG
[...]
4852 if (DEBUG_STREAM & GetDebugLevel())
4853 {
[...]
4856 PrintIPPkt(stdout, IPPROTO_TCP, stream_pkt);
[...]
4863 }
4864 #endif


And finally, as the snort authors suggested, if you are using -v:

snort/src/snort.c
766 /* print the packet to the screen */
767 if(pv.verbose_flag)
768 {
769 if(p.iph != NULL)
770 PrintIPPkt(stdout, p.iph->ip_proto, &p);


Additionally, as the second part of the misrepresentation of data, there is
several bugs in PrintTCPOptions(), which is apparent by the changes they
made-- these include nearly all of the TCP options, not just SACK. These
include the following options:

TCPOPT_MAXSEG, TCPOPT_WSCALE, TCPOPT_ECHO, TCPOPT_ECHOREPLY, 
TCPOPT_TIMESTAMP, TCPOPT_CC, TCPOPT_CCNEW, TCPOPT_CCECHO, and _any_
unrecognized or invalid option.

However, the snort team did say one thing correctly, and that these all are
NULL pointer dereferences, and therefore only a DoS and not exploitable to
run arbitrary code.

Best Regards,

J. Ferguson
Intrusion Analyst
NNSA Information Assurance Response Center (IARC)
fergusonj at ...13492...


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.snort.org/pipermail/snort-users/attachments/20050913/3105aacd/attachment.html>


More information about the Snort-users mailing list