Source linked

LXC + idmap + X11 socket: sandbox un navigateur sans sacrifier votre répertoire d'accueil

dobrowolski.dev@systems_wireyesterday·Systems Engineering·7 comments

Map container root pour héberger UID 100000 de sorte qu'un exploit de navigateur qui échappe à LXC hérite de zéro autorisations - et transmet X11 sans casser .Xauthority

lxclinux containersx11idmapapplication sandboxingarch linux

A browser exploit that chains a sandbox escape and a kernel vuln can read your entire home directory. One LXC configuration line maps container root to a host UID that doesn't exist — UID 100000 — so even a full escape hands the attacker no readable files.

That's the trick in a recent walkthrough by dobrowolski.dev: use unprivileged LXC containers with lxc.idmap = u 0 100000 65536 (and the same for GID). The container's root owns every file inside, but on the host those IDs sit in an unmapped range (100000–165535). No file on the host is owned by those UIDs, so cat /etc/shadow simply returns nothing.

veth, subuid, and the /etc/default/lxc dance

Start with pacman -S lxc lxcfs, then enable lxc-net.service to get a lxcbr0 bridge. The container config hooks into that bridge with four lines: veth, link=lxcbr0, flags=up, and a custom MAC. The real security comes from /etc/subuid and /etc/subgid — add root:100000:65536 to both files to authorize LXC to use that ID range.

dobrowolski.dev points out you can stack multiple ranges: root:100000:65536 plus root:200000:65536 lets you spin up separate containers with completely disjoint host ID pools. Each container's root maps to a different high-numbered UID; they cannot interfere with each other even if one is compromised.

X11 forwarding without the hostname mismatch

Mounting /tmp/.X11-unix into the container is the easy part. The hard part is .Xauthority — cookies are keyed by hostname, and the container's hostname won't match the host's. The fix: xauth nlist :0 | sed 's/^..../ffff/' | xauth -f /tmp/lxc.Xauthority nmerge -. That replaces the family field with FamilyWild (0xffff), making the cookie match any host. The resulting file is then bind-mounted read-only into the container at /tmp/lxc.Xauthority.

One last ownership detail: the .Xauthority file is owned by your host UID, but inside the container the IDs are shifted. Since the file is mounted read-only and the container's root maps to UID 100000 on the host, the container process can't even write to it — exactly what you want.

The complete config lives in /var/lib/lxc/www/config, not the template file. Add lxc.environment lines for DISPLAY=:0 and XAUTHORITY=/tmp/lxc.Xauthority, plus two lxc.mount.entry lines for the X11 socket and the auth file. Spin it up with lxc-create using a Debian trixie image, install Firefox inside, and run it as a dedicated www user.

This isn't a new product — it's a century-old UNIX trick (namespaces) combined with a decade-old security pattern (unprivileged containers). What's missing is a tool that automates the whole thing: a lxc-app wrapper that generates the idmap, creates the .Xauthority, and drops you into the container with one command. Until then, the 20-line config file is the best sandbox a sysadmin can build with standard tools.


Source: Enhancing X11 Application Security with LXC
Domain: dobrowolski.dev

Read original source ->

External source stays available while the OJO article and comment thread stay local.

Comments load interactively on the live page.