From d04e2e825ae5c34fb29e3275949fa1f44e227312 Mon Sep 17 00:00:00 2001 From: david Date: Wed, 27 Jan 2010 01:16:14 +0000 Subject: [PATCH] Use a bigger buffer to read IP addresses from /etc/resolv.conf (to acommonate IPv6 addresses) and make the sscanf format size match the buffer size (to avoid smashing the stack). The format string is constructed dynamically to the size of the buffer with Snprintf. Gunnar Lindberg reported this problem; discussion starts at http://seclists.org/nmap-dev/2010/q1/250. --- CHANGELOG | 6 ++++++ nmap_dns.cc | 8 ++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 5695d710c..e84fb0523 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,11 @@ # Nmap Changelog ($Id$); -*-text-*- +o Fixed a stack overflow that would happen when a nameserver entry in + /etc/resolv.conf contained more than 16 bytes, as could legitimately + happen with an IPv6 address. Gunnar Lindberg reported the problem + and contributed an initial patch, then Brandon and Kris refined and + implemented it. + o [Zenmap] Added a workaround for a Ubuntu Python packaging idiosyncrasy. As of version python2.6-2.6.4-0ubuntu3, Ubuntu's distutils modifies self.prefix, a variable we use in the setup.py script. This would diff --git a/nmap_dns.cc b/nmap_dns.cc index d82f28da6..e74fd85a2 100644 --- a/nmap_dns.cc +++ b/nmap_dns.cc @@ -937,7 +937,8 @@ void win32_read_registry(char *controlset) { static void parse_resolvdotconf() { FILE *fp; char buf[2048], *tp; - char ipaddr[16]; + char fmt[32]; + char ipaddr[INET6_ADDRSTRLEN]; fp = fopen("/etc/resolv.conf", "r"); if (fp == NULL) { @@ -945,6 +946,9 @@ static void parse_resolvdotconf() { return; } + /* Customize a sscanf format to sizeof(ipaddr). */ + Snprintf(fmt, sizeof(fmt), "nameserver %%%us", sizeof(ipaddr)); + while (fgets(buf, sizeof(buf), fp)) { tp = buf; @@ -956,7 +960,7 @@ static void parse_resolvdotconf() { // Skip any leading whitespace while (*tp == ' ' || *tp == '\t') tp++; - if (sscanf(tp, "nameserver %65s", ipaddr) == 1) add_dns_server(ipaddr); + if (sscanf(tp, fmt, ipaddr) == 1) add_dns_server(ipaddr); } fclose(fp);