[Snort-devel] Decoder: 'DECODE_IPV6_TRUNCATED' alert on DNS query (false positive)

Bram bram-fabeg at ...3414...
Fri Sep 6 08:32:06 EDT 2013


Hi,


The attached dump is a dns query (over IPv4) which generates the alert  
'DECODE_IPV6_TRUNCATED'.
This is unexpected and feels like a false positive.


Config:
	dynamicpreprocessor directory /usr/lib/snort_dynamicpreprocessor/

	output log_null

	output alert_fast: stdout

	alert ( msg:"DECODE_IPV6_TRUNCATED"; sid:273; gid:116; rev:1;  
metadata:rule-type decode; )


Running:
	$ snort -v -l /var/log -c /etc/ips/snort.conf --daq-dir /lib/daq/    
-r /tmp/116_273.cap 2>&1  | grep '116:'
	07/16-14:38:58.547143  [**] [116:273:1] (snort decoder) WARNING: IPV6  
truncated header [**] [Priority: 0] {UDP} 10.10.1.1:3544 -> 8.8.8.8:53

Version:
	$ snort -V

	   ,,_     -*> Snort! <*-
	  o"  )~   Version 2.9.5.3 GRE (Build 132)
	   ''''    By Martin Roesch & The Snort Team:  
http://www.snort.org/snort/snort-team
	           Copyright (C) 1998-2013 Sourcefire, Inc., et al.
	           Using libpcap version 1.3.0
	           Using PCRE version: 8.32 2012-11-30
	           Using ZLIB version: 1.2.8


Running it under gdb and breaking on 'DecodeIPV6' shows:
	Breakpoint 2, DecodeIPV6 (pkt=0x8f914a2 "mX\001", len=35, p=0x8765fe0  
<s_packet>) at decode.c:3672
	3672	in decode.c
	(gdb) bt
	#0  DecodeIPV6 (pkt=0x8f914a2 "mX\001", len=35, p=0x8765fe0  
<s_packet>) at decode.c:3672
	#1  0x080541bf in DecodeTeredo (pkt=0x8f914a2 "mX\001", len=35,  
p=0x8765fe0 <s_packet>) at decode.c:4234
	#2  0x08055852 in DecodeUDP (pkt=0x8f9149a "\r\330", len=43,  
p=0x8765fe0 <s_packet>) at decode.c:5111
	#3  0x080506d5 in DecodeIPv4Proto (proto=17 '\021', pkt=0x8f9149a  
"\r\330", len=43, p=0x8765fe0 <s_packet>) at decode.c:2198
	#4  0x08051293 in DecodeIP (pkt=0x8f91486 "E", len=63, p=0x8765fe0  
<s_packet>) at decode.c:2585
	#5  0x0804dfee in DecodeEthPkt (p=0x8765fe0 <s_packet>,  
pkthdr=0xbffff880, pkt=0x8f91478 "\030\357cc\350`h\005\312\b\353\b\b")  
at decode.c:709
	#6  0x08077d6c in ProcessPacket (p=0x8765fe0 <s_packet>,  
pkthdr=0xbffff880, pkt=0x8f91478 "\030\357cc\350`h\005\312\b\353\b\b",  
ft=0x0) at snort.c:1800
	#7  0x08077a95 in PacketCallback (user=0x0, pkthdr=0xbffff880,  
pkt=0x8f91478 "\030\357cc\350`h\005\312\b\353\b\b") at snort.c:1685
	...

Looking at the code shows why it is attempting to parse the packet as IPv6:

It seems to assume that this is a 'Teredo' connection/packe (RFC 4380).
That is: an IPv6 packet tunneled over IPv4 UDP.


The conditions in which it makes this assumption:
* the UDP data is at least 2 bytes
* the first 4 bits of data is '6'

When the conditions are true then it checks:
         if (ScDeepTeredoInspection() && (p->sp != TEREDO_PORT) &&  
(p->dp != TEREDO_PORT))
             p->packet_flags |= PKT_UNSURE_ENCAP;

=> 'PKT_UNSURE_ENCAP' is set when:
* 'enable_deep_teredo_inspection' is included in the config
* the source port is not port 3544
* the desination port is not port 3544

The 'PKT_UNSURE_ENCAP' flag is checked in DecodeIPV6, relevant code:
     if(len < IP6_HDR_LEN)
     {
         if ((p->packet_flags & PKT_UNSURE_ENCAP) == 0)
             DecoderEvent(p, DECODE_IPV6_TRUNCATED, DECODE_IPV6_TRUNCATED_STR,
                          1, 1);

         goto decodeipv6_fail;
     }


Looking at the config: 'enable_deep_teredo_inspection' is not set

Looking at the dump:
* the soucre port is set to 3544,
* the first 4 bits of the udp data is 6.


This source port was randomly chosen by the dns client.
The first 4 bits of the udp data happens to be 6 because the  
transaction id (also chosen by the dns client) is set to 0x6d58.
The total length of the udp data is 35 bytes.

=> 'IP6_HDR_LEN' is set to 40 bytes.

For larger DNS query the following happens:
* it first checks the length (OK)
* it checks the first 4 bits to see if these are set to 6 (OK - same  
check as in DecodeTeredo)
* it checks 'p->family' (not sure about this one)
* it compares the payload length with the length set in the IPv6  
header, for this it uses the first part of the DNS flags. (alert is  
given when the length in the header is larger then the UDP length)
* it calls 'CheckTeredoPrefix' to check the data, when this fails it  
aborts the IPv6 checking without generating an alert


This means that the false positives are limited to DNS queries:
* which are smaller then 40 bytes
* which use a port 3544
* which use a transaction id that starts with 0x6...


For larger DNS queries false positives may also be triggered depending  
on the flags in the dns query.. (no attempt was made to reproduce this)


Best regards,

Bram


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

-------------- next part --------------
A non-text attachment was scrubbed...
Name: 116_273.cap
Type: application/octet-stream
Size: 117 bytes
Desc: not available
URL: <https://lists.snort.org/pipermail/snort-devel/attachments/20130906/ab939f5b/attachment.obj>


More information about the Snort-devel mailing list