[systemd-devel] Github systemd issue 6237

Michael Chapman mike at very.puzzling.org
Mon Jul 10 11:15:31 UTC 2017


On Mon, 10 Jul 2017, Lennart Poettering wrote:
> On Thu, 06.07.17 09:36, Michael Chapman (mike at very.puzzling.org) wrote:
>
>> User=0day fails a syntactic validation, not a semantic validation. systemd
>> never even checks to see whether the user exists when the unit is loaded.
>> And nor should it! The user must be allowed to not exist at unit-load time.
>>
>> Contrary to some of the comments in this thread, there is no point in
>> systemd's operation where it goes "oh look, that user actually exists but
>> I'm going to pretend it doesn't".
>
> Well, that's where we disagree: POSIX allows you to create a user
> named "1000" that maps to a UID "1001". I find it very hard to swallow
> that people actually defend that as a good concept, and claim that
> systemd was negatively impacting security here by refusing this and
> other ambiguous mappings.

I do think that User=1000 should always be treated as a UID, regardless of 
whether there's a "1000" username on the system or not.

> We need to validate the input we get, that's security 101. And POSIX
> is *not* a good standard to strictly follow here and use for
> validating user names, because it's *very* underdefined:
>
> - It permits fully numeric names
> - It makes no size restrictions (strictly reading the spec even permits
>  zero-length usernames!)
> - It permits dots, which is conflicting with traditional chown syntax
> - It permits dots at the beginning of usernames (which is dangerous
>  security-wise as this permits users to hide home directories)
> - It permits naming users "-", which is often used as special "does
>  not apply" like value
>
> Now, because this is so weakly defined, we hence do not follow POSIX
> rules, but filter out more that might be dangerous. Specifically:
>
> 1. We do not permit empty usernames
> 2. We don't permit the first character to be numeric
>   (This also filters out fully numeric user names)
> 3. We do not permit dots in usernames, neither at the beginning nor in
>   the middle.
> 4. We do not permit "-" at the beginning of usernames (something which
>   POSIX explicitly suggests, btw)
> 5. We require that the user name fits in the utmp user name field, so
>   that we can always log properly about it.

I think 1, 4 and 5 are good things.

For 2 and 3, however, I'm not so sure.

> Note that this isn't even as strict as other systems go. For example,
> we do permit uppercase characters, and we do permit underscores.
>
> Are these random rules we came up here? Nope. This actually matches
> the various requirements enforced by the regex strings used by various
> distros in one way or another. Moreover, if you type "valid linux user
> name characters" into google, among the top links you'll find stuff
> like this:
>
> https://stackoverflow.com/questions/6949667/what-are-the-real-rules-for-linux-usernames-on-centos-6-and-rhel-6
>
> or this:
>
> https://unix.stackexchange.com/questions/157426/what-is-the-regex-to-validate-linux-users
>
> Which generally suggest similar rules.
>
> Now, I do think that systemd has the duty to complain about any system
> user names outside of the safe range. Not only for security reasons,
> but also for portability and compatibility reasons: I think we should
> ensure that unit files remain portable, and hence we should try to
> filter out early stuff that's unlikely going to work outside of the
> local scope.

I'm curious as to what you consider portability and compatibility here.

There are some "obviously bad" usernames, like the empty string. We should 
definitely prevent these from being used, and I do hope we can get systemd 
to complain noisily should somebody try to use them.

But there are less obviously bad usernames, because -- as you point out -- 
they're _actually in use already_. I myself already have systems with 
usernames that begin with a digit; I don't want those systems to suddenly 
break just because I update the Linux release to something that runs 
systemd. (In practice they probably won't break, since I'm unlikely to 
write system units for these users. But the principle of the matter 
stands.)

For these "less obviously bad" usernames, I think we should just rely on 
getpwnam() doing its own validation -- that is, in systemd's child process 
when it's spawning commands. After all, getpwnam() may have any kinds of 
restrictions due to the system's NSS config... or it may not. We're not in 
any place to second-guess what its limitations are.

So long as _we_ never treat a User= value incorrectly (which we don't, we 
decide whether a it's a UID, a username, or an invalid value very early 
on) everything should just work fine.

Obviously we should be encouraging software vendors and distributors to 
use nice usernames. The portability and compatibility comes from them. But 
if a sysadmin wants to run one of their own services as User=0day I don't 
think we should be getting in the way of that -- they should know what the 
portability issues are with that, if any.

> We should also not pretend all was good if other tools make less
> careful restrictions and permit usernames that cause ambiguities. Yes,
> a lot of software is very sloppy with validating input, and yes, some
> adduser/useradd implementations allow you to create a user called
> "1000", but I am very sure that their sloppiness should not leak into
> our codebase.
>
> Also, do note that system users are different concepts than regular
> users: system users are concepts required for system services which
> are usually put together by developers, packagers and administrators
> who hopefully understand these issues to some point and pick good
> names instead.
>
> And of course, note that systemd is open source. if you don't like the
> restrictions we make, you can patch them out (or even use some other
> project). But again, I think it's our duty to help build a more secure
> ecosystem (and we do that by validating our input, by running systemd
> services in sandboxes and so on), and hence these restrictions really
> need to stay.

Sorry, but I really can't see how forbidding usernames like "joe.hacker" 
or "0day" improves security. As you said, they're perfectly valid 
usernames. All of the libc functions that deal with usernames already 
handle them correctly.

systemd is in the lucky position that it has so few dependencies. For 
instance, we don't have to worry that the chown utility may misinterpret 
"joe.hacker", since systemd never invokes the chown utility. It's not one 
of systemd's dependencies.

> (I do accept though that it's a valid discussion whether systemd's
> current behaviour of warning and skipping invalid User= rvalues is the
> best choice, instead of erroring out completely.)
>
> Lennart


More information about the systemd-devel mailing list