Challenge, Medium,  on  LinuxSecurity

Restrict Access to a Unix Domain Socket

A Unix domain socket is the most common way for a daemon to expose a local API: the daemon binds a socket file, usually somewhere under /run or /var/run, and clients connect to that path instead of a TCP port.

Your task

The deployd daemon runs as a systemd service and listens on /run/deployd.sock. Sending it the DEPLOY command triggers a (simulated) production deployment - clearly not something an unprivileged user should be able to do. Right now, though, the socket is world-accessible.

Restrict access to /run/deployd.sock so that only root and members of the deploy group can connect to it. The restriction must also survive a restart of deployd, so that the socket is not left unprotected the next time the daemon comes back up.

Two user accounts are provided to check your work:

  • alice is a member of the deploy group and must always be able to reach the socket.
  • bob is a regular user and must always be refused access to the socket.

You can probe the socket as either user with the bundled client:

sudo -u alice deployctl PING
sudo -u bob deployctl PING

💡 Docker works exactly like this - the docker CLI talks to dockerd over /var/run/docker.sock.

Because a socket is just a file, anyone who can open it can control the daemon via its API. That is why /var/run/docker.sock is owned by root:docker with mode 0660: only root and members of the docker group can send API requests, while everyone else is denied access. Getting the socket path permissions wrong is a real privilege-escalation risk.

Hint 1: A Unix domain socket is a file

A Unix domain socket has an owner, a group, and permission bits, exactly like a regular file. Inspect it:

ls -l /run/deployd.sock
stat /run/deployd.sock

Connecting to a stream Unix socket requires write permission on the socket file. So to let only root and the deploy group members in, the socket needs the right group owner and a mode that grants the group access while denying "others" - the same root:docker, 0660 arrangement Docker uses.

Hint 2: How to make the protection stick

Changing the owner and mode of the live socket with chown/chmod works only until deployd recreates the socket - which it does every time the service restarts.

More advanced daemons may have a way to specify the owner and permissions of the socket file (e.g., dockerd has a -G flag for it), but deployd is a simple, bespoke daemon: it takes no options and always recreates the socket with the same hard-coded 0666 permissions. Assuming you cannot rewrite the daemon, the chown/chmod change has to be reapplied on every start.

Look at how the daemon is launched:

systemctl cat deployd.service

systemd can run an extra command right after a service starts. Find a [Service] directive that does this (the key word is "post start"), and use it to re-own and re-mode the socket each time deployd comes up. Then reload systemd and restart the service so the change takes effect.