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

system/2201: overflowable buffer in rpc.yppasswdd with -m option




>Number:         2201
>Category:       system
>Synopsis:       overflowable buffer in rpc.yppasswdd with -m option
>Confidential:   yes
>Severity:       non-critical
>Priority:       low
>Responsible:    bugs
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Nov 26 10:30:02 MST 2001
>Last-Modified:
>Originator:     jose
>Organization:
net
>Release:        3.0-current
>Environment:
	System      : OpenBSD 3.0
	Architecture: OpenBSD.i386
	Machine     : i386
>Description:
hi guys

small overflowable buffer in /usr/libexec/rpc.yppasswdd with the -m
argument. the code looks like it was never audited (ie CVS tags with
1997 dates). the suspect code fragment is here:

(CVS tag:  $OpenBSD: rpc.yppasswdd.c,v 1.9 1997/08/19 07:00:51 niklas Exp $)

     59 char    make_arg[1024] = "make";
                /* SNIP */
     74 int
     75 main(argc, argv)
     76         int     argc;
     77         char   *argv[];
     78 {
     79         SVCXPRT *transp;
     80         int     i = 1;
     81
     82         while (i < argc) {
     83                 if (argv[i][0] == '-') {
                        /* SNIP */
     90                         } else if (strcmp("-m", argv[i]) == 0) {
     91                                 domake = 1;
     92                                 while (i < argc) {
     93                                         strcat(make_arg, " ");
     94                                         strcat(make_arg, argv[i]);
     95                                         i++;
     96                                 }
                        /* SNIP */
    106         }

we enter a while loop in like 92 with an arbitrary endpoint, argc. this
is then used to strcat() a constant space (line 93) and the value of
the argument in line 94. this is appended to the char make_arg, which at
line 59 was set to a fixed buffer size of 1024.

furthermore this argument is used later on in a system() call:

file: /usr/src/libexec/rpc.yppasswdd/yppasswdd_mkpw.c
$OpenBSD: yppasswdd_mkpw.c,v 1.21 2001/08/17 14:04:36 espie Exp $

    230         if (fork() == 0) {
    231                 chdir("/var/yp");
    232                 (void)umask(022);
    233                 system(make_arg);
    234                 exit(0);
    235         }

make_arg is never sanitized in this executable.

long story short: while this is overflowable and a tainted source of input
(make_arg), its not suid root nor is it remotly callable with the -m
option. this isn't a security concern, but it's a quality issue, worth
fixing.

>How-To-Repeat:
its trivial to overflow this leading to a segfault:

$ rpc.yppasswdd -m `perl -e 'print "A"x4000'`
Memory fault (core dumped)

here's a gdb of it really quick:

$ gdb /usr/src/libexec/rpc.yppasswdd/rpc.yppasswdd
GNU gdb 4.16.1
Copyright 1996 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-unknown-openbsd3.0"...
(gdb) set args -m `perl -e 'print "A"x4000'`
(gdb) run
Starting program: /usr/src/libexec/rpc.yppasswdd/rpc.yppasswdd -m `perl -e 'prin
t "A"x4000'`

Program received signal SIGSEGV, Segmentation fault.
0x40088819 in strcat ()
(gdb) bt
#0  0x40088819 in strcat ()
#1  0x4284 in make_arg ()

>Fix:
here is a patch for rpc.yppasswdd.c (stolen, in large measure, from
netbsd's patch to the code):

--- rpc.yppasswdd.c.orig        Mon Nov 26 12:09:42 2001
+++ rpc.yppasswdd.c     Mon Nov 26 12:12:48 2001
@@ -88,10 +88,19 @@
                        } else if (strcmp("-nopw", argv[i]) == 0) {
                                nopw = 1;
                        } else if (strcmp("-m", argv[i]) == 0) {
+                               int len;
                                domake = 1;
+
+                               len = strlen(make_arg);
                                while (i < argc) {
+                                       int arglen;
+
+                                       arglen = strlen(argv[i]);
+                                       if ((len + arglen) > (sizeof(make_arg)-2))
+                                               errx(EXIT_FAILURE, strerror(E2BIG));
                                        strcat(make_arg, " ");
                                        strcat(make_arg, argv[i]);
+                                       len += arglen;
                                        i++;
                                }
                        } else if (strcmp("-d", argv[i]) == 0


____________________________
jose nazario						     jose@cwru.edu
	      	     PGP: 89 B0 81 DA 5B FD 7E 00  99 C3 B2 CD 48 A0 07 80
				       PGP key ID 0xFD37F4E5 (pgp.mit.edu)

>Audit-Trail:
>Unformatted:
X-sendbug-version: 3.97