Using PAM in setuid processes
Simon McVittie <simon.mcvittie <at> collabora.co.uk>
2013-01-24 19:22:34 GMT
I've recently been looking at the security properties of various setuid
executables, many of which use PAM for authentication.
What is PAM's policy on the extent to which modules may trust the
process' execution environment, particularly environment variables?
I can see three options for a consistent policy:
1) PAM is considered safe to use in a setuid process, even if the
environment has not been "cleaned". Modules must not use libraries
or execute helper programs that can be adversely affected by
2) PAM is only considered safe to use in a setuid process if the
environment has been "cleaned" against a whitelist. Modules may use
any library, or execute any helper program; privileged processes
that are run with a potentially-attacker-controlled environment
must "clean" it before using PAM. If the process intends to use the
original environment later, it can save a copy before cleaning it,
and pass that copy to execle or similar.
3) There is some mechanism that can/should be used in modules to decide
whether the process in which they are hosted is privileged or not.
If it is, they must ensure that they ignore environment variables;
if it is not, they may obey environment variables.
Which of these policies do the PAM maintainers consider it to have?
For some examples of setuid executables which behave defensively and
clear the environment (i.e. behaving as if the policy is (2), but also
OK for either of the others), see polkit's pkexec and
(saves the old environment first, and may pass a filtered subset
to the executed program)
(clears the environment altogether)
For examples of setuid executables which do not clear the environment
(i.e. assuming that the policy is (1)), see most su implementations.
Here are some examples of things modules in these processes can't be
allowed to do without special precautions if policy (1) is in effect:
* trust executables in $PATH
* trust $IFS not to be something that will confuse a shell script
* connect to $DBUS_SESSION_BUS_ADDRESS or $DBUS_SYSTEM_BUS_ADDRESS
(either of which can contain a command to start a "tunnel")
* load code from $PERL5LIB, $PYTHONPATH, $PYTHONHOME etc.
* trust UTF-8 input in conjunction with PERLIO=:utf8
* trust that $TZDIR is non-malicious
* connect to $DISPLAY? (if the X11 protocol is such that connecting to a
socket specified by an attacker can cause bad things to happen)
* execute an external command that does any of those
sudo(1) has a long list of variables that are considered unsafe.
If PAM doesn't have a policy for this, I would personally advocate
policy (2), as recommended by
I do notice that this would break use of pam_xauth in setuid
executables, although it isn't clear to me whether that would make sense
For the DBUS_* variables this was reported as CVE-2012-3524, and
mitigated in libdbus and GDBus by distrusting environment variables if
getuid() != geteuid() (so, a partial implementation of policy (3), but
perhaps not with the same mechanism to detect privilege that you'd choose).
I'm mainly interested in environment variables and setuid at the moment,
but similar considerations apply to other bits of process environment
that are inherited from a parent that can be less privileged (most
notably, current working directory), and to mechanisms for privilege
escalation other than setuid (setgid, Linux filesystem capabilities, etc.).