|
|||||||||||
|
Re: security audit: yp_access.c
From: Bill Paul <wpaul>
Date: Sun Feb 16 1997 - 15:03:10 EST
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. :) 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):
#ifndef lint
extern int debug;
#ifndef lint
extern int debug;
/*
+ * 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; /*
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;
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 |
||||||||||
|
|||||||||||