[HN Gopher] Don't abuse su for dropping user privileges (2015)
___________________________________________________________________
Don't abuse su for dropping user privileges (2015)
Author : aargh_aargh
Score : 43 points
Date : 2023-05-26 10:49 UTC (12 hours ago)
(HTM) web link (jdebp.uk)
(TXT) w3m dump (jdebp.uk)
| chasil wrote:
| I still have some SysV init and I use it to respawn Oracle
| clients in runlevel 4.
|
| I use this C to knock down the privilege from root to the app
| client account before I execve() the target:
| setfsgid(g); setfsuid(u); if(setgroups(NULL) ||
| setresgid(g,g,g) || setresuid(u,u,u)) {
| fprintf(stderr, "permissions error\n"); exit(1); }
|
| I hope that I did this correctly. Even if incorrect, it's worked
| since 2013.
|
| Interesting that the post's linked article does not even mention
| real, effective, and saved user/groupIDs.
| st_goliath wrote:
| > Interesting that the post's linked article does not even
| mention real, effective, and saved user/groupIDs.
|
| Even worse, the article doesn't even mention TIOCSTI, which is
| another big reason, you should not use `su` this way (see e.g.
| https://www.errno.fr/TTYPushback.html).
|
| The program run under su keeps the same TTY and can use the
| TIOCSTI ioctl to push data back into the TTY input buffer. When
| the program exits and the parent reads from stdin, it receives
| those bytes. If the parent happens to be a root shell from
| which you dropped privileges using su, you have a problem.
| JdeBP wrote:
| TIOCSTI is irrelevant. When one is _dropping_ privileges, in
| a system cron job or in a process supervised by one 's
| favourite service management system, there is no terminal
| involved. TIOCSTI simply doesn't enter into the picture at
| all.
|
| Only when one is in a terminal login session and using su to
| _elevate_ / _add_ privileges, does TIOCSTI become relevant.
| But no-one here is saying not to use su to _add_ privileges.
|
| People blame su, sudo, and (as the person at
| https://github.com/slicer69/doas/issues/110 did) doas for
| this feature of operating system kernels. The right thing to
| do with TIOCSTI it to just eliminate it from the kernel.
| OpenBSD did back in version 6.
|
| Sadly, the argument from Alan Cox, Linux developer, when this
| was proposed years ago was that it should stay in Linux, and
| all of the programs like su, sudo, and doas should have _even
| more_ things to do in the parent process that sticks around,
| namely pump I /O to and from a controlling pseudo-terminal
| that su/sudo/doas sets up for the shell subprocess, breaking
| (as the maintainer of OpenDoas pointed out) the long-standing
| notion that the child processes belong to the same terminal
| session and share things like a single getlogname() with the
| login shell.
|
| 6 years after https://www.openwall.com/lists/kernel-
| hardening/2017/05/10/3... and
| https://www.openwall.com/lists/oss-security/2017/06/03/9,
| there is no sign of anyone doing anything of the sort in any
| su or doas implementation. (It was briefly in one su
| implementation, but taken out in 2017 for being a "stupid
| hack": https://github.com/util-linux/util-
| linux/commit/23f75093264a...)
|
| Fortunately, some six months ago Linux developers finally
| made TIOCSTI removable and the right course of action is
| available to those that want it: https://lore.kernel.org/lkml
| /20221228205726.rfevry7ud6gmttg5...
| ptx wrote:
| The linked page also describes how this problem is solved by
| using "su -P" or the "use_pty" option with sudo, but says
| that is disabled by default. Any idea why the security fix
| isn't enabled by default?
| RjQoLCOSwiIKfpm wrote:
| The article seems quite unclear about potential consequences of
| using su this way.
|
| I typically use su to run some program in its own user account to
| ensure:
|
| - it has its own homedir and doesn't fill mine with garbage.
|
| - there is some level of isolation from the rest of the system
| for security, a basic "jail". I'm not trying to protect against
| targeted attacks from extremely competent threat actors here, but
| rather trying to stick software into its own user account so it
| can only access that account, with isolation of the same level as
| if I had manually logged in to a secondary account.
|
| Can such programs break out of their "jail" when using su?
|
| Or is the author of the article just angry for other reasons?
| jacobvosmaer wrote:
| The article does not talk about security problems. It's about
| whether your daemon works correctly.
|
| 1. Depending on the environment, process supervision can break
| if there is an unexpected process sitting between the
| supervisor and the supervisee. The article describes how the
| switch to PAM forced the introduction of an in-the-middle
| process responsible for closing the PAM session. The old su
| used exec, which avoids an in-the-middle process.
|
| 2. Su uses the shell of the target user, and will outright not
| work if the target user has a "nologin" shell.
|
| The article goes on to mention correct workarounds for this
| like daemontools setuidguid, Runit chpst or just rolling your
| own exec wrapper.
| jjnoakes wrote:
| > angry
|
| Seems like an unnecessary assumption.
| AstralStorm wrote:
| Yes, the program can likely setuid to the original user with
| su, as the session is the parent session and still active.
|
| This is not a behavior you want of a jail. Use chroot, LXC or
| your own setuid wrapper that removes the privilege.
| kazinator wrote:
| Every process in your system either still has an ancestor
| that is still running and has superuser privileges. Either
| because that was the real ancestor, or else because that
| ancestor is PID 1 due to reparenting.
|
| A process cannot use its existing ancestral sessions to gain
| control of their account.
| ptx wrote:
| Well, os.setuid and os.seteuid in Python give me
| "PermissionError: [Errno 1] Operation not permitted". Do you
| have an example of how this could be done?
| Tuna-Fish wrote:
| So, what is the correct default (nothing self-built, please)
| command to start a shell using the privilege level of some less
| privileged user? Setuigid doesn't seem to be included by default
| in distributions.
| klodolph wrote:
| The su command is correct for that purpose, as is sudo.
|
| This is kind of a subtle point that the article makes--the
| problem is that "su" is not good for dropping user privileges
| _in general_ , but it does work if you are a user trying to
| spawn an interactive shell as another user.
|
| Keep in mind that you are giving control of your terminal to
| that less-privileged account, and that this is a potential
| point of privilege escalation.
| tkhattra wrote:
| check out the setpriv command - https://man7.org/linux/man-
| pages/man1/setpriv.1.html
| cwillu wrote:
| According to man su(1):
|
| "su is mostly designed for unprivileged users, the recommended
| solution for privileged users (e.g. scripts executed by root)
| is to use non-set-user-ID command runuser(1) that does not
| require authentication and provide separate PAM configuration.
| If the PAM session is not required at all then the recommend
| solution is to use command setpriv(1)."
| tinus_hn wrote:
| Writing daemon instead of daemon is not cute and not clever.
| LanternLight83 wrote:
| i think its cute
| justin_oaks wrote:
| I assume that is why I see gosu [1] used so often for dropping
| privileges in Docker containers.
|
| It's good to have some explanation as to why su is unsuitable for
| this.
|
| [1] https://github.com/tianon/gosu
| kazinator wrote:
| This article is nonsense. I'm afraid.
|
| Firstly, the su program isn't standardized by POSIX, so
| everything we say about it is system-dependent.
|
| On the systems where that trick is used, su is documented as
| having that feature.
|
| When su is executed by root (so that its setuid bit is moot), it
| knows this, and allows a credentials change to a specified
| account without prompting for a password. This is a feature and
| the example cron jobs are using it correctly to obtain their
| desired effect of impersonating that user.
|
| su is not "dropping privileges"; it's impersonating a specific
| user, in a command dispatched from a root cron job or other
| script.
|
| Thus all that might be wrong is the _rhetoric_ used to describe
| the scripts, not what the scripts are actually doing, and only if
| we are nitpicky.
|
| "Dropping privileges" has a strict meaning, referring to the
| situation that some user _bob_ invoked a setuid root executable,
| which then disrobes itself of the root privilege, changing its
| effective-root uid to just _bob_ again.
|
| When root changes to another account that is unrelated to the
| real user ID, nevertheless, that situation fits the description
| of "dropping privileges" because that account is strictly less
| privileged than root.
|
| > The right way ... Create a small wrapper binary with C
|
| That's a silly nonstarter.
|
| > _The new implementation called fork() and only dropped
| privileges in the child, retaining a privileged account parent
| process that could call the PAM "user session" cleanup function
| once the child exited._
|
| Privileged parents waiting for unprivileged children to terminate
| is an established pattern in Unix-like systems.
|
| E.g. PID 1 (init or systemd) is privileged and handles the
| termination of everything that has no parent.
|
| The author is not connecting the dots here: reporting some actual
| privilege escalation bug in the use of "su bob command ...".
|
| Interactively, when you are root, you can do this:
| root # su bob /home/bob$ exit root #
|
| This exit back to root is not a security hole, and it is not
| relevant to the scripted scenario at all. Bob has not actually
| gained root access. The order of messages on the TTY isn't what
| determines the security context semantics.
| TacticalCoder wrote:
| > This exit back to root is not a security hole
|
| Wait... Doing just "su bob" is vulnerable to a known decades
| old exploit. You should do either "exec su bob" or "su -P bob"
| or you just gave bob root rights on every Linux kernel older
| than 6.2 (and I think on 6.2 and more recent the default is
| still insecure?).
|
| It's explained here with a simple PoC exploit (I tried the
| exploit and it works/worked) and it's been frontpage on HN in
| the past I think:
|
| https://www.errno.fr/TTYPushback.html
| hulitu wrote:
| > Consider this python sample and assume it's automatically
| being run at logon from the .bashrc of a technical account,
| such as postgres, to which the root user changes by typing su
| - postgres
|
| From su man page: "su is mostly designed for unprivileged
| users, the recommended solution for privileged users (e.g.,
| scripts executed by root) is to use non-set-user-ID command
| runuser(1) that does not require authentication and provides
| separate PAM configuration. If the PAM session is not
| required at all then the recommended solution is to use
| command setpriv(1)."
___________________________________________________________________
(page generated 2023-05-26 23:01 UTC)