It’s hardening time again.
Following up on my post “DNSSEC, SSH and keys.” this is another post in the series of hardening your SSH server and your server in general. Are you using password login or public keys?
Indeed. Why not both? And I am not going to recommend you that should put a password on your ssh keys (which is nice) but rather recommend real two-factor authentication: Public Key and a Password. What does it do?
Let me show you; but I am using kerberos instead of Passwords, so your mileage might vary, but the result is the same. At first connect your client gets the offer of sending either:
debug1: Authentications that can continue: publickey,gssapi-with-mic debug1: Next authentication method: gssapi-with-mic [...] Authenticated with partial success. debug1: Authentications that can continue: publickey debug1: Next authentication method: publickey debug1: Trying private key: /home/creiss/.ssh/id_rsa [...] debug1: No more authentication methods to try. Permission denied (publickey).
The important bits are in bold. What happens in human readable form:
- The Server offers to authenticate with Kerberos or (giggle, “or”) public keys.
- My client, having a valid kerberos ticket, sends it to the server.
- The Server accepts the kerberos ticket, but is greedy and wants more (authenticated with partial success). If my kerberos ticket would not have been valid, I’d get rejected right there.
- I moved my .ssh folder out of the way, so there is nothing for my client to send to the server. And even thou I was authenticated with a valid kerberos ticket I get denied. I need both public keys and kerberos to access.
Let’s check what happens which a valid public keypair:
debug1: Authentications that can continue: publickey,gssapi-with-mic debug1: Next authentication method: gssapi-with-mic [...] Authenticated with partial success. debug1: Authentications that can continue: publickey debug1: Next authentication method: publickey debug1: Offering RSA public key: /home/creiss/.ssh/id_rsa debug1: Server accepts key: pkalg ssh-rsa blen 535 [...] debug1: Authentication succeeded (publickey). Authenticated to ns1.alpha-labs.net ([22.214.171.124]:22).
This is the same as above, but my ssh private key got accepted, resulting in authentication. So I need something I know (kerberos password) and something I have (public key pair).
Again, don’t panic about kerberos. Just replace ‘gssapi-with-mit’ with ‘password‘ and you’re set. If you can, go for kerberos. It’s called the “holy grail of network administration” for a reason.
If you really need an answer on why hardening your remote access to your server is crucial you should reconsider the guy in charge of your security.
To implement two-factor ssh authentication, be sure you know your password and that you have a key pair which has also been added to the authorized_keys file on the target server. Add this to your /etc/ssh/sshd_config file for CentOS 6.x:
and this for CentOS 7.x:
Easy? Easy. Be careful: If you lose your client side key pair you will be unable to log in (via ssh).
Taking it up a notch
But the fun does not stop there– and why should it? Now you can easily connect to your favourite server and get a user shell. I am seriously hoping you’re not allowing direct remote root access. Tell me you don’t.
Of course you don’t. You’re not crazy.
We use sudo.
In this wonderful comic by xkcd there is no further authentication for granting superuser privileges– and of course there is no such thing; it’s a comic.
We however are serious admins. We want further proof. If you have your sudo to ask for a password then turn that off. Why bother having two locks that can be unlocked with the same key? A possible attacker that got to your shell has both your public and private key pair (can happen– hey, in the office someone is sitting in front of your pc (kill him, use a Nerf gun) or your notebook has been snatched at the airport) and your password. How an attacker managed to get the latter I leave open for discussion.
So for further authentication attempts you can’t re-use any of those again. But we want it comfy.
Enter the YubiKey. A cheap security token for your keychain, cost on amazon for 50 bucks (biggest edition, you can save if you get a smaller one). You put that device in your usb port and push a button. OTP magic happens and wham, authed:
[chris@artemis ~]$ sudo su - YubiKey for `chris': Last login: Wed Aug 19 21:08:26 CEST 2015 on pts/2 [artemis ~]#
I just pressed that button, no enter no nothing. And I got root.
Installing is a trivial matter, there are packages in the stock repositories for CentOS (pam_yubico) and Debian (libpam-yubico). Do an yum install pam_yubico or apt-get install libpam-yubico respectively and you’ll end up with the right package. Onward with the configuration, then!
For all flavors, edit /etc/pam.d/sudo and add, below ‘#%PAM-1.0‘, this line:
auth sufficient pam_yubico.so id=[api_id] mode=client authfile=/etc/yubikey_mappings
Replace “[api_id]” with your yubico api id. If you do not have one already, get one from here. The line explained:
- auth: Well, it does authenticate you, so 🙂
- sufficient: Satisfying this rule alone will grant access. If you want a two-factor login where you also have to type in your password, replace sufficient with required.
- pam_yubico.so: That’s the library we apt-get’ed or yum’ed earlier.
- mode=client: tells said library to go to the “yubico cloud”, ie, the official api servers to check. Other mode would be “challenge-response” for offline validation using YubiKeys with HMAC-SHA-1 Challenge-Response configurations. (See the man-page ykpamcfg(1) for further details on how to configure offline Challenge-Response validation.)
- authfile: Every YubiKey needs to be mapped to one user. Actually that’s wrong. A User can be assigned one-or-many Yubi-Keys. This is the mapping.
Edit (most likely create) the file /etc/yubikey_mappings, and add a user per line:
user:yubikey_id1:yubikey_id2: [...] yubikey_idn
real life example for me:
Don’t know your YubiKeys ID? Go to the ModHex calculator and give them one OTP (go into the OTP field and press your YubiKeys button). In the resulting page your ID is the “Modhex encoded” value. Sounds way more complicated that it is. As shown, separate each of your YubiKeys with a “:”.
That’s it for sudo. Next time you login, you’ll see the YubiKey prompt. Hit the button and feel the rootness.
So now (and hopefully you) can now auth securely and ascend to root by simply ssh’ing (no passwords asked, kerberos hooray). In the background kerberos tickets and ssh key pairs are exchanged all of which I never see, I am dropped right at my user shell.
And if I want root: “sudo su –” and the push of a button– and that’s all there is to it.
As always: If you need help implementing, contact me above.