cockpit-project / cockpit

Cockpit is a web-based graphical interface for servers.
http://www.cockpit-project.org/
GNU Lesser General Public License v2.1
11.3k stars 1.12k forks source link

Investigate systemd unit sandboxing options #21299

Open allisonkarlitskaya opened 20 hours ago

allisonkarlitskaya commented 20 hours ago

One of the attack scenarios that we consider possible in Cockpit is that one legitimate user could exploit a weakness in the large C code base of cockpit-ws to take over control of the process and use it to gain control over a logged-in session of another user. This is the main reason for why we go out of our way to isolate client-certificate-identified sessions from each other. But: I notice that we could be doing more limiting what cockpit-ws is able to do, via the large number of sandboxing options available in systemd unit files. I'm not sure, for example, that it wouldn't be possible for one cockpit-ws instance to gain control of another via ptrace() — they're running as the same user. We restrict things quite a lot with our custom selinux policy, but it would be good to look into locking things down with systemd. I'll open an issue for that.

_Originally posted by @allisonkarlitskaya in https://github.com/cockpit-project/cockpit/pull/16808#discussion_r1853104938_

allisonkarlitskaya commented 20 hours ago

This is suddenly relevant now that we no longer have the session starting as a direct descendent of cockpit-ws.

We can now more or less go wild here: practically the only thing that cockpit-ws needs to do anymore is read its config file, accept connections on an already-open listener socket, serve static files, and connect to and talk to the /run/cockpit/session socket.

allisonkarlitskaya commented 20 hours ago

Quite a shopping list here...

martinpitt commented 14 hours ago

Right! This was on my wishlist as well after landing the socket activation bits. We already lock down src/systemd/cockpit.service.in heavily (because we can), and I figure cockpit-wsinstance*.service should be able to become similarly strict.

martinpitt commented 6 hours ago

DynamicUser=yes already implies a lot of lockdown options such as ProtectSystem=full, ProtectHome, or PrivateTmp which is nice.

Wrt syscall filters, I tried

SystemCallFilter=@basic-io @file-system @io-event @memlock @network-io @process @signal 

which seemed reasonable to me. But that still crashed in uname(). I added "@aio @ipc @resources" but that didn't help. So I'm relying on systemd's recommendation of just using "@system-service", which seems to work fine. Let's find out in CI which ones I missed.

allisonkarlitskaya commented 4 hours ago

which seemed reasonable to me. But that still crashed in uname(). I added "@aio @ipc @resources" but that didn't help. So I'm relying on systemd's recommendation of just using "@System-service", which seems to work fine. Let's find out in CI which ones I missed.

It's possible to list syscall names here directly, ie: you could just say uname.