-
Epic
-
Resolution: Unresolved
-
Major
-
None
-
Prevent cross-frame command execution
-
40
-
False
-
None
-
False
-
?
-
RHELBU-2233 - Cockpit security enhancements
-
?
-
sst_cockpit
-
?
-
0% To Do, 7% In Progress, 93% Done
-
doc-ready, qe-ready, ux-ready
-
Bug Fix
-
Quarterly Plan 23Q1
With current cockpit, a frame (i.e. a cockpit page from a particular host) can access other frames. That means when you connect to a malicious host in Cockpit, it can damage all other connected hosts.
We should prevent this, and only allow frames to access themselves. The only exception is the shell, which of course needs to access all frames, but they are children of it. Peer-to-peer frame operations are neither needed at the moment, nor desirable.
We need to check how this affects page status notifications.
swalter@redhat.com experimented with this many years ago in https://github.com/cockpit-project/cockpit/pull/6260 but it never got completed.
Original threat modelling document from rhn-engineering-thoger
Meeting document https://docs.google.com/document/d/1vlCfqphBeOeszpYvz-NtZX3J-0Th3r2firjdqKNJZ34/edit#heading=h.yoyesevdgum1
Related bugs:
- https://bugzilla.redhat.com/show_bug.cgi?id=2161087
- https://bugzilla.redhat.com/show_bug.cgi?id=2161090
- https://bugzilla.redhat.com/show_bug.cgi?id=2161094
Possibly related/helpful: https://developer.chrome.com/blog/anonymous-iframe-origin-trial/
Design discussion
There is a magic triangle ("pick any two") about desirable Cockpit properties:
- SSH keys: Connect to production hosts with SSH key authentication
- Compatibility: Connect to different OS/versions with well-defined functionality
- Untrusted machines: Remote machines cannot influence the host or other remote sessions
Details about these properties
SSH keys
Connecting to a remote machine with SSH key authentication has to happen either from a running local Cockpit session (to load keys from and have an SSH agent), or from the Client flatpak.
In principle, the login page could allow uploading an SSH key and spawn a temporary SSH agent (not attached to any user, single-usage). However, this feels way too dangerous: both the key and its password have to go through the browser, possibly the internet, and through cockpit-ws. We may also not be able to guarantee that parallel login attempts couldn't interfere with each other, or always reliably cleaning up the temporary SSH agent. So we are not going to do that.
Compatibility
So far our guiding principle was that a cockpit-foo UI/package co-evolves with the corresponding foo API. We have comprehensive integration tests which ensure that our UIs adjust to and grow with API changes/additions/deprecations. We've seen plenty of such changes in e.g. podman or libvirt; other parts (like systemd or PCP) have been relatively stable over the years.
We also have dropped functionality ourselves, e.g. cockpit-docker, cockpit-kubernetes, or cockpit-dashboard on RHEL 7. This generalizes to different remote machines having different roles, installed packages, and APIs. E.g. the local host may not have libvirt and cockpit-machines installed, but a remote one does.
Thus, starting a Cockpit session on a remote machine loads and runs the installed cockpit-foo* packages from that machine, instead of the local host.
Untrusted machines
The shell's "Add host" functionality allows the user to run multiple parallel Cockpit sessions for different machines.
There are plenty of ways how a malicious remote machines can run arbitrary commands on all other currently running Cockpit sesssions: iframe traversal, opening a new web socket, or the "host" channel option. Fixing the latter is easy, but fixing the first two is somewhere between "hard" and "impossible": Despite weeks of research and discussion, we haven't been able to find a solution which isolates remote iframes from each other and from the Cockpit host. It is currently unknown whether this is possible at all. However, we do know that if it is possible, implementing it would be many months of work.
Goal conflicts
SSH keys and compatibility, sacrificing untrusted machines
This is the status quo. The "add host" dialog currently shows a warning. We mostly get away with this because in many environments the remote machines have similar trust levels, and also Cockpit makes it (deliberately) relatively hard to connect to many machines at the same time.
SSH keys and untrusted machines, sacrificing compatibility
This could be achieved by never loading manifests/pages from remote machines, and always using the local ones instead. But with our current level of CI and project maintenance we cannot make any guarantees: We know that e.g. current cockpit-machines won't work on RHEL 7, or current cockpit-podman won't work on Ubuntu 20.04 LTS.
The "certified to work" part could be fixable by significantly increasing our CI coverage, like re-enabling RHEL 7 and 8, Ubuntu 20.04 LTS, or Debian oldstable. Plus keeping deprecated functionality and hacks for a lot longer, which increases permanent maintenance and decreases velocity further.
But the "different roles" part is not fixable in principle: If the local host dosn't have some cockpit-foo package installed (or available even!), you cannot have that functionality for any remote host.
So the "compatibility" goal seems the hardest and least desirable to sacrifice.
Compatibility and untrusted machines, sacrificing SSH keys
Our login page already offers a "direct SSH login" with user+password, or more generally, PAM – e.g. 2FA is supported. However, this cannot support SSH key authentication – browsers don't speak SSH, and web pages don't have access to the user's SSH agent/keyring.
We could instantly fix all the issues in this epic by dropping the "Add hosts" feature. Then we would essentially drop SSH key auth from non-Linux clients (i.e. general browsers), this would only work with our Flatpak, and in "single key" custom configuration of our ws container.
It is currently unknown how many users this would affect. However, we do know that for our RHEL customers a lot of users have Windows clients, not Linux.