mirror of
https://github.com/zeek/zeek.git
synced 2025-10-05 08:08:19 +00:00
Add additional length checking to IPv6::ToVal
This commit is contained in:
parent
ee8e2decec
commit
d5a1eb162e
2 changed files with 60 additions and 13 deletions
70
src/IP.cc
70
src/IP.cc
|
@ -16,11 +16,22 @@
|
||||||
namespace zeek
|
namespace zeek
|
||||||
{
|
{
|
||||||
|
|
||||||
|
bool IPv6_Hdr::IsOptionTruncated(uint16_t off) const
|
||||||
|
{
|
||||||
|
if ( Length() < off )
|
||||||
|
{
|
||||||
|
reporter->Weird("truncated_IPv6_option");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static VectorValPtr BuildOptionsVal(const u_char* data, int len)
|
static VectorValPtr BuildOptionsVal(const u_char* data, int len)
|
||||||
{
|
{
|
||||||
auto vv = make_intrusive<VectorVal>(id::find_type<VectorType>("ip6_options"));
|
auto vv = make_intrusive<VectorVal>(id::find_type<VectorType>("ip6_options"));
|
||||||
|
|
||||||
while ( static_cast<size_t>(len) >= sizeof(struct ip6_opt) )
|
while ( len > 0 && static_cast<size_t>(len) >= sizeof(struct ip6_opt) )
|
||||||
{
|
{
|
||||||
static auto ip6_option_type = id::find_type<RecordType>("ip6_option");
|
static auto ip6_option_type = id::find_type<RecordType>("ip6_option");
|
||||||
const struct ip6_opt* opt = (const struct ip6_opt*)data;
|
const struct ip6_opt* opt = (const struct ip6_opt*)data;
|
||||||
|
@ -81,30 +92,40 @@ RecordValPtr IPv6_Hdr::ToVal(VectorValPtr chain) const
|
||||||
|
|
||||||
case IPPROTO_HOPOPTS:
|
case IPPROTO_HOPOPTS:
|
||||||
{
|
{
|
||||||
|
uint16_t off = 2 * sizeof(uint8_t);
|
||||||
|
if ( IsOptionTruncated(off) )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
static auto ip6_hopopts_type = id::find_type<RecordType>("ip6_hopopts");
|
static auto ip6_hopopts_type = id::find_type<RecordType>("ip6_hopopts");
|
||||||
rv = make_intrusive<RecordVal>(ip6_hopopts_type);
|
rv = make_intrusive<RecordVal>(ip6_hopopts_type);
|
||||||
const struct ip6_hbh* hbh = (const struct ip6_hbh*)data;
|
const struct ip6_hbh* hbh = (const struct ip6_hbh*)data;
|
||||||
rv->Assign(0, hbh->ip6h_nxt);
|
rv->Assign(0, hbh->ip6h_nxt);
|
||||||
rv->Assign(1, hbh->ip6h_len);
|
rv->Assign(1, hbh->ip6h_len);
|
||||||
uint16_t off = 2 * sizeof(uint8_t);
|
|
||||||
rv->Assign(2, BuildOptionsVal(data + off, Length() - off));
|
rv->Assign(2, BuildOptionsVal(data + off, Length() - off));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IPPROTO_DSTOPTS:
|
case IPPROTO_DSTOPTS:
|
||||||
{
|
{
|
||||||
|
uint16_t off = 2 * sizeof(uint8_t);
|
||||||
|
if ( IsOptionTruncated(off) )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
static auto ip6_dstopts_type = id::find_type<RecordType>("ip6_dstopts");
|
static auto ip6_dstopts_type = id::find_type<RecordType>("ip6_dstopts");
|
||||||
rv = make_intrusive<RecordVal>(ip6_dstopts_type);
|
rv = make_intrusive<RecordVal>(ip6_dstopts_type);
|
||||||
const struct ip6_dest* dst = (const struct ip6_dest*)data;
|
const struct ip6_dest* dst = (const struct ip6_dest*)data;
|
||||||
rv->Assign(0, dst->ip6d_nxt);
|
rv->Assign(0, dst->ip6d_nxt);
|
||||||
rv->Assign(1, dst->ip6d_len);
|
rv->Assign(1, dst->ip6d_len);
|
||||||
uint16_t off = 2 * sizeof(uint8_t);
|
|
||||||
rv->Assign(2, BuildOptionsVal(data + off, Length() - off));
|
rv->Assign(2, BuildOptionsVal(data + off, Length() - off));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IPPROTO_ROUTING:
|
case IPPROTO_ROUTING:
|
||||||
{
|
{
|
||||||
|
uint16_t off = 4 * sizeof(uint8_t);
|
||||||
|
if ( IsOptionTruncated(off) )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
static auto ip6_routing_type = id::find_type<RecordType>("ip6_routing");
|
static auto ip6_routing_type = id::find_type<RecordType>("ip6_routing");
|
||||||
rv = make_intrusive<RecordVal>(ip6_routing_type);
|
rv = make_intrusive<RecordVal>(ip6_routing_type);
|
||||||
const struct ip6_rthdr* rt = (const struct ip6_rthdr*)data;
|
const struct ip6_rthdr* rt = (const struct ip6_rthdr*)data;
|
||||||
|
@ -112,7 +133,6 @@ RecordValPtr IPv6_Hdr::ToVal(VectorValPtr chain) const
|
||||||
rv->Assign(1, rt->ip6r_len);
|
rv->Assign(1, rt->ip6r_len);
|
||||||
rv->Assign(2, rt->ip6r_type);
|
rv->Assign(2, rt->ip6r_type);
|
||||||
rv->Assign(3, rt->ip6r_segleft);
|
rv->Assign(3, rt->ip6r_segleft);
|
||||||
uint16_t off = 4 * sizeof(uint8_t);
|
|
||||||
rv->Assign(4, new String(data + off, Length() - off, true));
|
rv->Assign(4, new String(data + off, Length() - off, true));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -192,20 +212,26 @@ RecordValPtr IPv6_Hdr::ToVal(VectorValPtr chain) const
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
{
|
{
|
||||||
|
off += sizeof(uint16_t);
|
||||||
|
if ( IsOptionTruncated(off) )
|
||||||
|
break;
|
||||||
|
|
||||||
auto m = make_intrusive<RecordVal>(ip6_mob_brr_type);
|
auto m = make_intrusive<RecordVal>(ip6_mob_brr_type);
|
||||||
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
|
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
|
||||||
off += sizeof(uint16_t);
|
|
||||||
m->Assign(1, BuildOptionsVal(data + off, Length() - off));
|
m->Assign(1, BuildOptionsVal(data + off, Length() - off));
|
||||||
msg->Assign(1, std::move(m));
|
msg->Assign(1, std::move(m));
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
|
off += sizeof(uint16_t) + sizeof(uint64_t);
|
||||||
|
if ( IsOptionTruncated(off) )
|
||||||
|
break;
|
||||||
|
|
||||||
auto m = make_intrusive<RecordVal>(ip6_mob_hoti_type);
|
auto m = make_intrusive<RecordVal>(ip6_mob_hoti_type);
|
||||||
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
|
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
|
||||||
m->Assign(1, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t)))));
|
m->Assign(1, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t)))));
|
||||||
off += sizeof(uint16_t) + sizeof(uint64_t);
|
|
||||||
m->Assign(2, BuildOptionsVal(data + off, Length() - off));
|
m->Assign(2, BuildOptionsVal(data + off, Length() - off));
|
||||||
msg->Assign(2, std::move(m));
|
msg->Assign(2, std::move(m));
|
||||||
break;
|
break;
|
||||||
|
@ -213,10 +239,13 @@ RecordValPtr IPv6_Hdr::ToVal(VectorValPtr chain) const
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
{
|
{
|
||||||
|
off += sizeof(uint16_t) + sizeof(uint64_t);
|
||||||
|
if ( IsOptionTruncated(off) )
|
||||||
|
break;
|
||||||
|
|
||||||
auto m = make_intrusive<RecordVal>(ip6_mob_coti_type);
|
auto m = make_intrusive<RecordVal>(ip6_mob_coti_type);
|
||||||
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
|
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
|
||||||
m->Assign(1, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t)))));
|
m->Assign(1, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t)))));
|
||||||
off += sizeof(uint16_t) + sizeof(uint64_t);
|
|
||||||
m->Assign(2, BuildOptionsVal(data + off, Length() - off));
|
m->Assign(2, BuildOptionsVal(data + off, Length() - off));
|
||||||
msg->Assign(3, std::move(m));
|
msg->Assign(3, std::move(m));
|
||||||
break;
|
break;
|
||||||
|
@ -224,12 +253,15 @@ RecordValPtr IPv6_Hdr::ToVal(VectorValPtr chain) const
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
{
|
{
|
||||||
|
off += sizeof(uint16_t) + 2 * sizeof(uint64_t);
|
||||||
|
if ( IsOptionTruncated(off) )
|
||||||
|
break;
|
||||||
|
|
||||||
auto m = make_intrusive<RecordVal>(ip6_mob_hot_type);
|
auto m = make_intrusive<RecordVal>(ip6_mob_hot_type);
|
||||||
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
|
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
|
||||||
m->Assign(1, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t)))));
|
m->Assign(1, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t)))));
|
||||||
m->Assign(
|
m->Assign(
|
||||||
2, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t) + sizeof(uint64_t)))));
|
2, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t) + sizeof(uint64_t)))));
|
||||||
off += sizeof(uint16_t) + 2 * sizeof(uint64_t);
|
|
||||||
m->Assign(3, BuildOptionsVal(data + off, Length() - off));
|
m->Assign(3, BuildOptionsVal(data + off, Length() - off));
|
||||||
msg->Assign(4, std::move(m));
|
msg->Assign(4, std::move(m));
|
||||||
break;
|
break;
|
||||||
|
@ -237,12 +269,15 @@ RecordValPtr IPv6_Hdr::ToVal(VectorValPtr chain) const
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
{
|
{
|
||||||
|
off += sizeof(uint16_t) + 2 * sizeof(uint64_t);
|
||||||
|
if ( IsOptionTruncated(off) )
|
||||||
|
break;
|
||||||
|
|
||||||
auto m = make_intrusive<RecordVal>(ip6_mob_cot_type);
|
auto m = make_intrusive<RecordVal>(ip6_mob_cot_type);
|
||||||
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
|
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
|
||||||
m->Assign(1, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t)))));
|
m->Assign(1, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t)))));
|
||||||
m->Assign(
|
m->Assign(
|
||||||
2, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t) + sizeof(uint64_t)))));
|
2, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t) + sizeof(uint64_t)))));
|
||||||
off += sizeof(uint16_t) + 2 * sizeof(uint64_t);
|
|
||||||
m->Assign(3, BuildOptionsVal(data + off, Length() - off));
|
m->Assign(3, BuildOptionsVal(data + off, Length() - off));
|
||||||
msg->Assign(5, std::move(m));
|
msg->Assign(5, std::move(m));
|
||||||
break;
|
break;
|
||||||
|
@ -250,6 +285,10 @@ RecordValPtr IPv6_Hdr::ToVal(VectorValPtr chain) const
|
||||||
|
|
||||||
case 5:
|
case 5:
|
||||||
{
|
{
|
||||||
|
off += 3 * sizeof(uint16_t);
|
||||||
|
if ( IsOptionTruncated(off) )
|
||||||
|
break;
|
||||||
|
|
||||||
auto m = make_intrusive<RecordVal>(ip6_mob_bu_type);
|
auto m = make_intrusive<RecordVal>(ip6_mob_bu_type);
|
||||||
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
|
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
|
||||||
m->Assign(1, static_cast<bool>(
|
m->Assign(1, static_cast<bool>(
|
||||||
|
@ -261,7 +300,6 @@ RecordValPtr IPv6_Hdr::ToVal(VectorValPtr chain) const
|
||||||
m->Assign(4, static_cast<bool>(
|
m->Assign(4, static_cast<bool>(
|
||||||
ntohs(*((uint16_t*)(msg_data + sizeof(uint16_t)))) & 0x1000));
|
ntohs(*((uint16_t*)(msg_data + sizeof(uint16_t)))) & 0x1000));
|
||||||
m->Assign(5, ntohs(*((uint16_t*)(msg_data + 2 * sizeof(uint16_t)))));
|
m->Assign(5, ntohs(*((uint16_t*)(msg_data + 2 * sizeof(uint16_t)))));
|
||||||
off += 3 * sizeof(uint16_t);
|
|
||||||
m->Assign(6, BuildOptionsVal(data + off, Length() - off));
|
m->Assign(6, BuildOptionsVal(data + off, Length() - off));
|
||||||
msg->Assign(6, std::move(m));
|
msg->Assign(6, std::move(m));
|
||||||
break;
|
break;
|
||||||
|
@ -269,13 +307,16 @@ RecordValPtr IPv6_Hdr::ToVal(VectorValPtr chain) const
|
||||||
|
|
||||||
case 6:
|
case 6:
|
||||||
{
|
{
|
||||||
|
off += 3 * sizeof(uint16_t);
|
||||||
|
if ( IsOptionTruncated(off) )
|
||||||
|
break;
|
||||||
|
|
||||||
auto m = make_intrusive<RecordVal>(ip6_mob_back_type);
|
auto m = make_intrusive<RecordVal>(ip6_mob_back_type);
|
||||||
m->Assign(0, *((uint8_t*)msg_data));
|
m->Assign(0, *((uint8_t*)msg_data));
|
||||||
m->Assign(1,
|
m->Assign(1,
|
||||||
static_cast<bool>(*((uint8_t*)(msg_data + sizeof(uint8_t))) & 0x80));
|
static_cast<bool>(*((uint8_t*)(msg_data + sizeof(uint8_t))) & 0x80));
|
||||||
m->Assign(2, ntohs(*((uint16_t*)(msg_data + sizeof(uint16_t)))));
|
m->Assign(2, ntohs(*((uint16_t*)(msg_data + sizeof(uint16_t)))));
|
||||||
m->Assign(3, ntohs(*((uint16_t*)(msg_data + 2 * sizeof(uint16_t)))));
|
m->Assign(3, ntohs(*((uint16_t*)(msg_data + 2 * sizeof(uint16_t)))));
|
||||||
off += 3 * sizeof(uint16_t);
|
|
||||||
m->Assign(4, BuildOptionsVal(data + off, Length() - off));
|
m->Assign(4, BuildOptionsVal(data + off, Length() - off));
|
||||||
msg->Assign(7, std::move(m));
|
msg->Assign(7, std::move(m));
|
||||||
break;
|
break;
|
||||||
|
@ -283,11 +324,14 @@ RecordValPtr IPv6_Hdr::ToVal(VectorValPtr chain) const
|
||||||
|
|
||||||
case 7:
|
case 7:
|
||||||
{
|
{
|
||||||
|
off += sizeof(uint16_t) + sizeof(in6_addr);
|
||||||
|
if ( IsOptionTruncated(off) )
|
||||||
|
break;
|
||||||
|
|
||||||
auto m = make_intrusive<RecordVal>(ip6_mob_be_type);
|
auto m = make_intrusive<RecordVal>(ip6_mob_be_type);
|
||||||
m->Assign(0, *((uint8_t*)msg_data));
|
m->Assign(0, *((uint8_t*)msg_data));
|
||||||
const in6_addr* hoa = (const in6_addr*)(msg_data + sizeof(uint16_t));
|
const in6_addr* hoa = (const in6_addr*)(msg_data + sizeof(uint16_t));
|
||||||
m->Assign(1, make_intrusive<AddrVal>(IPAddr(*hoa)));
|
m->Assign(1, make_intrusive<AddrVal>(IPAddr(*hoa)));
|
||||||
off += sizeof(uint16_t) + sizeof(in6_addr);
|
|
||||||
m->Assign(2, BuildOptionsVal(data + off, Length() - off));
|
m->Assign(2, BuildOptionsVal(data + off, Length() - off));
|
||||||
msg->Assign(8, std::move(m));
|
msg->Assign(8, std::move(m));
|
||||||
break;
|
break;
|
||||||
|
|
3
src/IP.h
3
src/IP.h
|
@ -151,6 +151,9 @@ public:
|
||||||
protected:
|
protected:
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
const u_char* data;
|
const u_char* data;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool IsOptionTruncated(uint16_t off) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class IPv6_Hdr_Chain
|
class IPv6_Hdr_Chain
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue