There are some functions that are so frequently used, it doesn't make sense for each software developer to write their own code. Reading files, downloading web pages, drawing a red circle on the screen, and looking up Internet addresses are a few examples. Instead of every developer writing their own way to handle these operations, they are written once and stored in a library for reuse by anyone.
GNU C Library, aka glibc, is such a library of commonly-used functions for software written in the C language to run in Linux. Its "getaddrinfo()" function is used by the client side DNS resolver, a service that translates human-friendly websites names into computer-friendly network addresses.
This function has a flaw: when making a DNS request, it allocates 2048 bytes of memory for the answer, but does not check that the answer it receives fits in that buffer. A malicious DNS server or a man-in-the-middle attacker could provide a DNS answer that is larger than 2048 bytes, overflowing the buffer and potentially allowing the attacker to execute malicious commands.
Here's the rub: glibc isn't just one program: it's a library used by untold numbers of programs. Depending on the developer's choices it may be embedded in the compiled program, or the program may make use of the library installed on the operating system. In the latter case, patches are available for many Linux distributions to fix the bug. In the former case however, the software developer must patch the library themselves and recompile the software.
The saving grace is, most consumers may not be affected. Most home routers, Blu-ray players, media streaming devices, and other Internet of Things devices are built on Linux - but often a tiny distribution such as BusyBox designed for embedded operating systems. These distributions use alternatives to glibc that may not be affected. Specifically, the uClibc library popular in embedded devices was fixed in 2010. Android is not affected as it uses the non-vulnerable Bionic library. iOS uses yet another library (BSD running libc rather than glibc); as of this writing I have not found confirmation that iOS is or is not vulnerable.
Links:
- Google Project Zero (initial discovery)
- Proof of Concept exploit
- ARS Technica coverage
- Threatpost coverage
- Darknet coverage
- glibc patch details
- Ubuntu security notice and patches
- RedHat Linux advisory and patch details
- Debian security advisory
- Amazon Linux (AWS) security advisory
- SUSE Linux security advisory
- uClibc patch details (from 2010)
Update: since the vulnerability exists when maliciously large DNS answers are provided by an attacker, one way to prevent exploit is to block those malicious DNS answers. There are several ways to do this, but perhaps the simplest is to limit DNS to a known provider, and block anything else.
I prefer OpenDNS' Family Shield product - it lets me block known malicious content as well as other categories I don't want myself of my family exposed to (pornography, nudity, sexuality, and "tasteless" content (which OpenDNS describes as sites that contain torture, mutilation, horror, or the grotesque, as well as pro-suicide and pro-anorexia content).
OpenDNS has publicly stated that their DNS software does not use the vulnerable glibc library, and that they have validity checks that prevent them from passing malicious DNS responses from a third party back to you.
OpenDNS has publicly stated that their DNS software does not use the vulnerable glibc library, and that they have validity checks that prevent them from passing malicious DNS responses from a third party back to you.
The following iptables rules will allow DNS traffic to and from the OpenDNS server, while blocking anything else using TCP or UDP 53 (the network port corresponding to DNS requests and answers).
iptables -I FORWARD -p udp --dport 53 -j DROP
iptables -I FORWARD -p udp --sport 53 -j DROP
iptables -I FORWARD -p tcp --dport 53 -j DROP
iptables -I FORWARD -p tcp --sport 53 -j DROP
iptables -I FORWARD -d 208.67.220.123 -p udp --dport 53 -j ACCEPT
iptables -I FORWARD -d 208.67.222.123 -p udp --dport 53 -j ACCEPT
iptables -I FORWARD -s 208.67.220.123 -p udp --sport 53 -j ACCEPT
iptables -I FORWARD -s 208.67.222.123 -p udp --sport 53 -j ACCEPT