[Wine] Idea: wine + SUID sandbox = windows sandbox?

hqm wineforum-user at winehq.org
Thu May 31 07:10:25 CDT 2012

This post documents my experiment on using wine to prevent windows applications from using linux syscalls to access the filesystem, while still allowing the wine-provided Windows API to function normally.

Introduction: A lot of people want to use wine for sandboxing Windows programs, but there are so many ways to break out of it and call linux API directly: Z:, \\?\unix\, .exe.so, wine private functions, syscall, ...

What people overlook is that breaking out of wine doesn't necessarily compromise a sandbox. Note that wine, for the sake of compatibility, already has to shove most filesystem API calls to wineserver over a socket. This is pretty like the Xorg situation, where a high privilege server does stuff on behalf of a low privilege client. That leads to a natural question: what happens if we run wineserver under a non-root-but-has-something user and run wine under a sandboxed minimal-privilege user?

It turns out wine has taken lengthy measures to make sure all the wine stuff are run under the same user, presumably to prevent registry corruption. The protection measures aren't absolute, though, and we can still do a proof-of-concept experiment around it. Here is my experiment setup:

1. Create two linux users MAIN and SANDBOX. Supposedly, the user MAIN doesn't want Windows applications to access her files using Linux syscalls. Don't use your real users for this, as any mistake would corrupt their wineprefixes. 

Note: Neither user has to be a sudoer.

2. MAIN creates a normal wine prefix in some world readable place: /xxx/.wine
SANDBOX needs to have +x permission to be able to chdir within this wine prefix, but doesn't need +r beyond /xxx/.wine/drive_c, and doesn't need +w at all.

3. As MAIN, run WINEPREFIX=/xxx/.wine wineserver -p

4. As root, do a bunch of hacks to get around wine checks:
    chown SANDBOX /xxx/.wine
    ls /tmp/.wine-`id -u MAIN`/
You should see a server-...-..... directory here, which holds MAIN's wineserver socket. We now fake a similar directory for SANDBOX and hardlink the sockets in.

    mkdir /tmp/.wine-`id -u SANDBOX`
    mkdir /tmp/.wine-`id -u SANDBOX`/server-...-...../
    ln /tmp/.wine-`id -u MAIN`/server-.../lock /tmp/.wine-`id -u SANDBOX`/server-...-...../lock
    ln /tmp/.wine-`id -u MAIN`/server-.../socket /tmp/.wine-`id -u SANDBOX`/server-...-...../socket
    chown -R SANDBOX /tmp/.wine-`id -u SANDBOX`
    chmod -R a-rwx /tmp/.wine-`id -u SANDBOX`
    chmod -R u+rwx /tmp/.wine-`id -u SANDBOX`

Note that these root hacks won't be required if one removes the safety checks from wine code and removes the uid component from the socket path.

5. Run windows application under that wineprefix as user SANDBOX, e.g.:
    su SANDBOX
    WINEPREFIX=/xxx/.wine wine cmd

6. The wine cmd is able to read/write files normally in that wineprefix, but if you enable Z: (as root) and call things like /bin/ls or /bin/sh, you actually LOSE that access, since the linux user SANDBOX, who runs the wine loader, doesn't have the necessary privileges.

Now this creates an interesting situation: the Windows program can easily break out of the wine emulation, but can't gain anything by doing that. In fact, it couldn't even read/write its own C: by calling linux functions directly. I believe this may actually make wine a viable sandbox for running (potentially) malicious Windows programs, if only wineserver could be hardened a bit. 

Note: Currently, the Windows program should still be able to access the entire filesystem from this sandbox with MAIN's privilege by calling CreateFile with a \\?\unix\ path. Also, the Windows program would still encounter a few rough edges, e.g. it can't rename files or kill processes (even those spawned by itself). These issues could be easily fixable by patching wine, though.

More information about the wine-users mailing list