[489] in linux-security and linux-alert archive

home help back first fref pref prev next nref lref last post

Re: Another possible problem with ld.so?

daemon@ATHENA.MIT.EDU (Joshua Cowan)
Sun Nov 12 17:02:14 1995

Date: Fri, 10 Nov 1995 02:39:43 -0600
From: Joshua Cowan <jcowan@jcowan.reslife.okstate.edu>
To: Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl>
Cc: linux-security@tarsier.cv.nrao.edu
In-Reply-To: <199511091347.OAA05638@i17linuxb.ists.pwr.wroc.pl>

[Mod: The author is looking for opinions/criticisms from the list before
he does anything more with this code.  Please direct all responses to
the post's author--not to the list.  (Joshua can summarize any
criticisms that he receives and post them to the list in the future, if
he feels that they are worth distributing.)  I have not reviewed this
code for functionality myself; I've only looked over the concept of what
it's doing and figured that I'd forward it on.  --Jeff.]

>>>>> "MM" == Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl> writes:

    MM> Now, let's say this is a setuid root wrapper program which
    MM> executes some command as root after doing setuid(0).  If
    MM> LD_LIBRARY_PATH was defined twice in the environment, it will
    MM> still be defined (only one string has been removed) and passed

As far as wrappers go, this should fix the above problem.  It
implements the suggestion by Peter Da Silva.  Yes, it is rather
presumptuous/restrictive about what it lets into the environment, but
it is easy to allow other environment variables to pass if need be.

--
Joshua Cowan <jcowan@hermit.reslife.okstate.edu> __| I don't want to listen
http://hermit.reslife.okstate.edu/~jcowan       | but it's all too clear...
Computer Engineering Student -- Oklahoma State University -- Stillwater, OK
PGP key available from any PGP keyserver or by fingering the above address.


/* This is a login wrapper that removes all instances of various
   variables from the environment.

   Original author:      Lawrence R. Rogers

   This is a modified version and is only partially based on the work
   of the original author; Lawrence R. Rogers is not responsible for
   this version.

   NOTE: THIS PROGRAM MUST BE COMPILED STATICALLY TO BE EFFECTIVE
   AGAINST EXPLOITATION.  For example:

   gcc -static -o login FILENAME

   Where FILENAME is the name of the file to which you saved this.

   To install this wrapper, first move `/bin/login' or
   `/usr/bin/login' (make sure it is the one that telnetd (8)
   executes) to `/bin/login.real' or whatever you defined
   _PATH_LOGIN_REAL to be.  Then replace the original with the
   executable generated by compiling this file (again, make sure that
   this executable is statically linked or it will be ineffective).  */

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <syslog.h>

#ifndef SYSLOG_FACILITY
#define SYSLOG_FACILITY   LOG_AUTHPRIV
#endif /* SYSLOG_FACILITY */

#ifndef SYSLOG_LEVEL
#define SYSLOG_LEVEL   LOG_ALERT
#endif /* SYSLOG_LEVEL */

#ifndef _PATH_LOGIN_REAL
#define _PATH_LOGIN_REAL   "/bin/login.real"
#endif /* _PATH_LOGIN_REAL */

/* This should be a list of environment strings that we want to allow
   users to pass to login (1) (and possibly to the shell).  These will
   be matched using strncmp (3).

   This list should really only contain the names of environment
   variables that control display parameters, as any others should be
   able to wait until the shell's rc files (e.g., `.login',
   `.profile', `/etc/profile', etc.,) are executed.  */
static const char *legal_env_strings[] =
{
  "DISPLAY=",
  "TERM=",
  0
};

int
main (argc, argv, envp)
     int argc;
     char **argv, **envp;
{
  char **p1, **p2;
  int i;

  openlog (argv[0], LOG_PID, SYSLOG_FACILITY);

  for (p1 = p2 = envp; *p1; p1++)
    {
      int found = 0;

      /* Traverse the list of legal environment strings.  If we have a
         match, pass it in envp; otherwise, send a warning to the
         system logger.  */
      for (i = 0; legal_env_strings[i] && !found; i++)
	{
	  if (!strncmp (*p1, legal_env_strings[i], strlen (legal_env_strings[i])))
	    found = 1;
	}

      if (found)
	{
	  *p2++ = *p1;
	}
      else
	{
	  syslog (SYSLOG_LEVEL,
		  "illegal environment string: `%s'\n", *p1);
	}
    }
  *p2 = 0;

  closelog ();

  execve (_PATH_LOGIN_REAL, argv, envp);
  perror (_PATH_LOGIN_REAL);

  exit (1);
}

home help back first fref pref prev next nref lref last post