One of the questions that occupy people's mind is how to securely store SSH keys. In this article I will show what is my strategy.
My threat scenario is an attacker that gains remote access to my workstations and therefore can login into remote hosts I manage.
The first obvious piece of advice it to keep as less as possible SSH keys on any machine.
The second good practice is to store passwords on a FIDO token and configure it to decrypt passwords only with a physical contact from the user.
§ Generate an SSH key
Create a passphrase using this script (courtesy of Dr. Duh documentation)
generate_passphrase ()
{
export CERTIFY_PASS=$(LC_ALL=C tr -dc "A-Z3-9" < /dev/urandom | tr -d "IOUS5" | head -c ${PASS_LENGTH:-24} | fold -w ${PASS_GROUPSIZE:-4} | paste -sd ${PASS_DELIMITER:--} -);
printf "\nPassphrase:\t%s\n\n" "$CERTIFY_PASS"
}
Generate the SSH key and protect it with the passphrase. The parameters will ensure that is stored on the FIDO device currently unlocked (-O resident), and that can be used only for ssh and git (-O application=ssh:git):
$ ssh-keygen -t ed25519-sk \
-O resident \
-O application=ssh:git \
-C "user@host"
Then configure the ssh client to use it:
Host remote.host
Hostname 123.123.123.123
User user
IdentityFile ~/.ssh/the-ssh-key
Copy the SSH public key to the remote host:
ssh-copy-id ~/.ssh/the-ssh-key user@host§ An SSH git user
Let's say you have a git private repository on the server. You access the git repository via SSH. The remote ssh user doesn't need an interactive shell, it only needs to run git commands, so let's lock it down a bit with git-user(1):
# usermod -s /usr/bin/git-shell <user>
then bind the login to a non-interactive shell command (command adapted from git-shell(1)):
$ mkdir $HOME/git-shell-commands
$ cat >$HOME/git-shell-commands/no-interactive-login <<\EOF
#!/bin/sh
printf "This user has no interactive shell\n\n"
exit 128
EOF
$ chmod +x $HOME/git-shell-commands/no-interactive-login
And while we're here, we can also avoid the shell being too chatty
>$HOME/.hushlogin