mirror of
https://github.com/zeek/zeek.git
synced 2025-10-13 12:08:20 +00:00
Add some extra length checking when parsing mobile ipv6 packets
Credit to OSS-Fuzz for discovery https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=34263 (Link to details becomes public 30 days after patch release)
This commit is contained in:
parent
2c27f1bf34
commit
54271657a8
4 changed files with 57 additions and 22 deletions
61
src/IP.cc
61
src/IP.cc
|
@ -619,6 +619,12 @@ void IPv6_Hdr_Chain::ProcessRoutingHeader(const struct ip6_rthdr* r, uint16_t le
|
||||||
#ifdef ENABLE_MOBILE_IPV6
|
#ifdef ENABLE_MOBILE_IPV6
|
||||||
void IPv6_Hdr_Chain::ProcessDstOpts(const struct ip6_dest* d, uint16_t len)
|
void IPv6_Hdr_Chain::ProcessDstOpts(const struct ip6_dest* d, uint16_t len)
|
||||||
{
|
{
|
||||||
|
// Skip two bytes to get the beginning of the first option structure. These
|
||||||
|
// two bytes are the protocol for the next header and extension header length,
|
||||||
|
// already known to exist before calling this method. See header format:
|
||||||
|
// https://datatracker.ietf.org/doc/html/rfc8200#section-4.6
|
||||||
|
assert(len >= 2);
|
||||||
|
|
||||||
const u_char* data = (const u_char*) d;
|
const u_char* data = (const u_char*) d;
|
||||||
len -= 2 * sizeof(uint8_t);
|
len -= 2 * sizeof(uint8_t);
|
||||||
data += 2* sizeof(uint8_t);
|
data += 2* sizeof(uint8_t);
|
||||||
|
@ -627,34 +633,45 @@ void IPv6_Hdr_Chain::ProcessDstOpts(const struct ip6_dest* d, uint16_t len)
|
||||||
{
|
{
|
||||||
const struct ip6_opt* opt = (const struct ip6_opt*) data;
|
const struct ip6_opt* opt = (const struct ip6_opt*) data;
|
||||||
switch ( opt->ip6o_type ) {
|
switch ( opt->ip6o_type ) {
|
||||||
case 201: // Home Address Option, Mobile IPv6 RFC 6275 section 6.3
|
case 0:
|
||||||
{
|
// If option type is zero, it's a Pad0 and can be just a single
|
||||||
if ( opt->ip6o_len == 16 )
|
// byte in width. Skip over it.
|
||||||
if ( homeAddr )
|
|
||||||
reporter->Weird(SrcAddr(), DstAddr(), "multiple_home_addr_opts");
|
|
||||||
else
|
|
||||||
homeAddr = new IPAddr(*((const in6_addr*)(data + 2)));
|
|
||||||
else
|
|
||||||
reporter->Weird(SrcAddr(), DstAddr(), "bad_home_addr_len");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( opt->ip6o_type == 0 )
|
|
||||||
{
|
|
||||||
data += sizeof(uint8_t);
|
data += sizeof(uint8_t);
|
||||||
len -= sizeof(uint8_t);
|
len -= sizeof(uint8_t);
|
||||||
}
|
break;
|
||||||
else
|
default:
|
||||||
{
|
{
|
||||||
data += 2 * sizeof(uint8_t) + opt->ip6o_len;
|
// Double-check that the len can hold the whole option structure.
|
||||||
len -= 2 * sizeof(uint8_t) + opt->ip6o_len;
|
// Otherwise we get a buffer-overflow when we check the option_len.
|
||||||
|
// Also check that it holds everything for the option itself.
|
||||||
|
if ( len < sizeof(struct ip6_opt) ||
|
||||||
|
len < sizeof(struct ip6_opt) + opt->ip6o_len )
|
||||||
|
{
|
||||||
|
reporter->Weird(SrcAddr(), DstAddr(), "bad_ipv6_dest_opt_len");
|
||||||
|
len = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( opt->ip6o_type == 201 ) // Home Address Option, Mobile IPv6 RFC 6275 section 6.3
|
||||||
|
{
|
||||||
|
if ( opt->ip6o_len == sizeof(struct in6_addr) )
|
||||||
|
{
|
||||||
|
if ( homeAddr )
|
||||||
|
reporter->Weird(SrcAddr(), DstAddr(), "multiple_home_addr_opts");
|
||||||
|
else
|
||||||
|
homeAddr = new IPAddr(*((const in6_addr*)(data + sizeof(struct ip6_opt))));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
reporter->Weird(SrcAddr(), DstAddr(), "bad_home_addr_len");
|
||||||
|
}
|
||||||
|
|
||||||
|
data += sizeof(struct ip6_opt) + opt->ip6o_len;
|
||||||
|
len -= sizeof(struct ip6_opt) + opt->ip6o_len;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
VectorValPtr IPv6_Hdr_Chain::ToVal() const
|
VectorValPtr IPv6_Hdr_Chain::ToVal() const
|
||||||
|
|
14
testing/btest/Baseline/core.mobile-ipv6-dst-opts/weird.log
Normal file
14
testing/btest/Baseline/core.mobile-ipv6-dst-opts/weird.log
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
#separator \x09
|
||||||
|
#set_separator ,
|
||||||
|
#empty_field (empty)
|
||||||
|
#unset_field -
|
||||||
|
#path weird
|
||||||
|
#open XXXX-XX-XX-XX-XX-XX
|
||||||
|
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer source
|
||||||
|
#types time string addr port addr port string string bool string string
|
||||||
|
XXXXXXXXXX.XXXXXX - 2001:4f8:4:7:2e0:81ff:fe52:ffff 0 2001:4f8:4:7:2e0:81ff:fe52:9a6b 0 bad_ipv6_dest_opt_len - F zeek -
|
||||||
|
XXXXXXXXXX.XXXXXX - 2001:78:1:32::1 0 2001:4f8:4:7:2e0:81ff:fe52:9a6b 0 multiple_home_addr_opts - F zeek -
|
||||||
|
XXXXXXXXXX.XXXXXX - 2001:78:1:32::1 0 2001:4f8:4:7:2e0:81ff:fe52:9a6b 0 invalid_IP_header_size - F zeek IP
|
||||||
|
XXXXXXXXXX.XXXXXX - 2001:4f8:4:7:2e0:81ff:fe52:ffff 0 2001:4f8:4:7:2e0:81ff:fe52:9a6b 0 bad_home_addr_len - F zeek -
|
||||||
|
#close XXXX-XX-XX-XX-XX-XX
|
BIN
testing/btest/Traces/ipv6-mobility-dst-opts.trace
Executable file
BIN
testing/btest/Traces/ipv6-mobility-dst-opts.trace
Executable file
Binary file not shown.
4
testing/btest/core/mobile-ipv6-dst-opts.test
Normal file
4
testing/btest/core/mobile-ipv6-dst-opts.test
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# @TEST-REQUIRES: grep -q "#define ENABLE_MOBILE_IPV6" $BUILD/zeek-config.h
|
||||||
|
#
|
||||||
|
# @TEST-EXEC: zeek -C -r $TRACES/ipv6-mobility-dst-opts.trace
|
||||||
|
# @TEST-EXEC: btest-diff weird.log
|
Loading…
Add table
Add a link
Reference in a new issue