New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
systemd can't handle the process previlege that belongs to user name startswith number, such as 0day #6237
Comments
Yes, as you found out "0day" is not a valid username. I wonder which tool permitted you to create it in the first place. Note that not permitting numeric first characters is done on purpose: to avoid ambiguities between numeric UID and textual user names. systemd will validate all configuration data you drop at it, making it hard to generate invalid configuration. Hence, yes, it's a feature that we don't permit invalid user names, and I'd consider it a limitation of xinetd that it doesn't refuse an invalid username. So, yeah, I don't think there's anything to fix in systemd here. I understand this is annoying, but still: the username is clearly not valid. I hope that makes sense? |
Yeah, thanks. |
Wouldn't it make sense to refuse User=0day then? In fact, wouldn't it even make sense to refuse User=0x200 or User=01000 rather than User=512 (in other words, to only allow decimal canonical user IDs) for the same reason? BTW: where does xinetd come in here? |
It appears that el7 patches shadow-utils-4.1.5.1/libmisc/chkname.c so that it does allow that kind of usernames, explicitly removing the restrictions: https://gist.github.com/bloerwald/a482791395114fa82636e2ab207cdb11 While it does indeed seem to be a not-a-bug in systemd, one may want to make someone maintaining that el7 patch aware of that the combination of systemd and that patch does pose an issue. A patch refusing any |
useradd doesn't complain: screenshot |
Does the POSIX standard deny leading numbers for user names on *nix? |
Tested on Debian with
|
Let's look if it's actually invalid... Probably not because:
http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_276
So in my humble opinion, it's a valid name and thus systemd has a bug here. Even if you assume leading numbers are not allowed, systemd running the unit under root is a bug too. It should refuse to run the unit, in particular in the light of:
This is clearly not the case, So either way, there is a bug here. |
hm yes I'll look into it |
I think people are getting distracted with whether or not 0day is a valid name or not. The real problem here is that the unit is run as root, despite "0day" not describing the root user, isn't it? Can a systemd developer tell: Will a patch that gives an error in this case be accepted? I can get started on it if so. |
@rain-1 there's 2 bugs - one is that it is still running as root and the other is that it doesn't support usernames starting with numbers. |
I see! please make a separate issue to track the second bug (usernames starting with numbers). |
Actually, fix the incorrect user name handling thereby fixing the run-as-root issue too. And we kinda made an issue about that already, namely THIS one. |
This is a severe security issue that should be fixed, and assigned a CVE, and not not-a-bug. |
@julian-klode you might have misunderstood this bug, it cannot be used for priv. esc. |
@rain-1 If the process starts, and you expect it to start a user and not as root, then that is a security issue, because your service suddenly runs as root (and you might not notice it until it is too late). |
So many bugs and issues, and all the time the poettering ignorance... I just cannot stand it... It does not matter if its free, if you carry such things with it. Sadly the only way leaving it is using devuan... |
Seems the stuff is parsed using:
Meaning indeed, Edit: See other comments following up on this probably not being the case after all. |
@RealDolos My systemd v232 says:
|
If a user name is indeed allowed to be made up of digits alone, there has to be a way to distinguish it from a UID. I propose to specify the information in the same way GNU coreutiles does, by appending a + whenever a UID is meant, and otherwise try to resolve to a username first. See also: https://www.gnu.org/software/coreutils/manual/coreutils.html#Disambiguating-names-and-IDs |
@UgnilJoZ do you actually have a user with uid 7? |
@RealDolos Yes, I just created one for testing ;) |
@RealDolos safe_atou checks that it is a valid number, and not a number with something at the end, so the warning here makes sense. But then the bug report is incomplete, because systemd does at least warn about it. I'm not sure it makes sense to start a service if the specified user is invalid, though. |
That one is easy, in my humble opinion: Same as systemd should not pick and run some random binary when the specified ExecStart is invalid, it shouldn't run a service under a random uid if it cannot find the specified user (uid 0 being the random uid fairly picked by the Debian PRNG, of course) PS: Sorry, @julian-klode, only saw just now that you're actually a Debian dev. My Debian PRNG quip wasn't meant to personally target you. |
In Line 136 in dd83526
|
The line which does the hard-coded fallback to root is here: systemd/src/shared/condition.c Line 172 in defdbbb
|
@red-hood That's not even remotely true - the code is for ConditionUser, and the line mentioned says that if the user could not be parsed (< 0) that the condition is not met (return 0 => false) - and chasing it down step by step in issue comments is not helping anyone. |
The 7oz test was perfect. Clearly the issue is not missing validation - in
fact, the safe_atou function does exactly what it should (but it's odd that
some of the functions in the family skip leading whitespace and some don't)
and rejects strings with appended characters. It handles integer overflows
incorrectly though (signed integer overflows, as in safe_atoi, are
undefined behavior), but that's not relevant in this ticket.
The real bug is that invalid User= directives are skipped rather than
rejecting the whole unit. That's actually a lot worse, as it means that a
typo in a username leads to stuff running as root.
Part of this behavior is actually documented in systemd.unit(5):
"Unit files may contain additional options on top of those listed here. If
systemd encounters an unknown option, it will write a warning log message
but continue loading the unit."
What I can't find documented is that options with invalid values are
"loudly ignored" too.
Nevertheless, this is indeed a security issue, albeit probably not worth a
CVE. When I can get an admin to install my unit file, I can try to misspell
my user name (e.g. using Unicode characters that look like Latin letters
but actually are Greek or Cyrillic glyphs) - or, for that matter, the name
of the User directive itself - to trick the admin into believing the unit
runs as my user or a role account I "own", while it'll actually run as
root. That pathologic user names like here can also trigger this issue is
actually harmless in comparison.
Now how can this broader issue be fixed? Hard. Very hard. Making a valid
User= directive mandatory would be a good start - but this is horribly
backwards incompatible and would at the very least need a long-term plan to
get everyone to migrate their unit files. Revisiting the decision to loudly
ignore invalid directives could work - but I can already imagine how much
that would break (and it'd mean that a software maintainer who ships unit
files with their software can't attempt to use newly added directives, even
if the software could run without them too).
What about at the very least rejecting unit files that contain non-ASCII
characters in option names, or User= option values? Then an attacker at
least needs a "visible" misspelling. Combining that with also causing a
failed User= directive to make the whole unit file rejected would solve the
security issue entirely.
As for the allowed character set in user names - that's a different story.
Once units with invalid names are properly rejected (instead of falling
back to root), I suppose systemd can enforce any policy it wants there and
distributions can override it if they really need to.
|
Maybe a systemd config option that turns such warning cases into errors? Or like, a config file that enumerates the kinds of errors that should be fatal instead of warnings? |
Sigh, since this now attracting the trolls, I'm locking the conversation. |
Just to summarize things:
|
Agreed about 1 and 2, but I disagree about 3. Setting I agree that not handling user names that start with digits can be considered "not a bug". |
That's exactly what happens, and what I wrote above: if the username is valid but the user doesn't exist we'll let the unit fail on start. If the username is already invalid syntax-wise we'll log about it but proceed. Hence, if you write:
Then we'll ignore the assignment altogether (but log about it), since it's syntactically invalid. But if you specify:
and the user "waldo" does not exist (though it is syntactically valid), then we'll accept the setting, but as soon as you actually try to start the unit it will fail with "user not found". |
Thanks @poettering for the clarification! |
User @roland found that usernames that contain unicode characters also cause this bug.
|
@haraldh we stick to the portable set, that the majority of distros agrees on, and umlauts in user names don't work on fedora, nor arch... I am pretty sure it works on a small minority of distros only. here's the output i get on fedora:
Note that fedora/rhel explicitly patch our the upstream rules of shadow-utils: https://src.fedoraproject.org/cgit/rpms/shadow-utils.git/tree/shadow-4.1.5.1-goodname.patch#n7 Note that neither the upstream nor the fedora rules actually accept umlauts in usernames. Anyway, systemd is not a tool for generic user management, it's a tool for service management. We make restrictions on the username you may make use of to keep things safe and portable between distributions, hence we stick to the set of user names that are portable, and complain about all others. I am happy with changing our rules, but before we do that, please work with the POSIX, shadow-utils, libuser communities, as well with the other Linux distributions to come up with a single unified set of rules, and then we are happy to adopt that too in systemd. But until then, I think it's better for systemd to stick to the rules that only permit names that are portable to all of these systems. After all systemd not only consumes these names, it also potentially creates them (via sysusers.d or when DynamicUser=1 is used), and we should make sure systemd cannot beused as a vehicle for creating users that are otherwise not allowed. Also: don't forget we don't break people's stuff with this, User=/Group= knew no counterpart in sysvinit, because priv dropping had to be implemented by the daemons manually there. If you do decide to let systemd do the priv dropping for you, we politely ask you to use portable names, so that the unit files work everywhere. And the rules we enforce are neither crazy nor random, they are the common core every distro accepts. |
If an error is encountered in any of the Exec* lines, WorkingDirectory, SELinuxContext, ApparmorProfile, SmackProcessLabel, Service (in .socket units), User, or Group, refuse to load the unit. If the config stanza has support, ignore the failure if '-' is present. For those configuration directives, even if we started the unit, it's pretty likely that it'll do something unexpected (like write files in a wrong place, or with a wrong context, or run with wrong permissions, etc). It seems better to refuse to start the unit and have the admin clean up the configuration without giving the service a chance to mess up stuff. Note that all "security" options that restrict what the unit can do (Capabilities, AmbientCapabilities, Restrict*, SystemCallFilter, Limit*, PrivateDevices, Protect*, etc) are _not_ treated like this. Such options are only supplementary, and are not always available depending on the architecture and compilation options, so unit authors have to make sure that the service runs correctly without them anyway. Fixes systemd#6237, systemd#6277.
Submission type
systemd version the issue has been seen with
Used distribution
In case of bug report: Expected behaviour you didn't see
In case of bug report: Unexpected behaviour you saw
In case of bug report: Steps to reproduce the problem
linux user's name :
0day
conf file:
socat.service
and then use
systemctl start socat.service
to start process, but the previlege is rootP.S.
I searched google and found that it was not right to named a linux user with
0day
, it should satisfy"^[a-z][-a-z0-9]*\$
, but when I usexinted
to start the service, it can handle the previlege rightly with linux user0day
The text was updated successfully, but these errors were encountered: