Server Interpreted "localuser" Authentication using SO_PEERCRED interferes with SSH

Tavis Ormandy taviso at cmpxchg8b.com
Sat May 15 17:10:06 PDT 2010


Hello, I've run into an issue with si:localuser acls when using X11 forwarding
with ssh. I was hoping to get some input from someone more familiar with X
authentication internals as to if this is a bug or not, and if so, on which
side.

When openssh forwards X11 connections from a remote host, it first parses
$DISPLAY and opens the appropriate UNIX domain socket, which it then uses to
forward X11 traffic from the remote peer to the local X server.

Ssh generates an xauth cookie (simply using system("xauth generate ..")), and
verifies that any X11 connection it forwards _must_ be using this cookie for
authentication and using this specific authentication mechanism, if it isn't,
the connection is rejected.

This works fine, except in the case of untrusted cookies with
si:localuser acls. openssh supports untrusted cookies for when you're
connecting to a machine you don't trust (this is the difference between
ssh -X and ssh -Y, the former will use "xauth generate untrusted"), this means
that if the remote machine has been compromised it can only do limited damage
with the untrusted cookie, instead of completely compromise your workstation
(by sending input events to your xterm or whatever).

Ssh also verifies you're using the cookie it generated to authenticate before
it will relay your traffic to the X server, but it also applies a timeout,
see this code from clientloop.c:

 300    snprintf(cmd, sizeof(cmd),
 301        "%s -f %s generate %s " SSH_X11_PROTO
 302        " untrusted timeout 1200 2>" _PATH_DEVNULL,
 303        xauth_path, xauthfile, display);

The problem is, if I'm using xhost +si:localuser:taviso, once the
timeout has expired, X will fall back to SO_PEERCRED verification. As
openssh opened the connection, the credentials check out and I'm
authenticated. This is bad, because now the remote (possibly compromised)
machine has a trusted X connection to my workstation.

I think this might be an X bug, because openssh makes an attempt to
verify the authentication taking place is that expected, for example, see the
following openssh code:

 910     /* Check if authentication protocol matches. */
 911     if (proto_len != strlen(x11_saved_proto) ||
 912         memcmp(ucp + 12, x11_saved_proto, proto_len) != 0) {
 913         debug2("X11 connection uses different authentication protocol.");
 914         return -1;
 915     }
 916     /* Check if authentication data matches our fake data. */
 917     if (data_len != x11_fake_data_len ||
 918         memcmp(ucp + 12 + ((proto_len + 3) & ~3),
 919         x11_fake_data, x11_fake_data_len) != 0) {
 920         debug2("X11 auth data does not match fake data.");
 921         return -1;
 922     }

But it turns out this doesnt work with si:localuser authentication, as even
though the cookie should be rejected, X falls back to peer credentials. I'm not
sure this was intended, after I've tried to authenticate with an expired
untrusted cookie, shouldn't the connection be rejected? Was this intended
behaviour?

If it is intended behaviour and not an X bug, do you have any suggestions I
could pass along to the openssh guys to make sure that no "fallback"
authentication attempts are made? I'm not sure how this can be implemented, but
if you guys have any ideas please let me know.

Any input appreciated!

Thanks, Tavis.

-- 
-------------------------------------
taviso at cmpxchg8b.com | pgp encrypted mail preferred
-------------------------------------------------------


More information about the xorg-devel mailing list