This is the mail archive of the newlib@sources.redhat.com mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Security Problem ( Buffer Overflow) in newlib


Hello Cygwin-Friends,

I made some C/C++ experiments with Cygwin and found an Buffer Overflow
problem in the newlib library. I have a CVS snapshot
"cygwin-src-20010907.tar.bz2" of Cygwin/Newlib, but the problem isn't
new.

Let us take a look at newlib/libc/unix/getpwent.c:

Line 13-19:
-------------------------------------------------------------------
static char logname[8];
static char password[1024];
static char gecos[1024];
static char dir[1024];
static char shell[1024];
-------------------------------------------------------------------

Line 33-37:
-------------------------------------------------------------------
      sscanf (buf, "%[^:]:%[^:]:%d:%d:%[^:]:%[^:]:%s\n",
	      logname, password, &pw_passwd.pw_uid,
             &pw_passwd.pw_gid, gecos,
	      dir, shell);
-------------------------------------------------------------------

We see, that there is no length checking.

One example for a buffer overflow:

1) Cygwin is installed as "administrator", so /etc/passwd contains:
   administator:x:1111:2222:Administrator:/home/administrator:/bin/bash

2) The word "Administrator" has 13 characters, but logname[8] has only
   7 characters plus '\0'.

I suggest to dynamically resize logname, password, dir and shell. As
an (not so nice) alternative we can check the length and cut for
instance logname after xy characters.

For testing I uses the following entry in /etc/passwd:
-------------------------------------------------------------------
administator:x:3333:100:Administrator:/home/administrator:/bin/bash
-------------------------------------------------------------------

and the following C program (runs on Cygwin and Linux):
-------------------------------------------------------------------
#include <pwd.h>

int main(int argc, char *argv[])
{
  struct passwd *pw;
  if(argc!=2) {
      printf("usage: %s loginname\n",argv[0]);
      return 1;
  }
  pw=getpwnam(argv[1]);
  if(pw) {
      printf("char  *pw_name:               %s\n",pw->pw_name);
      printf("char  *pw_passwd:             %s\n",pw->pw_passwd);
      printf("int   pw_uid:                 %d\n",pw->pw_uid);
      printf("int   pw_gid:                 %d\n",pw->pw_gid);
      /* on Linux there is no pw_comment */
      /*printf("char  *pw_comment:            %s\n",pw->pw_comment);*/
      printf("char  *pw_gecos:              %s\n",pw->pw_gecos);
      printf("char  *pw_dir:                %s\n",pw->pw_dir);
      printf("char  *pw_shell:              %s\n",pw->pw_shell);
  }
  else {
      printf("Could not find %s !\n",argv[1]);
      return 2;
  }
  return 0;
}
-------------------------------------------------------------------

Bye, Björn

--
Björn Voigt <bjoern@cs.tu-berlin.de>
WWW:     http://user.cs.tu-berlin.de/~bjoern/




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]