[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: