Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Authentication with X cookie instead of xhost +LOCAL: #30

Closed
mviereck opened this Issue Oct 17, 2016 · 7 comments

Comments

Projects
None yet
2 participants
@mviereck
Copy link

mviereck commented Oct 17, 2016

I have managed to use VirtualGL without setting xhost +LOCAL:
The core point is to extract the cookie from ~/.Xauthority for display :0 and to change it a bit. It is described here: http://stackoverflow.com/a/25280523/5369403

Xcookie=/tmp/Xcookie
touch $Xcookie
xauth nlist :0 | sed -e 's/^..../ffff/' | xauth -f $Xcookie nmerge - 

Inserting ffff in the cookie removes restriction to localhost clients. Clients from other hosts using this cookie can access display :0.
I'm using this with VirtualGL in my project x11docker: https://github.com/mviereck/x11docker

Maybe it would be possible to let VirtualGL use this cookie to access display :0 without providing this cookie to client applications? I think this can be a security improvement.

@dcommander

This comment has been minimized.

Copy link
Contributor

dcommander commented Oct 17, 2016

It might be an improvement compared to xhost +LOCAL:, but xhost +LOCAL: is not the preferred way of using VirtualGL. The preferred way is to restrict access to only the members of the vglusers group. In that case, a script (vglgenkey) is run from the display manager startup, and this script generates a new cookie that is stored under a directory that is only accessible to certain users of the system. Explain how your proposal would improve upon the security of that mechanism, and I'll consider it. But if clients from other hosts can access display :0, then that is less secure than xhost +LOCAL:, not more.

@mviereck

This comment has been minimized.

Copy link
Author

mviereck commented Oct 17, 2016

In my case, I run GUI applications in an isolated docker container, and I want to avoid giving them access to display :0. Also, I try to need a minimal setup to be done by users. With this prepared cookie, I don't need to setup VirtualGL server and don't need to use xhost +LOCAL:.
But whatever way I choose, either with vglusers group or with that cookie, client applications get full access to display :0.
As far as I understand, VirtualGL only sends OpenGL requests to display :0, filtering them out of the communication between client and maybe Xvfb.
I think, my proposal could be used to authenticate OpenGL requests from VirtualGL without providing the cookie to the clients. In this case, client access to display :0 would be restricted to OpenGL requests only.

@dcommander

This comment has been minimized.

Copy link
Contributor

dcommander commented Oct 18, 2016

OK, but how would VirtualGL obtain the cookie in the first place? If the display manager is sitting at the login prompt, then the only way to get access to the cookie for :0 is from within the display manager process. That's why we run a script (vglgenkey) from within the display manager's startup scripts. vglgenkey either copies the existing cookie for Display :0, or it creates a new one. It stores the resulting cookie under /etc/VirtualGL, which is readable only by vglusers. Before any user can access Display :0, they have to load that cookie into their ~/.Xauthority file, which is accomplished within the vglrun script. After that point, the user can run any X application on Display :0. VirtualGL could conceivably load the cookie in-process rather than in the vglrun script, but that wouldn't change anything about the user's access to display :0. In order to run xauth against Display :0, you have to have access to it first, so actually your command lines above would not ever work if Display :0 was sitting at the login prompt. You'd have to do the same thing we're doing. You'd have to run xauth within the DM process and copy the cookie to some location on the filesystem, and once you did that, anyone with access to that location could load the cookie. I cannot think of any way for VirtualGL to obtain exclusive access to that cookie. If VirtualGL has access to it, so would any other X application.

If you can somehow access the cookie for Display :0 without obtaining it through the DM process, then I'd love to hear about it. Otherwise, my best suggestion is for you to copy vgl_xauth_key from /etc/VirtualGL to a temporary directory readable only by the current user, modify the cookie to allow access from other hosts, then map that temporary directory to /etc/VirtualGL within the Docker container. Then when you run vglrun within the Docker container, it will load /etc/VirtualGL/vgl_xauth_key as it normally would, and that should grant access to Display :0 on the host.

@mviereck

This comment has been minimized.

Copy link
Author

mviereck commented Oct 19, 2016

Thank you for your detailed and comprehensive answer!

You'd have to run xauth within the DM process and copy the cookie to some location on the filesystem, and once you did that, anyone with access to that location could load the cookie. I cannot think of any way for VirtualGL to obtain exclusive access to that cookie. If VirtualGL has access to it, so would any other X application.

ok, I see your point. Except that I don't need to get the cookie from within the DM process in my use case and can get it from within running display :0, I have to provide a cookie for display :0 anywhere in the filesystem of the client application, may it be vgl_xauth_key or my prepared cookie.
Any application using this cookie would have access to display :0, and I see no way to cirumvent this.

I see one possible point to improve security slightly at least. As for now, vgl_xauth_key is inserted into .Xauthority from client applications. If vgl_xauth_key would be stored in a different file, and the VirtualGL libs in LD_PRELOAD would use this file instead of client .Xauthority, than client applications could not access display :0 by simply setting DISPLAY=:0 but would have to find and to use vgl_xauth_key. Similar to environment variable VGL_DISPLAY there could be something like VGL_COOKIE pointing to vgl_xauth_key.

This approach would prevent accidently access from innocent applications to display :0, but could not prevent access from evil applications directly searching for vgl_xauth_key.
For this to work VirtualGL would have to replace cookies in OpenGL requests by vgl_xauth_cookie. I can not assess if this is an easy task or would cause unreasonable overhead.

If you can somehow access the cookie for Display :0 without obtaining it through the DM process, then I'd love to hear about it.

As the cookie is created within the DM process, I don't see any way to influence it earlier. Also, I'm not as deep inaugurated into X mysteries as you are ;-). If you need access to display :0 after startup of X, you can use .Xauthority as I described above to create a manipulated cookie. This possibility seems to me rather a security leak of X than an intentional feature, but it works. Even if xauth would refuse to work at first, having any access to .Xauthority would allow to get the data.

Then when you run vglrun within the Docker container, it will load /etc/VirtualGL/vgl_xauth_key as it normally would, and that should grant access to Display :0 on the host.

As I can use my manipulated cookie, I don't need to use vgl_xauth_key. I did not test it yet, but I believe VirtualGL won't refuse to work using the manipulated cookie even if vgl_server and vglusers group are configured on host.

By the way, I don't install VirtualGL in docker images but only map the VirtualGL libs from host into docker container and set environment variables taken from vglrun on host. This way I am able to use VirtualGL in any docker image without the need to prepare it, and only need it to be installed on host.
This way I determine VirtualGL environment variables, first setting DISPLAY to :0 or another X server I want to use:
comm -1 -3 <(env | sort) <(vglrun -c 0 -d $DISPLAY env | grep -v '^\[' | sort)

@dcommander

This comment has been minimized.

Copy link
Contributor

dcommander commented Oct 19, 2016

On 10/19/16 9:58 AM, mviereck wrote:

ok, I see your point. Except that I don't need to get the cookie from
within the DM process in my use case and can get it from within running
display :0, I have to provide a cookie for display :0 anywhere in the
filesystem of the client application, may it be vgl_xauth_key or my
prepared cookie.

That's fine, but this is not a normal use case for VirtualGL. It's
designed to be used with the 3D X server sitting at the login prompt.
There are negative security ramifications to leaving the 3D X server
logged in, and I cannot support that configuration in any official capacity.

I see one possible point to improve security slightly at least. As for
now, vgl_xauth_key is inserted into .Xauthority from client
applications. If vgl_xauth_key would be stored in a different file, and
the VirtualGL libs in LD_PRELOAD would use this file instead of client
.Xauthority, than client applications could not access display :0 by
simply setting DISPLAY=:0 but would have to find and to use
vgl_xauth_key. Similar to environment variable VGL_DISPLAY there could
be something like VGL_COOKIE pointing to vgl_xauth_key.

This is not really any more secure. All a user would have to do is run
'xauth merge /etc/VirtualGL/vgl_xauth_key'. I don't think that the
advantages of what you're proposing outweigh the pain of implementing
it. In the long term, I would like to move away from using a 3D X
server at all (refer to #10), so I don't want to spend any more time
than necessary supporting new methods of accessing the 3D X server,
unless those methods have significant advantages. The current methods
work fine for the normal VirtualGL use cases.

This approach would prevent accidently access from innocent applications
to display :0, but could not prevent access from evil applications
directly searching for vgl_xauth_key.
For this to work VirtualGL would have to replace cookies in OpenGL
requests by vgl_xauth_cookie. I can not assess if this is an easy task
or would cause unreasonable overhead.

There is really no way to obscure the key. It has to be located in some
well-known place in the filesystem in order for VirtualGL to access it,
and if VirtualGL can find it, so can other applications.

As the cookie is created within the DM process, I don't see any way to
influence it earlier. Also, I'm not as deep inaugurated into X mysteries
as you are ;-). If you need access to display :0 after startup of X, you
can use .Xauthority as I described above to create a manipulated cookie.
This possibility seems to me rather a security leak of X than an
intentional feature, but it works. Even if xauth would refuse to work at
first, having any access to .Xauthority would allow to get the data.

That only works if the 3D X server is logged in, though, and keeping the
3D X server logged in is a much greater security risk than anything else
we're discussing here. The reason why we don't support or recommend
that configuration is exactly because it creates the security leak you
just described. Most large-scale VirtualGL deployments use a headless
GPU attached to the 3D X server, so there really isn't a way to log into
that X server locally. It is used only for VirtualGL access.
Conceivably someone could attach a VNC server to it, which is why
vglserver_config tries as best it can to disable XTEST (but such is
unfortunately impossible on a lot of modern Linux distributions, because
the X server command line is hard-coded within GDM these days and can't
be modified.)

@mviereck

This comment has been minimized.

Copy link
Author

mviereck commented Oct 20, 2016

ok, I see my question answered and will be satisfied with the solution I've already found.

That only works if the 3D X server is logged in, though, and keeping the 3D X server logged in is a much greater security risk than anything else we're discussing here. The reason why we don't support or recommend that configuration is exactly because it creates the security leak you just described. Most large-scale VirtualGL deployments use a headless GPU attached to the 3D X server, so there really isn't a way to log into that X server locally. It is used only for VirtualGL access.
Conceivably someone could attach a VNC server to it, which is why vglserver_config tries as best it can to disable XTEST (but such is unfortunately impossible on a lot of modern Linux distributions, because the X server command line is hard-coded within GDM these days and can't be modified.)

If you don't need to log in into X, why are you using GDM at all? You could ask to install another DM like slim instead of GDM on vglserver_config if it provides to disable XTEST, or you could run X on your own with XTEST disabled, logged in with a custom strong restricted user. I'm just curious, you don't need to spend your time on a detailed answer, and I'm sure you have conveived this already.

Maybe Wayland provides a more secure environment than X for VirtualGL, but of course a headless environment without X or Wayland would be the best solution.

Thank you for giving me some insight already!

@dcommander

This comment has been minimized.

Copy link
Contributor

dcommander commented Oct 20, 2016

Most large VirtualGL shops are deploying it on some flavor of Enterprise Linux (SUSE or Red Hat, most commonly) in production environments, so it's convenient to use the DM that is already there. Still others use VirtualGL for remotely accessing their own workstation, so they don't want to change their workstation's DM, but they don't want to leave it logged in either. Certainly system administrators are free to configure VirtualGL servers as they see fit, and some of them do use techniques similar to the ones you describe. My point is that we have to support a variety of different environments, and most of them require going through the DM to access the 3D X server, as we're currently doing. It's also worthy of note that VirtualGL is a 12-year-old product, and it came of age during my days at Sun Microsystems (late 2004-early 2009.) Back then, I was having to support Solaris 8/SPARC workstations with Sun framebuffers, and those could only run dtlogin. Furthermore, headless GPUs were not common back then, and SLiM didn't exist.

Security-wise, it's more difficult to configure a restricted user/restricted X server environment than it is to just take advantage of an existing DM environment, which is already reasonably locked down. In most cases, on modern Enterprise Linux distros, the DMs are SELinux-aware, so only certain files on the filesystem are accessible within those environments. Even with a restricted X server that was logged in with a restricted user, if another user had access to that cookie, then they could theoretically launch a window manager on that X server, or they could obtain a new cookie via the X Security extension. We could of course disable X Security as well as XTEST, but ultimately, it would be a lot of effort to come up with a VirtualGL-friendly custom headless X configuration that worked across a variety of platforms. I'd much rather spend that effort on using EGL to access the GPU (#10) instead of going through a 3D X server, but I'm seeking funding to further pursue that goal. It's somewhat easier to support DM's, because there are only a few common ones. Once I get GDM or LightDM working on one platform, making it work on other platforms is usually just a matter of handling the different locations for the DM startup scripts.

That being said, I do think it would be a good idea for vglserver_config to support some common SLiM configurations.

As far as Wayland, I have an active contract right now to look into that. Refer to TurboVNC/turbovnc#18. It's unclear to me whether VirtualGL would even be needed in a Wayland environment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.