Pantek Library
Hosting Provided By
CybrHost
High Speed Hosting

Re: security audit: yp_access.c

From: Bill Paul <wpaul>
Date: Sun Feb 16 1997 - 15:03:10 EST


>
> [Resent due to mail problem]

Yes, you would need to break root before being able to exploit this to break root (unless the sysadmin is a dolt and left the securenets file world writable).

> ... but we fix it anyway, right?

Of course. :)

> #define LINEBUFSZ 1024

I tried to make ypserv on my machine throw up by creating a securenets entry with a ridiculously long garbage network address. Curiously, ypserv did not crash, though it did flag the entry as bogus. I'm not sure how this can be: if addr1 and addr2 are on the stack, then making the first string be several hundred characters of garbage should have overwritten the stack and caused ypserv to die rather violently.

In any event, this is a bug. I think the right thing to do here is to turn addr1 and addr2 into pointers and manipulate linebuf in place. Here's my attempt at creating a bulletproof mechanism for doing this (ignore the diffs between the rcsid strings: these are from my own sources at home which have different revision numbers):

  • 1.2 1996/12/27 04:52:52 --- 1.3 1997/02/16 19:44:27
  • 53,59 **** #endif

  #ifndef lint
! static const char rcsid[] = "$Id: yp_access.c,v 1.2 1996/12/27 04:52:52 wpaul Exp $";   #endif   

Do you need help?X

  extern int debug;
--- 53,59 ----
  #endif   

  #ifndef lint
! static const char rcsid[] = "$Id: yp_access.c,v 1.3 1997/02/16 19:44:27 wpaul Exp $";   #endif   

  extern int debug;


  • 104,109 **** --- 104,146 ---- #define LINEBUFSZ 1024
  /*
+  * Find string in buffer, ignoring possible leading and
+  * trailing whitespace and making sure result is NUL terminated.
+  */
+ static char *yp_getstr(linebuf, len)
+ 	char *linebuf;
+ {
+ 	char *p1;
+ 	char *p2;
+ 
+ 	if (linebuf == NULL || !len)
+ 		return(NULL);
+ 
+ 	/* Skip leading white space. */
+ 	p1 = linebuf;
+ 	while(isspace(*p1)) {
+ 		if (p1 == linebuf + len)
+ 			return(NULL);
+ 		if (*p1 == '\n' || *p1 == '\0')
+ 			return(NULL);
+ 		p1++;
+ 	}
+ 
+ 	/* Find end of string. */
+ 	p2 = p1;
+ 	while(!isspace(*p2)) {
+ 		if (p2 == linebuf + len)
+ 			return(NULL);
+ 		if (*p2 == '\n' || *p2 == '\0')
+ 			break;
+ 		p2++;
+ 	}
+ 
+ 	*p2 = '\0';
+ 	return(p1);
+ }

+
+ /*
   * Read /var/yp/securenets file and initialize the securenets
   * list. If the file doesn't exist, we set up a dummy entry that
   * allows all hosts to connect.
***************

*** 112,118 ****
  {
  	FILE *fp;
  	char path[MAXPATHLEN + 2];
! 	char linebuf[1024 + 2];
  	struct securenet *tmp;
  
  	/*

--- 149,155 ----
  {
  	FILE *fp;
  	char path[MAXPATHLEN + 2];
! 	char linebuf[LINEBUFSZ + 2];
  	struct securenet *tmp;
  
  	/*

  • 144,168 **** securenets = NULL;
  	while(fgets(linebuf, LINEBUFSZ, fp)) {
! 		char addr1[20], addr2[20];
  
  		if (linebuf[0] == '#')
  			continue;
! 		if (sscanf(linebuf, "%s %s", addr1, addr2) < 2) {
  			yp_error("badly formatted securenets entry: %s",
! 							linebuf);
! 			continue;
  		}
  
  		tmp = (struct securenet *)malloc(sizeof(struct securenet));
  
! 		if (!inet_aton((char *)&addr1, (struct in_addr *)&tmp->net)) {
  			yp_error("badly formatted securenets entry: %s", addr1);
  			free(tmp);
  			continue;
  		}
  
! 		if (!inet_aton((char *)&addr2, (struct in_addr *)&tmp->mask)) {
  			yp_error("badly formatted securenets entry: %s", addr2);
  			free(tmp);
  			continue;
--- 181,218 ----
  	securenets = NULL;
Do you need more help?X
while(fgets(linebuf, LINEBUFSZ, fp)) { ! char *addr1, *addr2; ! char *p; ! int l; if (linebuf[0] == '#') continue; ! ! p = linebuf; ! l = LINEBUFSZ; ! if ((addr1 = yp_getstr(p, l)) == NULL) { yp_error("badly formatted securenets entry: %s", ! linebuf); ! continue; ! } ! ! p = addr1 + strlen(addr1) + 1; ! l = LINEBUFSZ - (p - (char *)&linebuf); ! if ((addr2 = yp_getstr(p, l)) == NULL) { ! yp_error("badly formatted securenets entry: %s", ! linebuf); ! continue; } tmp = (struct securenet *)malloc(sizeof(struct securenet)); ! if (!inet_aton(addr1, (struct in_addr *)&tmp->net)) { yp_error("badly formatted securenets entry: %s", addr1); free(tmp); continue; } ! if (!inet_aton(addr2, (struct in_addr *)&tmp->mask)) { yp_error("badly formatted securenets entry: %s", addr2); free(tmp); continue;

I didn't try rejecting cruft after LINEBUFSZ bytes, though that shouldn't be too hard.

-Bill Received on Sun Feb 16 12:03:10 1997

This archive was generated by hypermail 2.1.8 : Wed Aug 23 2006 - 12:41:04 EDT


Contact Us  Legal Notices  Order Services Online 
Pantek Home  Privacy Policy  IT news  Site Map  Pantek Library