inliniac/suricata — pull request #1119 by bmeeks8 (2014-09-04 18:11:52+00:00)
Title: Master 2.0.x ipv6 negated range bugfix

I discovered a bug in the Signature Match Address Array comparison code for IPv6 addresses. The function DetectAddressMatchIPv6() walks a signature's source or destination match address array comparing each to the current packet's address corresponding value. The match address array consists of value pairs representing a lower and upper address range. If the packet's address is within that range (including equal to either the lower or upper bound), then a signature match flag is returned.

The original test of each signature match address to the packet was performed using a set of four compounded AND comparisons looking at each of the four 32-bit blocks that comprise an IPv6 address. The problem with the old comparison is that if ANY of the four 32-bit blocks failed the test, then a "no-match" was returned. This is incorrect. If one or more of the more significant 32-bit blocks met the condition, then it is a match no matter if some of the less significant 32-bit blocks did not meet the condition. Consider this example where Packet represents the packet address being checked, and Target represents the upper bound of a match address pair. We are testing if Packet is less than Target.

Packet -- 2001:0470 : 1f07:00e2 : 1988:01f1 : d468:27ab
Target -- 2001:0470 : 1f07:00e2 : a48c:2e52 : d121:101e

In this example the Packet's address is less than the target and it should give a match. However, the old code would compare each 32-bit block (shown spaced out above for clarity) and logically AND the result with the next least significant block comparison. If any of the four blocks failed the comparison, that kicked out the whole address. The flaw is illustrated above. The first two blocks are equal and yield TRUE, the next less significant block is TRUE (that is, Packet is less than Target), but the last block compare is FALSE. That last block is the least significant block, though, so it should not invalidate a TRUE from any of the more significant blocks.

Bill