Re: [PATCH v5 0/2] security: tty: make TIOCSTI ioctl require CAP_SYS_ADMIN

From: Jann Horn
Date: Tue Apr 25 2017 - 16:07:26 EST


On Tue, Apr 25, 2017 at 9:30 PM, One Thousand Gnomes
<gnomes@xxxxxxxxxxxxxxxxxxx> wrote:
> On Tue, 25 Apr 2017 15:56:32 +0200
> Jann Horn <jannh@xxxxxxxxxx> wrote:
>
>> On Tue, Apr 25, 2017 at 3:47 PM, Alan Cox <gnomes@xxxxxxxxxxxxxxxxxxx> wrote:
>> >> There could be a few user programs that would be effected by this
>> >> change.
>> >> See: <https://codesearch.debian.net/search?q=ioctl%5C%28.*TIOCSTI>
>> >> notable programs are: agetty, csh, xemacs and tcsh
>> >>
>> >> However, I still believe that this change is worth it given that the
>> >> Kconfig defaults to n. This will be a feature that is turned on for the
>> >> same reason that people activate it when using grsecurity. Users of this
>> >> opt-in feature will realize that they are choosing security over some OS
>> >> features
>> >
>> > Only in this case they are not.
>> >
>> > If I am at the point I have the ability to send you TIOCSTI you already
>> > lost because I can just open /dev/tty to get access to my controlling tty
>> > and use write().
>>
>> In terms of PTYs, this patch does not try to prevent writes to a slave
>> device (which afaik is what /dev/tty will give you). It tries to prevent the
>> equivalent of writes to the master device. As far as I know, there is no
>> way to go from a slave to the corresponding master without having
>> access to the master in some other way already.
>
> Ok so the point I was trying to make about write and read is I can
> already trash your channel when you su. Probably less irritatingly.
>
> In the pty case yes I can go from the tty to pty trivially and then open
> it, however the owner of the pty side would normally have exclusivity so
> while it's a potential hole it isn't a trivial one.

Really? By "pty", are you referring to the master? If so, as far as I know,
to go from the slave to the master, you need one of:

- ptrace access to a process that already has an FD to the master, via
ptrace() or so (/proc/$pid/fd/$fd won't work)
- for a BSD PTY (which AFAIK isn't used much anymore), access to
/dev/ptyXX

Am I overlooking something?

> If I want to do the equvalent of the TIOCSTI attack then I fork a process
> and exit the parent. The child can now use ptrace to reprogram your shell
> to do whatever interesting things it likes (eg running child processes
> called "su" via a second pty/tty pair). Not exactly rocket science.

Why would the child be able to ptrace the shell? AFAICS, in the most
relevant scenarios, the child can't ptrace the shell because the
shell has a different UID (in the case of e.g. su or sudo). In other
scenarios, Yama, if enabled, should still stop you from doing that.
And even with containers that have the same UID as the calling user,
which I think is not exactly a good approach from a security perspective,
the PID namespace should stop you from ptracing things outside the
container.


> The tty layer does not try to manage this because it can't and two
> processes with the same uid are not protected from one another in the
> traditional Unix model. As with anything else when you try and glue
> namespaces on top of a model not designed for it you get a pile of holes.
>
> There is no safe way to fix it if you can't trust the environment you are
> communicating through. Secure practice is either to make another
> connection or if local to switch console and use SAK then login.

This is somewhat off-topic, but SAK has several security issues, one of
which is documented in the source code. I would be surprised if anyone
actually relied on that. Comment above __do_SAK():

/*
* This implements the "Secure Attention Key" --- the idea is to
* prevent trojan horses by killing all processes associated with this
* tty when the user hits the "Secure Attention Key". Required for
* super-paranoid applications --- see the Orange Book for more details.
* [...]
* Now, if it would be correct ;-/ The current code has a nasty hole -
* it doesn't catch files in flight. We may send the descriptor to ourselves
* via AF_UNIX socket, close it and later fetch from socket. FIXME.
* [...]
*/


> In the namespaces case it certainly makes sense to forbid a process in
> one namespace from typing characters into another namespace but to me
> that implies that tty sessions/job control are namespaced, and that makes
> transitioning namespace or even just typing stuff into a docker container
> shell rather more tricky to get right if you have to be in the right tty
> session _and_ namespace to use the tty.
>
> Alan