Is it OK to set up passwordless `sudo` on a cloud server?

Solution 1:

I love the idea of accessing servers via keys, so that I don't have to type in my password every time I ssh into a box, I even lock my user's (not root) password (passwd -l username) so it's impossible to log in without a key...Would you recommend/not recommend doing this for a user account on a server?

You're going about disabling password-based logins the wrong way. Instead of locking a user's account, set PasswordAuthentication no in your /etc/ssh/sshd_config.

With that set, password authentication is disabled for ssh, but you can still use a password for sudo.

The only time I recommend setting NOPASSWD in sudo is for service accounts, where processes need to be able to run commands via sudo programmatically. In those circumstances, make sure that you explicitly whitelist only the specific commands that account needs to run. For interactive accounts, you should always leave passwords enabled.

Responses to your follow-up questions:

But I guess that if I disable password authentication in /etc/ssh/sshd_config so that you still have to have a key to log in, I can use a simpler password just for sudo that's easier to type in? Is that a valid strategy?

Yes, that's correct. I still recommend using relatively strong local account passwords, but not ridiculously-strong. ~8 characters, randomly generated is sufficient.

If I also have a key to log in as root via ssh, if somebody gets access to my computer and steal my keys (they're still protected by OS' keyring password though!), they might as well get a direct access to the root account, bypassing the sudo path.

Root access via ssh should be disabled. Period. Set PermitRootLogin no in your sshd_config.

What should be the policy for accessing the root account then?

You should always have a means of obtaining out-of-band access to the console of your server. Several VPS vendors do provide this, as do vendors of dedicated hardware. If your provider doesn't grant real console access (say, EC2 for instance), you can typically still restore access using a process like what I outline in this answer.

Solution 2:

I generally restrict use of NOPASSWORD to commands that are run by an automated process. It is preferable to have a service account for these commands, and restrict the use of sudo to the required commands.

Allowing NOPASSWORD for general commands, allows anyone who gets access to your userid to run any commands. This could result from a compromise of your credentials, but could be as simple as someone sitting at your desk when you step away for a second.

I find I don't have to enter my password that often. Once you enter your password, you can run several commands if you don't wait too long between them. The timeout is configurable.


Solution 3:

You can have the best of both worlds: SSH authentication for both login and for sudo. If you integrate the pam_ssh_agent_auth module you can use SSH keys to authenticate without giving a password when you sudo.

I've been using this in production for more than five years.

To configure it, install the PAM module, and then add a line to /etc/pam.d/sudo or your system's equivalent:

auth    sufficient     pam_ssh_agent_auth.so file=~/.ssh/authorized_keys

If you do this, be sure to protect your keys on your computer with a passphrase. That way, someone would have to break into your computer and steal the keys to get in. They could do that by pulling them from memory while they were unlocked if they have access to your account, by cracking your passphrase, or stealing your passphrase through a keylogger or shoulder surfing it while you type it in (look behind you!).

You can use the same SSH key as you do to login, or you could set up a separate key that you only add to your agent when you sudo. So if you want to be extra careful, you could maintain a separate authorized_keys file that has a separate SSH key that you only add to your agent when you need to sudo:

auth    sufficient     pam_ssh_agent_auth.so file=~/.ssh/authorized_keys_sudo

Solution 4:

I would only use this in two circumstances:

  • When it is absolutely required for an automated script that is running as a specific user
  • For specific admin tasks (read only admin tasks, not those that take action to alter the system) and then only for specific users of course

By default most sudo configurations will not ask you again for a while in the same session (if you open a new shell that doesn't have any effect). You can control this behaviour to an extent with the timestamp_timeout setting.

Password-less sudo is not nearly as dangerous as passphrase-less ssh keys, as a remote attacker needs your credentials to get in in the first place, but if they have got in by somehow compromising your private key (or if they are physically local to you and you've left yourself logged in and unlocked while away from the machine) then the password request is a valuable extra defence between them and privileged access.

Regarding follow-up 2:

If I also have a key to log in as root via ssh

This is best avoided too, for exactly the reason you describe. If a remote connection must have privileged access have it login via a service account and give that just enough control to do its job via sudo. This is more faf to configure of course so many don't bother (which works in your favour if you do, as there is plenty of lower hanging fruit than you for attackers to spend there time on!), so it comes down to the age old compromise between security and convenience (pro tip: pick security!).


Solution 5:

Since you asked, here's my general advice on how to address the sudo issue.

Sudo was not designed to provide more security (although it can in some regard)... but rather provide a good audit trail of who's doing what on your system with what privileges.

A properly setup Sudo will not use the ALL=(ALL) ALL setting, but rather something more limited to whatever it is specifically that the user needs. For example, if you need a user to be able to login and restart a stuck service, they probably do not need the ability to install new software or shutdown your server, change firewall rules, etc.

It's sometimes common for people to use sudo to elevate themselves to the root account, ie. sudo su -. Once they do that, you stop seeing who's doing what from the root account (root can be logged into multiple times concurrently). So sometimes people want to disable the sudo su - command as well. But, for practical reasons, if you do need a fully root-privileged account for administration, at the very least having someone issue the sudo su - command would log who elevated to root and when.

How I secure my boxes:

Change the SSH port to something other than the default. This is to avoid the dumb-bots that look for port numbers then pound away until they get in (or not).

Disallow Root login over SSH using the AllowRootLogin no setting in your sshd_config. This prevents someone from brute forcing into your root account. It's just generally good practice to never allow someone to directly log in to the root/administrator account for audit reasons as well as security. If you allow root login directly, you don't know who logged in, who they got the password from, etc. But, if someone logs into Jimmy's account, then elevates their permissions to root, you have a better idea where to start your audit search (and who's account to reset).

Only allow users to SSH that require it Use the AllowUsers setting and explicity specify which accounts needs SSH access. This will, by default, block all other accounts from SSH.

Edit Sudoers via visudo and only allow the commands the user needs. There are a lot of in depth guides on how to do this, so I won't detail here. Here's a starter: http://ubuntuforums.org/showthread.php?t=1132821

The gist of this is to prevent a compromised account from jeopardizing your machine. ie. if Sally's account gets broken into, and Sally can only use sudo to restart the web server, well the attacker might have fun restarting your web server in a loop, but at least they can't rm -rf /your/webserver/directory or open all your firewall ports, etc.

Setup good firewall rules that only allow the ports that are necessary for your box to operate. Generally you want to drop everything and only allow explicitly what you need. There's plenty of decent iptables and other firewall starts online, here's one I use (it's a basic starter):

# Generated by iptables-save v1.4.7 on Mon Mar  3 17:55:02 2014
*filter
:INPUT DROP [4528:192078]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [39845:27914520]
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -m state --state NEW -j DROP
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 4254 -m state --state NEW -j ACCEPT
-A INPUT -p tcp -m tcp --dport 8080 -m state --state NEW -j ACCEPT
-A INPUT -p tcp -m tcp --dport 8443 -m state --state NEW -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 11 -j ACCEPT
-A OUTPUT -o lo -j ACCEPT
COMMIT
# Completed on Mon Mar  3 17:55:02 2014

Also a strong password is key. Even if you use SSH keys for your remote access, you should still require a password for Sudo use. This is a case where sudo could provide some more security. If someone were to steal your ssh keys, they would still be prevented from doing anything significant on your box if they have to still brute force your account password to use sudo. Passwords should not be a word, but rather a Pass Phrase. Think of a sentence, and use that. This generally will get you something more than 8 characters long, providing plenty of entropy, but also is easier to remember than some random password. Of course, good password practices say to use a machine-generated random password as to fool cracking tools like John the Ripper, which will rip right through most passphrases and passwords. No, changing E with 3 does not work, John gets those permutations as well.