101

In my /etc/passwd file, I can see that the www-data user used by Apache, as well as all sorts of system users, have either /usr/sbin/nologin or /bin/false as their login shell. For example, here is a selection of lines:

daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
games:x:5:60:games:/usr/games:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
syslog:x:101:104::/home/syslog:/bin/false
whoopsie:x:109:116::/nonexistent:/bin/false
mark:x:1000:1000:mark,,,:/home/mark:/bin/bash

Consequently, if I try to swap to any of these users (which I'd sometimes like to do to check my understanding of their permissions, and which there are probably other at least halfway sane reasons for), I fail:

mark@lunchbox:~$ sudo su www-data
This account is currently not available.
mark@lunchbox:~$ sudo su syslog
mark@lunchbox:~$ 

Of course, it's not much of an inconvenience, because I can still launch a shell for them via a method like this:

mark@lunchbox:~$ sudo -u www-data /bin/bash
www-data@lunchbox:~$ 

But that just leaves me wondering what purpose is served by denying these users a login shell. Looking around the internet for an explanation, many people claim that this has something to do with security, and everybody seems to agree that it would be in some way a bad idea to change the login shells of these users. Here's a collection of quotes:

Setting the Apache user's shell to something non-interactive is generally good security practice (really all service users who don't have to log in interactively should have their shell set to something that's non-interactive).

-- https://serverfault.com/a/559315/147556

the shell for the user www-data is set to /usr/sbin/nologin, and it's set for a very good reason.

-- https://askubuntu.com/a/486661/119754

[system accounts] can be security holes, especially if they have a shell enabled:

  • Bad

    bin:x:1:1:bin:/bin:/bin/sh
    
  • Good

    bin:x:1:1:bin:/bin:/sbin/nologin
    

-- https://unix.stackexchange.com/a/78996/29001

For security reasons I created a user account with no login shell for running the Tomcat server:

# groupadd tomcat
# useradd -g tomcat -s /usr/sbin/nologin -m -d /home/tomcat tomcat

-- http://www.puschitz.com/InstallingTomcat.html

While these posts are in unanimous agreement that not giving system users real login shells is good for security, not one of them justifies this claim, and I can't find an explanation of it anywhere.

What attack are we trying to protect ourselves against by not giving these users real login shells?

1

8 Answers 8

62

If you take a look at the nologin man page you'll see the following description.

excerpt

nologin displays a message that an account is not available and exits non-zero. It is intended as a replacement shell field to deny login access to an account.

If the file /etc/nologin.txt exists, nologin displays its contents to the user instead of the default message.

The exit code returned by nologin is always 1.

So the actual intent of nologin is just so that when a user attempts to login with an account that makes use of it in the /etc/passwd is so that they're presented with a user friendly message, and that any scripts/commands that attempt to make use of this login receive the exit code of 1.

Security

With respect to security, you'll typically see either /sbin/nologin or sometimes /bin/false, among other things in that field. They both serve the same purpose, but /sbin/nologin is probably the preferred method. In any case they're limiting direct access to a shell as this particular user account.

Why is this considered valuable with respect to security?

The "why" is hard to fully describe, but the value in limiting a user's account in this manner, is that it thwarts direct access via the login application when you attempt to gain access using said user account.

Using either nologin or /bin/false accomplishes this. Limiting your system's attack surface is a common technique in the security world, whether disabling services on specific ports, or limiting the nature of the logins on one's systems.

Still there are other rationalizations for using nologin. For example, scp will no longer work with a user account that does not designate an actual shell, as described in this ServerFault Q&A titled: What is the difference between /sbin/nologin and /bin/false?.

3
  • 1
    They both serve the same purpose, but /sbin/nologin is probably the preferred method. From a security standpoint, `/sbin/nologin`` isn't the preferred method; it wastes time and cycles providing a response. Although neither provide particularly good security; they're defense-in-depth measures, but they don't actually stop someone from running a command as a given user. Jul 29, 2015 at 16:13
  • 10
    @ParthianShot the time and cycles needed to echo a single hardcoded string, relative to whatever work the OS is doing anyway in order to look up what shell to execute for the user, seem unlikely to be of crucial importance to anyone constructing a denial of service attack. slm is suggesting nologin is the preferred method for UX reasons, not security ones - doing sudo su someuser and just having nothing happen because their login shell is false is confusing. Also, both of these do prevent someone from running a command as a given user in some circumstances, described in answers here.
    – Mark Amery
    Oct 27, 2015 at 12:34
  • @ParthianShot: It does prevent regular users from running commands as another user: your sudo -u www-data example implies sudo rights not available to everyone. It also prevents SSH shell access, as ssh [email protected] /bin/bash will (try to) run bash in that user's shell, so if that's set to nologin or false the bash attempt will fail.
    – MestreLion
    Jun 11 at 11:06
33

Definitely it serves a security purpose. For example, look at the below bug filed for a system user who had a shell.

My debian server was compromised due to the daemon account having a valid login shell and having samba open for internet access. The break in was made by setting a password remotly via samba for the daemon account and the logging in through ssh. Some local root exploit was then used to OWN my server.

I would recommend you to read this wonderful answer by Gilles where he has provided links to some of the bugs as well.

There are bugs filed over this issue in Debian (274229, 330882, 581899), currently open and classified as “wishlist”. I tend to agree that these are bugs and system users should have /bin/false as their shell unless it appears necessary to do otherwise.

3
  • ...I don't see how that actually depends specifically on the declared shell for the user. If the attacker only ran ssh user@site, and that worked, they wouldn't continue to trying ssh user@site /bin/bash, but I'm pretty sure that'd still work regardless of declared shell. Jul 29, 2015 at 16:14
  • 3
    @ParthianShot, anecdotal evidence: on my CentOS server, when an account's shell is set to /sbin/nologin ssh user@site /bin/bash returns a simple This account is currently not available. message. Also, this answer says nologin protects SSH access
    – metavida
    Oct 19, 2015 at 18:19
  • 1
    @ParthianShot based on the description, that's not what's happened. What's happened is: Samba was misconfigured; the attacker configured ssh access via Samba; the attacker logged on via ssh. Although this case is obviously the sysadmin's fault, if you replace "misconfigured Samba" with "exploitable service", then preventing login access makes sense, as it reduces the surface of attack. of course, if the exploit grants local execution, having ssh access rather than not, makes little difference.
    – Marcus
    Aug 3, 2019 at 10:29
19

To add to the excellent answers of @slm and @ramesh:

Yes, as you have pointed out, you can still switch to users with nologin as their default shell by running sudo with a shell defined, but in this case, you have had to:

  1. Log in as another user that has a valid shell
  2. Have sudo permissions configured for that user to run the su command, and
  3. Had your su attempt logged to the sudoers log (assuming of course that sudo logging is enabled).

The users that have nologin defined as their default shell often have higher privileges/are able to do more damage to the system than a regular user, so having them unable to log in directly attempts to limit the damage that a breach of your system could suffer.

10

Next to the great answers already given, I can think of the following scenario.

A security bug in a service running as a restricted user allows to write a file as that user. This file can be ~/.ssh/authorized_keys.

This allows the attacker to login directly in a shell which would make it much easier to execute a privilege escalation.

Disallowing a login shell would make this option a lot more difficult.

7

In addition to the excellent answers that have been given, it serves another purpose.

If you run an FTP daemon on your server, it checks the login shell of users that attempt to login. If the shell isn't listed in /etc/shells, it doesn't allow them to login. So giving daemon accounts a special shell prevents someone from modifying the account via FTP.

6

Yes, it serves a security purpose. It's a defence-in-depth measure.

The core reason it serves a purpose is that there are various bits of software that will validate some form of login credentials for a specified user and then use that user's login shell to run a command. Perhaps the most notable example is SSH. If you successfully authenticate as a user over SSH, SSH then launches the user's login shell (or uses it to run the command you provide, if you use the ssh [email protected] 'command to run' syntax).

Of course, ideally an attacker won't be able to authenticate as a user at all. But suppose the following situation happens:

  • A server you control is running a web service as a user that has a home directory and a login shell
  • An attacker discovers a vulnerability in that service that allows the attacker to write files to the user's home directory

Now your attacker can write an SSH public key to ~/.ssh/authorized_keys, then SSH in, and - boom! - they've got shell access to your server.

If the user instead has /usr/sbin/nologin as their login shell, then even after the attacker successfully writes the public key to authorized_keys, it's not useful to them. All it allows them to do is remotely run nologin, which isn't very useful. They can't get shell, and their attack has been mitigated.

In case this scenario seems very hypothetical, I'd like to note that I was targeted by precisely this attack at some point in 2015, around a year after I asked this question. Like a goddamned idiot, I'd left a Redis instance with no password open to the world. It got targeted by the Redis crackit attack, in which the attacker inserts an SSH public key into your Redis database, then sends a command telling Redis to write the contents of the database to .ssh/authorized_keys, then tries to SSH in. I was saved from the consequences of my own incompetence only by the fact that the maintainers of the redis-server Apt package (which I'd used to install Redis) had the wisdom to make it run Redis as a redis user who has no home directory or login shell; had it not been for them, my server would likely have been ransomwared or ended up part of some hacker's botnet.

That experience gave me some degree of humility and made me appreciate the importance of defence in depth, and, in particular, of not granting login shells to accounts that run webservers, databases, and other background services.

2

Generally I would say /bin/false and /sbin/nologin are the same - but I suppose it depends on which SSH server you are using.

It would be prudent for me to point out this recent exploit on OpenSSH appears to affect /bin/false logins but NOT /sbin/nologin. However it states that Dropbear is different in this manner (also the exploit specifically applies to OpenSSH).

Exploit affects most versions:

7.2p1 and lower (all versions; dating back ~20 years) With X11 forwarding enabled

https://www.exploit-db.com/exploits/39569/

So based on this - I personally would do /sbin/nologin however I'm not sure if this might affect services which create the /bin/false entry in /etc/passwd. You can experiment and see your results, but please do so at your own risk! I suppose worst case you can just change it back and restart any affect service(s). I personally have quite a few entries using /bin/false - Not sure if I want to bother with this as X11 forwarding is not something I have enabled ;)

If you use OpenSSH (many folks do I think...) AND have X11 forwarding enabled - you may wish to consider /sbin/nologin (or maybe switch to Dropbear).

0

It is generally good security practice to set service and application accounts to non interactive login. An authorized user may still have access to those accounts using SU or SUDO but all their actions are tracked in the Sudoers log files and can be traced back to the user who executed commands under service account privileges. This is why it is important to store log files in a centralized log management system so that system administrators do no have access to change log files. The user executing commands under SU or SUDO is already authorized to access the system.

On the other hand an external or unauthorized user to the system will completely have no access to login using those accounts and that's a security measure.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .