Austin Group Defect Tracker

Aardvark Mark IV

Viewing Issue Simple Details Jump to Notes ] Issue History ] Print ]
ID Category Severity Type Date Submitted Last Update
0000922 [1003.1(2013)/Issue7+TC1] System Interfaces Editorial Clarification Requested 2015-02-11 10:08 2015-09-04 18:34
Reporter Florian Weimer View Status public  
Assigned To
Priority normal Resolution Open  
Status New  
Name Florian Weimer
Organization Red Hat
User Reference
Section 8.1 Environment Variable Definition
Page Number [^]
Line Number 141
Interp Status ---
Final Accepted Text
Summary 0000922: Implementations should be allowed to change/remove implementation-defined environment variables
Description Most implementations treat some implementation-defined environment variables in special ways and remove or reset them as part of the initialization of a SUID/SGID process image. The standard is currently not clear whether this is permitted, although it is required to prevent security defects in applications from materializing, which means that implementations are more or less forced to behave in the current way.
Desired Action Add the following clarification to the environment setup:

“If the set-user-ID or set-group-ID mode bit of the new process image file is set, implementations may change or remove variables from the environment of the new process, and functions in the System Interfaces volume may ignore the values of environment variables.”
Tags No tags attached.
Attached Files

- Relationships

-  Notes
dalias (reporter)
2015-02-13 18:45

While there is some historical precedent for this, it has always been non-conforming and its value as a security measure is questionable. I would prefer that this change not be made.

If a program has been invoked with the setuid/setgid bits set, the implementation is of course free to ignore (or restrict the interpretation of) implementation-defined environment variables and may even limit the interpretation of some standard variables (like TZ), for itself. There is little value however in stripping them from the environment, because such a program cannot safely run further programs that were not designed to be invoked setuid/setgid unless the application manually provides a new, safe environment (possibly copying some variables from its own environment, but with a whitelist approach, not a blacklist approach).
eblake (manager)
2015-04-30 15:39

Another thing to consider is glibc's secure_getenv(), which puts the burden on an application that is sometimes run with privileges to audit which environment probes it leaves alone, and which environment probes it ignores when run securely. One benefit of secure_getenv() is that the environment is unchanged, so if the setuid app drops privileges before forking a child, the child can use the original environment. A drawback is that each application that wants to use it must be audited for which variables to use it on.
eblake (manager)
2015-04-30 16:10

Current list dropped by glibc (from;a=blob;f=sysdeps/generic/unsecvars.h;h=d5b8119c9cb5cf5f1391325282287c5935c86589;hb=HEAD [^] and;a=blob;f=sysdeps/unix/sysv/linux/i386/dl-librecon.h;h=687ac3035938c0a3a45cf729f0eba3df86e92c3e;hb=HEAD [^] ):

/* Environment variable to be removed for SUID programs. The names are
   2 all stuffed in a single string which means they have to be terminated
   3 with a '\0' explicitly. */
   4 #define UNSECURE_ENVVARS \
   5 "GCONV_PATH\0" \
   6 "GETCONF_DIR\0" \
   7 "HOSTALIASES\0" \
   8 "LD_AUDIT\0" \
   9 "LD_DEBUG\0" \
  10 "LD_DEBUG_OUTPUT\0" \
  11 "LD_DYNAMIC_WEAK\0" \
  12 "LD_LIBRARY_PATH\0" \
  13 "LD_ORIGIN_PATH\0" \
  14 "LD_PRELOAD\0" \
  15 "LD_PROFILE\0" \
  16 "LD_SHOW_AUXV\0" \
  17 "LD_USE_LOAD_BIAS\0" \
  18 "LOCALDOMAIN\0" \
  19 "LOCPATH\0" \
  20 "MALLOC_TRACE\0" \
  21 "NIS_PATH\0" \
  22 "NLSPATH\0" \
  24 "RES_OPTIONS\0" \
  25 "TMPDIR\0" \
  26 "TZDIR\0"

  56 /* Extra unsecure variables. The names are all stuffed in a single
  57 string which means they have to be terminated with a '\0' explicitly. */
philip-guenther (reporter)
2015-09-04 18:15

The status email says:
> Action on Eric: propose wording for Issue 8 to add secure_getenv(),
> and make it clear that deleting from environment without explicit
> request is not compliant, but ignoring is fine.

Implementations have environment variables that are not safe to blindly pass across security boundaries. The canonical example is, of course, LD_LIBRARY_PATH, though may others have been created by various implementations.

It sounds like the committee is saying that implementation MUST pass those across the suid/sgid security boundary. How and by whom will they be blocked? Is the committee suggesting that each suid/sgid application that ever execs a non-suid/sgid application must somehow determine the list of environment variables used by the implementation and manually delete them? That'll have to be a *runtime* determination, of course, to support OS upgrades creating more such environment variables.

APIs to do that don't exist.

Existing suid/sgid applications don't call those non-existent APIs, obviously, and instead have guessed-at hardcoded lists, or just trust the implementation to do The Right Thing and delete the variables that are dangerous in that implementation.

Lacking any plan on how the POSIX software ecosystem could ever *believably* get to a state where suid/sgid applications will *correctly* and *reliably* do this for themselves, the suggestion from the committee that implementations MUST pass all environment variables through is folly and will certainly not be adopted by OpenBSD.
dalias (reporter)
2015-09-04 18:34

Regarding note 0002810, stripping these variables is neither correct nor sufficient for security.

There are three cases to consider:

1. The suid/sgid application has dropped its elevated privileges and is running an external program on the behalf of the user who invoked it. In this case, the right behavior is to honor any environment variables that user may have set, including "dangerous" things like LD_LIBRARY_PATH or LD_PRELOAD. Failure to do so is functional breakage (and is non-conforming).

2. The suid/sgid application is executing an external program with the same elevated privileges it was invoked with (2a), or fully elevated privileges (2b, real id escalated to effective id). In case 2a, for environment variables meaningful to the implementation (like LD_*), they will be ignored by the same logic that ignored them in the original application: real/effective id mismatch or some other implementation-specific mechanism. Of course, this usage is inherently unsafe anyway if the program being invoked was not designed to be invoked with mismatching real/effective ids. In either case 2a or 2b, however, passing any environment variables (not just implementation-defined ones) that were under the control of the invoking user is unsafe, because they might be interpreted by the application (directly or via third-party library code).

The only safe way to exec or posix_spawn from a suid/sgid program without dropping privileges is to completely sanitize the invoking-user-controlled environmental state, which includes the environment variables and a lot more. This should be done by passing a completely new environment array to execve or posix_spawn rather than using the suid/sgid application's environ.

- Issue History
Date Modified Username Field Change
2015-02-11 10:08 Florian Weimer New Issue
2015-02-11 10:08 Florian Weimer Name => Florian Weimer
2015-02-11 10:08 Florian Weimer Organization => Red Hat
2015-02-11 10:08 Florian Weimer Section => 8.1 Environment Variable Definition
2015-02-11 10:08 Florian Weimer Page Number => [^]
2015-02-11 10:08 Florian Weimer Line Number => 141
2015-02-11 10:08 Florian Weimer Issue Monitored: Florian Weimer
2015-02-13 18:45 dalias Note Added: 0002546
2015-04-30 15:39 eblake Note Added: 0002643
2015-04-30 16:10 eblake Note Added: 0002644
2015-09-04 18:15 philip-guenther Note Added: 0002810
2015-09-04 18:34 dalias Note Added: 0002811

Mantis 1.1.6[^]
Copyright © 2000 - 2008 Mantis Group
Powered by Mantis Bugtracker