diff --git a/cve-2020-16898.lua b/cve-2020-16898.lua index c065e9c..1f62570 100644 --- a/cve-2020-16898.lua +++ b/cve-2020-16898.lua @@ -25,15 +25,22 @@ function match(args) -- ICMPv6 Options start at byte 17 of the ICMPv6 payload. offset = offset + 16 + + -- Continue looking for Options until we've run out of packet bytes. while offset < string.len(packet) do + -- We're only interested in RDNSS Options (Type = 25). local option_type = tonumber(packet:byte(offset)) + + -- The Option's Length field counts in 8-byte increments, so Length = 2 means the Option is 16 bytes long. offset = offset + 1 local length = tonumber(packet:byte(offset)) -- The vulnerability is exercised when an even length value is in an RDNSS Option. if option_type == 25 and length > 3 and (length % 2) == 0 then return 1 + + -- Otherwise, move to the start of the next Option, if present. else offset = offset + (length * 8) - 1 end diff --git a/cve-2020-16898.rules b/cve-2020-16898.rules index 982c4d3..249f73b 100644 --- a/cve-2020-16898.rules +++ b/cve-2020-16898.rules @@ -1 +1 @@ -alert icmp any any -> any any (msg:"Potential CVE-2020-16898 Exploit"; lua:cve-2020-16898.lua; sid:202016898; rev:1;) +alert icmp any any -> any any (msg:"Potential CVE-2020-16898 Exploit"; lua:cve-2020-16898.lua; sid:202016898; rev:1;) \ No newline at end of file diff --git a/cve-2020-16899.lua b/cve-2020-16899.lua new file mode 100755 index 0000000..0d1a927 --- /dev/null +++ b/cve-2020-16899.lua @@ -0,0 +1,83 @@ +function init(args) + local needs = {} + needs["packet"] = tostring(true) + return needs +end + +function match(args) + local packet = args["packet"] + if packet == nil then + print("Packet buffer empty! Aborting...") + return 0 + end + + -- SCPacketPayload starts at byte 5 of the ICMPv6 header, so we use the packet buffer instead. + local buffer = SCPacketPayload() + local search_str = string.sub(buffer, 1, 8) + local s, _ = string.find(packet, search_str) + local offset = s - 4 + + -- Only inspect Router Advertisement (Type = 134) ICMPv6 packets. + local type = tonumber(packet:byte(offset)) + if type ~= 134 then + return 0 + end + + -- ICMPv6 Options start at byte 17 of the ICMPv6 payload. + offset = offset + 16 + + -- Continue looking for Options until we've run out of packet bytes. + while offset < string.len(packet) do + + -- We're only interested in DNSSL Options (Type = 31). + local option_type = tonumber(packet:byte(offset)) + + -- The Option's Length field counts in 8-byte increments, so Length = 2 means the Option is 16 bytes long. + offset = offset + 1 + local length = tonumber(packet:byte(offset)) + + -- The vulnerability is exercised when Length is greater than 35 for a DNSSL Option. + if option_type == 31 and length >= 35 then + + -- Move to the DNS Search List field, skipping over Reserved (2 bytes) and Lifetime (4 bytes). + offset = offset + 7 + + -- Compute the last byte of the Search List and ensure we have enough bytes remaining in our buffer. + local end_of_option = offset + ((length - 1) * 8) - 1 + if end_of_option > string.len(packet) then + return 0 + end + + -- Calculate the length of each DNS name (including padding) and flag any with length >= 264 bytes. + while offset <= end_of_option do + + -- Holds the length of the current DNS name being read. + local dns_name_len = 0 + + -- Count the bytes of the DNS name (non-null). + while offset <= string.len(packet) and tonumber(packet:byte(offset)) ~= 0 do + dns_name_len = dns_name_len + 1 + offset = offset + 1 + end + + -- Count the bytes of the null padding. + while offset <= string.len(packet) and tonumber(packet:byte(offset)) == 0 do + dns_name_len = dns_name_len + 1 + offset = offset + 1 + end + + -- If the total length of the DNS name with padding is 264 bytes or greater, flag the packet. + if dns_name_len >= 264 then + return 1 + end + end + + -- Otherwise, move to the start of the next Option, if present. + else + offset = offset + (length * 8) - 1 + end + end + + -- If no malicious data is found, return 0. + return 0 +end diff --git a/cve-2020-16899.rules b/cve-2020-16899.rules new file mode 100755 index 0000000..064634f --- /dev/null +++ b/cve-2020-16899.rules @@ -0,0 +1 @@ +alert icmp any any -> any any (msg:"Potential CVE-2020-16899 Exploit"; lua:cve-2020-16899.lua; sid:202016899; rev:1;) \ No newline at end of file