Bug#139879: nscd reverse-lookup exploit (bug 120059 revisited)
Hi
I had the same problem:
~# host ensim.rackshack.net
ensim.rackshack.net A 127.0.0.1
~# host 127.0.0.1
Name: ensim.rackshack.net
Address: 127.0.0.1
Solution is simple - during gethostbyname nscd inserts into cache
domain(key) -> ip(data) AND ip(key) -> domain(data). We need to separate
ip(key) -> domain(data) insertion only for gethostbyaddr.
nscd from glibc_2.2.5-11:
diff -u nscd-2.2.5.old/hstcache.c nscd-2.2.5/hstcache.c
--- nscd-2.2.5.old/hstcache.c Tue Mar 11 07:56:09 2003
+++ nscd-2.2.5/hstcache.c Tue Mar 11 10:58:48 2003
@@ -36,7 +36,8 @@
#include "nscd.h"
#include "dbg_log.h"
-
+#define BY_ADDR 1
+#define BY_NAME 0
/* This is the standard reply in case the service is disabled. */
static const hst_response_header disabled =
@@ -88,7 +89,7 @@
static void
-cache_addhst (struct database *db, int fd, request_header *req, void *key,
+cache_addhst (int whatby, struct database *db, int fd, request_header *req, void *key,
struct hostent *hst, uid_t owner)
{
ssize_t total;
@@ -219,6 +220,7 @@
handle and it is more than questionable whether it is
worthwhile complicating the cache handling just for handling
such a special case. */
+if (whatby==BY_NAME) {
if (hst->h_addr_list[1] == NULL)
for (cnt = 0; cnt < h_aliases_cnt; ++cnt)
{
@@ -231,7 +233,8 @@
aliases += h_aliases_len[cnt];
}
-
+}
+if (whatby==BY_ADDR) {
/* Next the normal addresses. */
for (cnt = 0; cnt < h_addr_list_cnt; ++cnt)
{
@@ -239,7 +242,8 @@
data, 0, t, db, owner);
addresses += hst->h_length;
}
-
+}
+if (whatby==BY_NAME) {
/* If necessary the IPv6 addresses. */
if (addr_list_type == GETHOSTBYADDR)
for (cnt = 0; cnt < h_addr_list_cnt; ++cnt)
@@ -248,7 +252,6 @@
data, 0, t, db, owner);
addresses += IN6ADDRSZ;
}
-
/* Avoid adding names if more than one address is available. See
above for more info. */
if (hst->h_addr_list[1] == NULL)
@@ -270,6 +273,7 @@
cache_add (GETHOSTBYNAMEv6, data->strdata, h_name_len, data,
total, data, 1, t, db, owner);
}
+}
pthread_rwlock_unlock (&db->lock);
}
@@ -349,7 +353,7 @@
if (secure[hstdb])
seteuid (oldeuid);
- cache_addhst (db, fd, req, key, hst, uid);
+ cache_addhst (BY_NAME, db, fd, req, key, hst, uid);
if (use_malloc)
free (buffer);
@@ -426,7 +430,7 @@
if (secure[hstdb])
seteuid (oldeuid);
- cache_addhst (db, fd, req, key, hst, uid);
+ cache_addhst_addr (BY_ADDR, db, fd, req, key, hst, uid);
if (use_malloc)
free (buffer);
@@ -504,7 +508,7 @@
if (secure[hstdb])
seteuid (oldeuid);
- cache_addhst (db, fd, req, key, hst, uid);
+ cache_addhst (BY_NAME, db, fd, req, key, hst, uid);
if (use_malloc)
free (buffer);
@@ -581,7 +585,7 @@
if (secure[hstdb])
seteuid (oldeuid);
- cache_addhst (db, fd, req, key, hst, uid);
+ cache_addhst (BY_ADDR, db, fd, req, key, hst, uid);
if (use_malloc)
free (buffer);
Reply to: