Add mitigation for CVE-2015-0235 (bug #68925)

This commit is contained in:
Stanislav Malyshev 2015-01-31 18:59:18 -08:00
parent d8803d8147
commit 457367e0b6
5 changed files with 47 additions and 5 deletions

View File

@ -9,6 +9,10 @@
#include <arpa/inet.h>
#endif
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 255
#endif
extern int php_string_to_if_index(const char *val, unsigned *out);
#if HAVE_IPV6
@ -90,7 +94,7 @@ int php_set_inet_addr(struct sockaddr_in *sin, char *string, php_socket *php_soc
if (inet_aton(string, &tmp)) {
sin->sin_addr.s_addr = tmp.s_addr;
} else {
if (! (host_entry = gethostbyname(string))) {
if (strlen(string) > MAXHOSTNAMELEN || ! (host_entry = gethostbyname(string))) {
/* Note: < -10000 indicates a host lookup error */
#ifdef PHP_WIN32
PHP_SOCKET_ERROR(php_sock, "Host lookup failed", WSAGetLastError());

View File

@ -221,6 +221,12 @@ PHP_FUNCTION(gethostbyname)
return;
}
if(hostname_len > MAXHOSTNAMELEN) {
/* name too long, protect from CVE-2015-0235 */
php_error_docref(NULL, E_WARNING, "Host name is too long, the limit is %d characters", MAXHOSTNAMELEN);
RETURN_STRINGL(hostname, hostname_len);
}
RETURN_STR(php_gethostbyname(hostname));
}
/* }}} */
@ -239,6 +245,12 @@ PHP_FUNCTION(gethostbynamel)
return;
}
if(hostname_len > MAXHOSTNAMELEN) {
/* name too long, protect from CVE-2015-0235 */
php_error_docref(NULL, E_WARNING, "Host name is too long, the limit is %d characters", MAXHOSTNAMELEN);
RETURN_FALSE;
}
hp = gethostbyname(hostname);
if (hp == NULL || hp->h_addr_list == NULL) {
RETURN_FALSE;

View File

@ -0,0 +1,13 @@
--TEST--
Bug #68925 (CVE-2015-0235 GHOST: glibc gethostbyname buffer overflow)
--FILE--
<?php
var_dump(gethostbyname(str_repeat("0", 2501)));
var_dump(gethostbynamel(str_repeat("0", 2501)));
?>
--EXPECTF--
Warning: gethostbyname(): Host name is too long, the limit is 256 characters in %s/bug68925.php on line %d
string(2501) "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
Warning: gethostbynamel(): Host name is too long, the limit is 256 characters in %s/bug68925.php on line %d
bool(false)

View File

@ -24,7 +24,7 @@
#include "php.h"
#include <stddef.h>
#include <errno.h>
#ifdef PHP_WIN32
@ -105,6 +105,10 @@ const struct in6_addr in6addr_any = {0}; /* IN6ADDR_ANY_INIT; */
# define PHP_TIMEOUT_ERROR_VALUE ETIMEDOUT
#endif
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 255
#endif
#if HAVE_GETADDRINFO
#ifdef HAVE_GAI_STRERROR
# define PHP_GAI_STRERROR(x) (gai_strerror(x))
@ -246,7 +250,12 @@ PHPAPI int php_network_getaddresses(const char *host, int socktype, struct socka
#else
if (!inet_aton(host, &in)) {
/* XXX NOT THREAD SAFE (is safe under win32) */
host_info = gethostbyname(host);
if(strlen(host) > MAXHOSTNAMELEN) {
host_info = NULL;
errno = E2BIG;
} else {
host_info = gethostbyname(host);
}
if (host_info == NULL) {
if (error_string) {
error_string = strpprintf(0, "php_network_getaddresses: gethostbyname failed. errno=%d", errno);

View File

@ -616,7 +616,11 @@ int fcgi_listen(const char *path, int backlog)
if (sa.sa_inet.sin_addr.s_addr == INADDR_NONE) {
struct hostent *hep;
hep = gethostbyname(host);
if(strlen(host) > MAXHOSTNAMELEN) {
hep = NULL;
} else {
hep = gethostbyname(host);
}
if (!hep || hep->h_addrtype != AF_INET || !hep->h_addr_list[0]) {
fprintf(stderr, "Cannot resolve host name '%s'!\n", host);
return -1;
@ -820,7 +824,7 @@ static inline ssize_t safe_read(fcgi_request *req, const void *buf, size_t count
if (!req->tcp) {
unsigned int in_len = tmp > UINT_MAX ? UINT_MAX : (unsigned int)tmp;
ret = read(req->fd, ((char*)buf)+n, in_len);
} else {
int in_len = tmp > INT_MAX ? INT_MAX : (int)tmp;