guix-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Providing an alternative to setuid in GuixSD


From: sbaugh
Subject: Re: Providing an alternative to setuid in GuixSD
Date: Mon, 24 Oct 2016 18:01:47 -0400
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/25.1 (gnu/linux)

Chris Marusich <address@hidden> writes:
> Hi,
>
> I don't think I have all the answers, but this is an interesting topic,
> so I'll chime in with what I can.  I'm sure others will have more
> thoughts to share, too.
>
> address@hidden writes:
>
>> 1. Each binary is an attack surface which is frequently exploited by
>>    attackers for local privilege escalation. So getting rid of them
>>    would improve security.
>>
>> 2. setuid binaries make access control decisions in an environment
>>    controlled by the user running them, by looking at files at absolute
>>    paths in that environment, such as /etc/passwd. Thus, if unprivileged
>>    users had access to chroot or other filesystem namespacing
>>    functionality, those users could escalate privileges by manipulating
>>    /etc/passwd, /etc/shadow, /etc/sudoers, and then running a setuid
>>    binary. So unprivileged chroot is not possible.
>
> When you say "filesystem namespacing functionality," are you referring
> to the Linux feature known as "user namespaces"?

I was referring to things which correspond ~directly to chroot, like
mount namespaces or Plan 9 namespaces. But it's best to just consider
chroot I think.

The vulnerability is most clear when chroot is unprivileged, but it is
present in any system with setuid binaries and the ability to perform
non-trivial filesystem namespace manipulations without privileges. (In
particular, to change what the root directory points to)

Given chroot, all you need to do is:
1. Create your own filesystem tree with your own /etc/passwd and
/etc/shadow which specifies a known password for root.
2. Chroot into that filesystem tree
3. Run su and provide the known password for root; it will check the
password against the /etc/shadow that you created.
4. Escape the chroot. Once you have root in the chroot, there are many
mechanisms for doing this.  For example, create a device file
corresponding to the real root fs, mount it, and chroot again there.
5. Enjoy your new root privileges in the main filesystem namespace.

> There is an article on LWN that discusses some of the security issues
> surrounding this:
>
> Filesystem mounts in user namespaces
> https://lwn.net/Articles/652468/
>
> I admittedly don't know a lot about this feature, but it sounds like it
> is not currently designed to let a user escalate privilege in a way that
> would enable malicious modification of system files such as /etc/passwd.
> Can you clarify your second concern a little more to help me understand?

That's partially correct; user namespaces would not allow modification
of the "real" /etc/passwd, but they would allow you to create a mount
namespace where you can put whatever file you want in place of
/etc/passwd. In fact, you could get up to step 4 of the above attack.
But then you would be stuck: You are not supposed to be able to escape a
user namespace even with root, and while you are still inside a user
namespace your privileges don't mean anything.

So, user namespaces provide an alternative solution. But they also
independently expose quite a large attack surface, and I am not really
optimistic about them being accessible unprivileged in any mainstream
distro any time soon...

I am much more optimistic about the project of eliminating setuid
binaries and thereby allowing "plain old chroot" to be safely done
without privileges. This would only allow an a small subset of the
functionality of user namespaces, but it would be enough for a lot of
applications.

> It would be nice if the Guix daemon could create chroots for building
> packages even when it runs as a non-privileged user.  That is definitely
> a limitation (see the comment about "--disable-chroot" in (guix) Build
> Environment Setup).  However, I don't understand how eliminating setuid
> binaries would enable unprivileged access to root.  Can you clarify why
> the latter follows from the former?

Eliminating setuid binaries means step 3 in the above attack outline is
not possible. A distribution without setuid binaries could therefore
safely turn on unprivileged access to chroot.

>> == How to do it ==
>>
>> Most (all?) setuid binaries can be replaced with a non-setuid binary
>> which performs local IPC to a privileged daemon.
>>
>> The largest targets for elimination are sudo and su. Luckily there is
>> already a ready alternative for those commands: ssh. We can augment lsh
>> with the rich access controls of sudo, add any extra missing features,
>> and then replace sudo/su with wrappers around ssh. (A wrapper would be
>> needed just for sheer familiarity of the system to a user.) sshd runs
>> and performs access controls in a fixed environment, so this is not
>> vulnerable to the chroot attack I mentioned above.
>>
>> Once we have a solid replacement for sudo, we can take a generic
>> approach to eliminating other setuid binaries: just replace them with
>> wrappers which call 'sudo command "$@"', and make sure the
>> sudo-replacement is appropriately configured to allow running that
>> command without authentication.
>>
>> I believe we could do this with all binaries, though there may be some
>> issues I'm not yet aware of yet.
>>
>> In the longer term I'm not sure if we would want to individually
>> replace setuid binaries with IPC-performing commands. The only real
>> benefit is maybe elegance...
>
> That's an interesting idea.  Some questions come to mind:
>
> * How would we allow one user to run a program as a different user?

Well, if user A can authenticate as user B, they certainly can also run
a program as user B through normal ssh-like means. So I assume you mean
allowing user A to run a program as user B only by authenticating as
user A.  I believe that can be achieved with some ssh tricks. (I've done
just this with ssh and Kerberos principals before; I believe you could
do the same with ssh and Unix authentication but I haven't thought about
it in much detail so I'm waving my hands a bit here)

> * How would we allow a user to update their own entries in shared
> databases like /etc/passwd?

Through IPC to a privileged process: The "passwd" tool, as an example,
could simply send a message providing the new password to a daemon
privileged to perform the actual update.

Alternatively for case of passwd specifically, we could use the tcb
framework of Openwall: http://www.openwall.com/tcb/ Which is a somewhat
more elegant trick, but may be more work and less compatible. (I'm also
not sure that it works with absolutely all PAM modules; there could be
some besides the basic files authentication which anticipate running as
root. But I don't know for sure.)

> * Could this approach work with any kernel, not just Linux?

Definitely. As described currently it's totally kernel-independent.

At some point, file-descriptor-passing-over-Unix-sockets might be
useful. That would add a very small amount of kernel-dependence as that
is sometimes available in different ways on different Unix kernels. (But
it is still generally available.)

> * Because the daemon must have enough privileges to take any potential
> action that might be requested, does this solution fail to enforce the
> principle of least privilege in basically the same way that many setuid
> programs do (because they start with more privileges than they need)?

Yes. However, it's a big advance over setuid, because the daemon runs in
a fixed environment, rather than running in an environment entirely
controlled by an unprivileged user. And that is enough of an improvement
to get big benefits, namely, safe unprivileged chroot.

> * Do you know of any prior art in this area which is similar to what you
> are proposing?  I saw some interesting-looking references in the Protego
> paper linked above, but I didn't go down the rabbit hole.

Yes, there is some pre-existing software which is directly relevant:
- s6-sudod, which is explicitly for this purpose:
http://skarnet.org/software/s6/s6-sudod.html
- remctl, which is much older but could be usable for this purpose:
https://www.eyrie.org/~eagle/software/remctl/
- systemd's machinectl has a "shell" subcommand for getting a shell in
containers running on the local host, or on the local host itself:
https://www.freedesktop.org/software/systemd/man/machinectl.html

I don't know of any Unix/Linux distributions that really use this
approach. There's some similarity to Plan 9; Plan 9 has unprivileged
namespacing in part because it doesn't have setuid.

Of course, Guix is also an example of this IPC-to-privileged-action
approach: To perform the privileged action of isolating our builds, we
perform IPC to another more privileged process which does it for us.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]