|Anonymous | Login||2022-01-19 19:23 UTC|
|Main | My View | View Issues | Change Log | Docs|
|Viewing Issue Simple Details|
|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|
|Section||8.1 Environment Variable Definition|
|Page Number||http://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html [^]|
|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.|
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.|
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).
|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.|
Current list dropped by glibc (from https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=sysdeps/generic/unsecvars.h;h=d5b8119c9cb5cf5f1391325282287c5935c86589;hb=HEAD [^] and https://sourceware.org/git/gitweb.cgi?p=glibc.git;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" \
23 "RESOLV_HOST_CONF\0" \
24 "RES_OPTIONS\0" \
25 "TMPDIR\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. */
58 #define EXTRA_UNSECURE_ENVVARS \
59 "LD_AOUT_LIBRARY_PATH\0" \
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.
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.
|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||=> http://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html [^]|
|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|