Created
November 11, 2020 09:30
-
-
Save linuxthor/9bd20e59d1afb72ba1dd22b1f5a055e2 to your computer and use it in GitHub Desktop.
sftp-gotchas.txt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
A couple of thoughts about SFTP & SCP | |
===================================== | |
SCP looks long in the tooth now and people have come to talk about deprecating it entirely. This | |
is due to SCP being the spiritual successor of RCP and inheriting a bunch of cruft that makes it | |
vulnerable to stuff like CVE-2019-6111 (the one where the server could overwrite arbitrary files | |
on the client) and CVE-2020-15778 (the one where shell commands could be put in backticks in | |
filenames) so SFTP seems to be the replacement.. It's a more flexible protocol for sure but there | |
can be a gotcha not present with SCP.. | |
SFTP allows resumed transfers (upload or download) at some offset the client specifies.. and the | |
issue I have in mind is actually mentioned in the OpenSSH SFTP code.. | |
/* | |
* On platforms where we can, avoid making /proc/self/{mem,maps} | |
* available to the user so that sftp access doesn't automatically | |
* imply arbitrary code execution access that will break | |
* restricted configurations. | |
*/ | |
platform_disable_tracing(1); /* strict */ | |
So.. it sets the process non-dumpable and that's fine.. but it can't do anything about other processes | |
that happen to be running as the same UID.. | |
Imagine a scenario.. a restricted user is created: | |
sftpnob:x:1001:1002::/srv/ssh/jail:/usr/sbin/nologin | |
This user has no login shell - often, I'm sad to say, I've seen setups where this was considered 'good | |
enough' for an "SFTP only user" - but we'll imagine the admin did a little more and tried to restrict | |
the user further: | |
Match Group sftponly | |
ForceCommand internal-sftp | |
AllowTcpForwarding no | |
X11Forwarding no | |
The crucial mistake here is not chrooting the user via ChrootDirectory %h or similar. If the user can reach | |
/proc then they can write into another processes memory via the /proc/PID/mem pseudo file (they can know exactly | |
the offsets by downloading /proc/PID/maps and studying it) | |
You might be thinking at this point that there wouldn't be a process for the poor sftp user to mess with | |
as the OpenSSH folks made their stuff undumpable and it *should* be the case but you can always rely on | |
systemd to do something.. Interesting.. ;-) | |
sftpnob 32235 0.0 0.0 110164 3712 ? S 15:59 0:00 \_ sshd: sftpnob@notty | |
sftpnob 32237 0.0 0.0 110164 3264 ? Ss 15:59 0:00 \_ sshd: sftpnob@internal-sftp | |
sftpnob 32112 0.4 0.0 76812 7808 ? Ss 15:59 0:00 /lib/systemd/systemd --user | |
sftpnob 32113 0.0 0.0 262076 2920 ? S 15:59 0:00 \_ (sd-pam) | |
In my testing the systemd user process can be written to in this scenario. It's stack can be completely | |
replaced or whatever. | |
(In many distros you can't write to /proc/PID/mem as Yama sees it as ptracing but if there is no Yama then | |
it can be possible) | |
Of course if systemd is in the mix and we're looking at this same scenario of the poorly restricted user | |
then they might just as well do something like: | |
sftp> mkdir /run/user/1001/systemd/system.control/ | |
sftp> put /tmp/spawn-reverse-shell.service /run/user/1001/systemd/system.control/systemd-exit.service | |
and log out to get a shell (making it persist longer than a few seconds being possible by dropping a cron | |
etc) | |
Something slightly esoteric that I think it's worth knowing about when considering SFTP as a replacement for | |
SCP. |
Author
linuxthor
commented
Nov 11, 2020
-
- When I say "can't do anything about" - Yes.. the offsets could be fixed at some range (but perhaps there are people with use cases where they want to seek really far into huuuuge files that report a zero size(?)) I was more meaning that the fix would probably diverge somehow from the spec as written so it would be something that needed to considered/maintained as an exception case.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment