borgbackup / borg

Deduplicating archiver with compression and authenticated encryption.
https://www.borgbackup.org/
Other
11.18k stars 742 forks source link

include stricter shell as recommended ssh configuration #8318

Open qyanu opened 3 months ago

qyanu commented 3 months ago

Hello!

Context

i currently use borg 1.x on a debian bookworm system, where i (also) want the server to not trust the clients that much and said clients connect to the server (and send data) over the network via ssh. This is as described in (one of) the configurations recommended by borg in its documentation.

Documentation reference: https://github.com/borgbackup/borg/blob/6039349932a874fbb6d053b1dd5d7d400780378b/docs/usage/serve.rst?plain=1#L47

I create this issue against the 2.x branch, but it both concerns the 1.x and 2.x documentation. I couldn't find a previous issue discussing (and possibly rejecting) my proposal through the github issue search, but i am not very confident that i didn't miss a related issue.

This issue proposes an improvement to the documentation, described just now. Further down, a longer rationale is given for the change.

Proposed Improvement

In the documentation, in the section Usage > borg serve > Example and also the following section SSH Configuration, the text should also mention that setting a shell with smaller footprint for the user under which borg serve is started, will reduce attack surface.

Rationale

I suppose that many users expect their backup-strategy to also hold (i.e. provide a means of disaster-recovery) with a reasonable certainty in the face of a "hacked" borg-client (e.g. a user's daily workstation); this is certainly a goal with my backup-strategy. When borg is chosen as a building block for this backup-strategy, and borg is setup on a separate backup-server according to the description presented in the documentation section "Usage > borg serve", then i think this setup is needlessly in risk of shell-bugs similar to shellshock (CVE-2014-6271 and others, see: https://en.wikipedia.org/wiki/Shellshock_(software_bug) ).

Note It must be noted, that all this discussion is strictly speaking outside the scope of borg. However, since borg elects to giving ssh-related configuration directions in it's documentation, it takes on (some) responsibility of recommending a secure-by-default configuration.

In the recommended setup, the forced command (specified in the authorized_keys file) is executed by sshd by using $SHELL -c $COMMAND, where $SHELL is the user's login shell, and $COMMAND is the forced command (ref: https://manpages.debian.org/bookworm/openssh-server/sshd_config.5.en.html#ForceCommand ). Now if the user's shell is configured to be /bin/bash (as is the default in the operating system i use, debian bookworm, and i suppose is easily the default shell in other linux operating systems), then a very large codebase is "pulled in" into the attack surface. For example a similar situation to the bug coined shellshock, in which a carefully crafted environment variable will lead to arbitrary code execution, might come around. After all, the borg-client connecting to borg-serve through ssh is in full control of the contents of the environment variable SSH_ORIGINAL_COMMAND.

However, in order for the data transfer between the borg-client and borg-serve to work, actually all the bash-features and thus all the extra code are not needed. Thus, reducing the loaded code reduces the attack surface and finally reduces the chance of there being some (hidden) security bug.

sub-idea

When a dedicated user is used on the backup-server, then that user's shell could be set to a special borg-ssh-shell wrapper binary (to be implemented some day). This way, no traditional shell (/bin/sh, /bin/bash, etc) is started at the backup-server at all. Then sshd would still execute $SHELL -c $COMMAND, but $SHELL is now the borg-serve wrapper. This wrapper would discard argv[1] (which is always -c), split argv[2] in a shell-like manner (as ssh gives the command to $SHELL in one string), retain environment variable SSH_ORIGINAL_COMMAND and then execve (ref: https://manpages.debian.org/bookworm/manpages-dev/execve.2.en.html ) the actual borg-serve process with the such calculated argv and envp.

ThomasWaldmann commented 3 months ago

Interesting idea - did you practically try some alternative, small shells with borg 1.x client/server setup?

qyanu commented 2 months ago

@ThomasWaldmann on my backup server, i indeed did the two recommended steps with a username "borg" and debian's reduces bourne shell "/bin/dash":

dash is debian's "posix-compliant no-additional-features" shell. Just now, i did not (yet) evaluate any other shells, since i would instead invest the time in trying out the idea with the borg-as-login-shell wrapper.

qyanu commented 2 months ago

Looking through the list of debian packages in the "shells" section [1], posh might be another candidate, besides dash, as small /bin/sh implementation. dash would still have the advantage of being an essential package in debian and therefore being installed anyway (and supposedly therefore with greater scrutiny by debian developers or the debian security team).

However, regarding the topic of this github issue, i would not recommend writing any linux-distribution specific wordings into the borg documentation. I would rather point out the considerations, that using a dedicated user and a minimal shell are good practices.

[1] https://packages.debian.org/unstable/shells/

qyanu commented 2 months ago

I have started writing some text, but writing understandable documentation is hard. This is what i got so far: https://github.com/qyanu-pull-requests/borg/tree/3818recommendchsh-master

Feedback from colleagues suggests, that this whole business of sshd using the user's login shell might be a surprising decision on part of openssh, and borg itself should stay away from dealing with it (I don't necessarily agree). One also mentioned, that some users with non-default shells (the example csh was mentioned) would need a different force command anyway.

Since i value the mentioned colleagues as non-beginner users, and having them consider the openssh behaviour surprising tells me, that a good documentation should address this.