The key that the website logs in with was written into the authorized_keys of the Administrator, which would have given everyone who has the website administrator rights on the box. It only gets access as the root user. The deploy script logs in as Administrator with the personal key of the deployer instead, from the agent or from -i. Co-Authored-By: Claude Code <noreply@anthropic.com>
5.2 KiB
The shell server
The website's terminal connects to a shell server, whose root user logs in at wss://web.nowhere.wirs.ing and
gets a shell on the box.
The security model
The box is an isolated, disposable VPS at a random hoster. We assume that it can be compromised and that this is acceptable: the worst case is that the gimmick on the website stops working. Nothing else is on the box. The website and the websocket bridge that carries the connection run on other servers, so a compromised shell server cannot get at them.
The root user on the box is a normal Windows account without administrator rights. It may do a lot of things
there, including things we did not plan for. We do not try to contain it and we do not try to undo what it does.
We only keep the basic user journey working.
What we keep working
- The prompt:
root@khaos-im-kiez:~#, which~/.zshrcsets. - The home directory the user ends up in:
/home/root. It is the one from therootentry in/etc/passwd, which the user cannot change, because/etcis read-only for them. They can delete their home directory, though. cat README,cat README.en,cat CODE_OF_CONDUCTandcat CODE_OF_CONDUCT.enalways work. The four files are always there and always regular text files.- The website can log in: the key it uses is in
~/.ssh/authorized_keys. That key gets access to therootuser only, never to the Administrator account, whose keys belong to the people who deploy.
Modifying the four files is allowed; the next cleanup undoes it. Deleting them is not permanent either.
The user may add keys of their own to authorized_keys; they stay. The key of the website is put back, so that the
site keeps working. The user owns their home directory, so they can always delete the file - nothing on Windows can
stop them from that - but the next cleanup brings it back. Until then, the site cannot log in.
What we do not keep working
Everything else. If the user breaks the shell, the packages, the disk or the connection, we fix that by hand or throw the box away. The cleanup does not try.
Two things that the user cannot break and therefore do not need to be restored: the entry in /etc/passwd with
the home directory and the shell, and the host keys in /etc/ssh, which the website pins. The sshd runs as SYSTEM,
so the user cannot restart it with a different key either.
The cleanup
The scheduled task KiK restore shell files runs every 30 minutes and at every startup, as SYSTEM. The user cannot
stop it: the task, its script and the copies it restores from are readable and writable only by SYSTEM and the
administrators.
Neither the setup nor the cleanup ever runs as the root user. The setup runs in an elevated PowerShell, as an
administrator, and refuses to run without those rights; the cleanup runs as SYSTEM. The root account is a
different one, without administrator rights, and it never executes any of it.
What the cleanup does:
- Creates
/home/rootif it is gone, and gives therootaccount write access on it. - Puts every copy in
files/back into the home directory: the shell configuration, the keys and the four text files.
Anything that is not a regular file - a directory or a link - is removed and replaced by the copy, so that the files cannot become anything but text. The contents are restored as well: the user may edit the files, the next run undoes that.
This directory
home/- the files that belong in the home directory of the user:~/.zshrc,~/.zshenvand the key in~/.ssh/authorized_keysthat the website logs in with. This is where they are edited.resources/- the copies the cleanup restores from: the four text files and the files ofhome/.scripts/make_files.py- builds the resources.scripts/deploy.sh- deploys the cleanup to the server and installs it.scripts/install_restore_task.ps1- installs the scheduled task.scripts/restore_ssh_access.cmd- puts the SSH access back, for when the home directory was deleted.
The resources are built from the website's pages and the files of home/:
python3 server/scripts/make_files.py
Installing the cleanup on the server
server/scripts/deploy.sh
The script logs in as Administrator - whose shell is a Windows one - copies the scripts and the resources to the
Administrator's home directory and runs the installer there. It logs in with the personal key of the deployer, from
the agent or from -i; the key of the website never gets administrator rights, it only logs in as the root user.
It checks the host key against the one the website pins, and checks that the key in home/.ssh/authorized_keys is
the one the website uses. --uninstall removes the task again.
The installer can also be run by hand, in an elevated PowerShell on the server:
powershell -ExecutionPolicy Bypass -File .\scripts\install_restore_task.ps1
The task runs as SYSTEM, so the root user can neither stop it nor change the copies it restores from. It also
runs at startup. Remove it again with -Uninstall.
Getting the SSH access back
If the home directory was deleted, the key that lets the website in went with it. Over RDP, as Administrator, run
scripts/restore_ssh_access.cmd. From then on the cleanup puts the key back by itself.