CVE-2016-1245 (published 2017-02-22T23:59Z)

It was discovered that the zebra daemon in Quagga before 1.0.20161017 suffered from a stack-based buffer overflow when processing IPv6 Neighbor Discovery messages. The root cause was relying on BUFSIZ to be compatible with a message size; however, BUFSIZ is system-dependent.

Severity: HIGH
CVSS v2 base score: 7.5 (AV:N/AC:L/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 9.8, CRITICAL (CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-119
cwe_name: Improper Restriction of Operations within the Bounds of a Memory Buffer
description: The product performs operations on a memory buffer, but it reads from or writes to a memory location outside the buffer's intended boundary. This may result in read or write operations on unexpected memory locations that could be linked to other variables, data structures, or internal program data.
extended_description: 
            Certain languages allow direct addressing of memory locations and do not automatically ensure that these locations are valid for the memory buffer that is being referenced. This can cause read or write operations to be performed on memory locations that may be associated with other variables, data structures, or internal program data.
         
         

Fix information:
repo_url: https://github.com/Quagga/quagga
commit_details: repo_url: https://github.com/Quagga/quagga
author: David Lamparter
author_date: 2016-08-31 13:31:16+02:00
msg: zebra: stack overrun in IPv6 RA receive code (CVE-2016-1245)

The IPv6 RA code also receives ICMPv6 RS and RA messages.
Unfortunately, by bad coding practice, the buffer size specified on
receiving such messages mixed up 2 constants that in fact have
different values.

The code itself has:
 #define RTADV_MSG_SIZE 4096
While BUFSIZ is system-dependent, in my case (x86_64 glibc):
 /usr/include/_G_config.h:#define _G_BUFSIZ 8192
 /usr/include/libio.h:#define _IO_BUFSIZ _G_BUFSIZ
 /usr/include/stdio.h:# define BUFSIZ _IO_BUFSIZ

FreeBSD, OpenBSD, NetBSD and Illumos are not affected, since all of them
have BUFSIZ == 1024.

As the latter is passed to the kernel on recvmsg(), it's possible to
overwrite 4kB of stack -- with ICMPv6 packets that can be globally sent
to any of the system's addresses (using fragmentation to get to 8k).

(The socket has filters installed limiting this to RS and RA packets,
but does not have a filter for source address or TTL.)

Issue discovered by trying to test other stuff, which randomly caused
the stack to be smaller than 8kB in that code location, which then
causes the kernel to report EFAULT (Bad address).

Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Reviewed-by: Donald Sharp <sharpd@cumulusnetworks.com>
repository: repo_url: https://github.com/Quagga/quagga
repo_name: Quagga/quagga
description: Quagga Tracking repository - Master is at http://git.savannah.gnu.org/cgit/quagga.git
repo_language: C
owner: Quagga
file_changes: filename: rtadv.c
change_type: ModificationType.MODIFY
diff: @@ -482,7 +482,7 @@ rtadv_read (struct thread *thread)
   /* Register myself. */
   rtadv_event (zvrf, RTADV_READ, sock);
 
-  len = rtadv_recv_packet (sock, buf, BUFSIZ, &from, &ifindex, &hoplimit);
+  len = rtadv_recv_packet (sock, buf, sizeof (buf), &from, &ifindex, &hoplimit);
 
   if (len < 0) 
     {

programming_language: C