FS#67519 - [pam] v1.4 changed some behaviour of pam_env.so, pambase might need to use the user_readenv=1 flag.

Attached to Project: Arch Linux
Opened by Philipp Korber (philippkorber) - Friday, 07 August 2020, 13:22 GMT
Last edited by Tobias Powalowski (tpowa) - Friday, 14 August 2020, 12:47 GMT
Task Type Bug Report
Category Packages: Testing
Status Closed
Assigned To Tobias Powalowski (tpowa)
Architecture All
Severity Low
Priority Normal
Reported Version
Due in Version Undecided
Due Date Undecided
Percent Complete 100%
Votes 0
Private No

Details

Description:

As of v1.4.0 pam_env.so no longer loads user defined environment files (`~/.pam_environment`) by default.

This can be re-enabled by using the `user_readenv=1`
flag for all usages which use `pam_env.so` as last
entry in a pam stack.

The reason for this change is that if pam_env.so is not called last in a pam stack then the user can inject env variables which might affect how following pam modules work leading to
potential security vulnerabilities.

Additional info:
* >=1.4.0
* https://github.com/linux-pam/linux-pam/blob/650273e77b643f14d937f26f8b628481a4b4b56a/NEWS#L11


Steps to reproduce:
-

PS:
I attached a patch which might work, but I didn't test it as I currently have no container system setup and won't play around with PAM on my main system ;=)


This task depends upon

Closed by  Tobias Powalowski (tpowa)
Friday, 14 August 2020, 12:47 GMT
Reason for closing:  Fixed
Comment by loqs (loqs) - Friday, 07 August 2020, 13:48 GMT
 FS#67369 
Comment by loqs (loqs) - Friday, 07 August 2020, 15:08 GMT
pam_env is also used in cronie, inetutils, gdm, lightdm, sddm, at, fcron and opendoas.
at sets user_readenv=1

auth required pam_env.so user_readenv=1
Are those potentially user controlled variables then propagated to account, password or session?
Comment by Philipp Korber (philippkorber) - Friday, 07 August 2020, 16:06 GMT
> Are those potentially user controlled variables then propagated to account, password or session?

As far as I know system-auth runs pam_env for auth and session as last module to do exactly that.

For example I configure all my user-wide environment variables using ~/.pam_environment because
it (more or less) works independent of the shell or login through which a program is launched.
(It is, or at least was the easiest way to set env variables for all programs including such
launched directly by sway).

Or this is what I thought until recently, in truth it only works if whatever I use to login
does either directly use pam_env or indirectly by e.g. including `system-auth`, which you normally might expect to happen but doesn't always happen (which also means that such auth
methods would circumvent any 2FA configured in system-auth or whatever custom PAM modules you put in making PAM IMHO rather annoying to use. Like for example if I run su environment are not loaded, 2FA configured in system-auth is not run etc. But if I run sudo environment variables are loaded and 2FA configured in system-auth applies).


I also asked the PAM devs about it, as I didn't know if maybe some other mechanism is at play https://github.com/linux-pam/linux-pam/issues/260.

Note that pam_env will always load `/etc/security/pam_env.conf` into the environment, then by default it will also load `/etc/environment` and in the past also loaded `~/.pam_environment`
by default, which was changed to now be opt-in instead.

Comment by Philipp Korber (philippkorber) - Friday, 07 August 2020, 16:29 GMT
> Are those potentially user controlled variables then propagated to account, password or session?

I just noticed I might have misunderstood the question.

They are set as environment variables. But PAM differentiates between environment variables and PAM Items, so it doesn't necessary affect PAM modules called later one in the stack.

Also pam_env provides only the auth and and session module type. So if pam is run for auth/session and the auth/session stack includes pam_env it will load the environment variables. But if only the auth stack includes pam_env but the session stack does not then it's only available for contexts where auth is used but not such for which session is used.

Also given that pam_env doesn't provide password and account it's not affecting PAM executions using such a type at all.
Comment by loqs (loqs) - Friday, 07 August 2020, 17:00 GMT
What I meant was if $LD_PRELOAD was set by pam_env in auth would it be able to change pam_time.so in account or pam_limits.so in session which have not been loaded before to a user controlled version?
If pam always runs with AT_SECURE set then this example would be impossible.

If pam_env in auth is not changed, does that break you use case?
Comment by Philipp Korber (philippkorber) - Friday, 07 August 2020, 17:58 GMT
(browser refresh reposted my last comment)



Comment by Philipp Korber (philippkorber) - Friday, 07 August 2020, 18:06 GMT
My use-case would not be broken I think.

Wrt. LD_PRELOAD I'm not sure. I.e. environment variables set via pam are not environment variables
of the PAM process (the process which called pam_start and will implicitly run the modules. At least that process need to access them through PAM e.g. `su` does get them using pam_listenv than copies them over from there before calling exec after forking out a new child to run given command/shell).

But I don't know if they might be set by PAM when running given modules or if given modules might just explicitly access them (e.g. to check if a previous PAM command set REMOTEHOST or similar).

Also I don't know if env variables set when running auth type modules will carry over to session type modules being run later, it actually somewhat seems to be the case as they share the same pam context but I don't really know.
Comment by Philipp Korber (philippkorber) - Friday, 07 August 2020, 18:34 GMT
Looking into it:

I'm pretty sure now that env variables loaded with pam_env are not set as environment variables of either:

- The PAM process/calling process.
- Any PAM module

But they do affect following aspects:

- Any call to `pam_exec` will setup the env based on pam_getenvlist (contains all entries set with `pam_putenv` like e.g. called by `pam_env`).

- Any module which want's to explicitly check an variable set by `pam_putenv` (e.g. check if some other PAM module set REMOTEHOST).

From this and looking into `pam_exec` it became clear that an LD_PRELOAD attack should be possible if pam_exec is used after `pam_env.so read_userenv=1` with a binary not hardened against LD_PRELOAD based attacks (the severity can be slightly reduced by calling pam_exec with the seteuid flag).

So I guess `pam_env.so read_userenv=1` should never be included in the `auth` stack.

But calling it as last entry in the `session` stack should (probably?) be fine.

Furthermore I guess pam_exec should be avoided.
Comment by Philipp Korber (philippkorber) - Friday, 07 August 2020, 19:13 GMT
I just played around with the su-l pam and found following:

Environment variables set with auth pam_env.so do carry over to pam_exec calls in session.

But strangely not to such in account, even through `pam_acct_mgmt` is called by su after `pam_authenticate` with the same pam handle.

I mean it kinda makes sense because pam_env doesn't provide for this type. But then it also means I still have a misunderstanding in about how PAM works. I though there is a PAM env map per "pam session"/thing pam_handle_t points to. But I guess that's not the case.

Anyway it generally confirms what I posted previously.
Comment by Tobias Powalowski (tpowa) - Wednesday, 12 August 2020, 19:40 GMT
pam-1.4.0-3 and pambase-20200721.1-2 should fix this.

Loading...