Skip to content
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

init script security fixes #5850

Merged
merged 7 commits into from Feb 21, 2018
Merged

init script security fixes #5850

merged 7 commits into from Feb 21, 2018

Conversation

Crunsher
Copy link
Contributor

This assumes the parent directories for run dir (usually /var/run), log dir (usually /var/log) and cache dir (usually /var/cache) are all owned by and can only be written to by root.

Still a bit of testing to do before we can merge this. I'm also open for suggestions, the current solution is quite ugly

refs #5793

ICINGA2_ERROR_LOG=@CMAKE_INSTALL_FULL_LOCALSTATEDIR@/log/icinga2/error.log
ICINGA2_STARTUP_LOG=@CMAKE_INSTALL_FULL_LOCALSTATEDIR@/log/icinga2/startup.log
ICINGA2_LOG=@CMAKE_INSTALL_FULL_LOCALSTATEDIR@/log/icinga2/icinga2.log
ICINGA2_LOG_DIR=@CMAKE_INSTALL_FULL_LOCALSTATEDIR@/log/icinga2
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be undefined in installations where this configuration file is not overridden on upgrade. prepare-dirs should have a fallback definition if ICINGA2_LOG_DIR is not defined.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aye, will use dirname -- $ICINGA2_LOG as fallback

@Crunsher
Copy link
Contributor Author

Added a default for ICINGA2_LOG_DIR and quoted all the paths in case somebody has spaces or other wonky stuff in their config

@dnsmichi
Copy link
Contributor

I'd wait on @orlitzky 's feedback.

@dnsmichi dnsmichi added Installation needs feedback We'll only proceed once we hear from you again labels Dec 19, 2017
@orlitzky
Copy link

I'm skeptical about the invisible but important requirement that all of those parent directories are owned/writable only by root. If the user is supposed to verify that the permissions on the parent directories are correct, why not just have him verify that the permissions on the log directory are correct too? (I know that the answer is "because they don't know what they're doing," -- that's why I'm worried about leaving it up to them to set all those variables responsibly.)

And there's a typo "mdkir" in there =)

I was up all night so it might be another day before I can give more intelligent feedback.

@Crunsher
Copy link
Contributor Author

It's not only that they are supposed what they are doing when they change the default location, but that we can't guarantee security when they have a custom installation :/
Another idea I had is checking if the default is unchanged and only trying to create them in that case, yet this can just as easily be exploited.

@orlitzky
Copy link

I'm better now... in this stanza,

mkdir "$ICINGA2_RUN_DIR"/icinga2
mdkir "$ICINGA2_RUN_DIR"/icinga2/cmd
chmod 755 "$ICINGA2_RUN_DIR"/icinga2
chmod 2750 "$ICINGA2_RUN_DIR"/icinga2/cmd
chown -R $ICINGA2_USER:$ICINGA2_COMMAND_GROUP "$ICINGA2_RUN_DIR"/icinga2

the last chown doesn't need to be recursive, because you know both directories were just created. That chunk of code is a bit hairy though because you don't want to mess with icinga2/cmd unless icinga2 is still root:root. Later on there's a test -e foo || ... construct to create the log dir... would the same thing work here for consistency? I.e.

# The order of these two next two statements is important, because it's not safe to "install"
# into a directory that isn't owned by root.
test -e "$ICINGA2_RUN_DIR"/icinga2/cmd || install -m 2750 -o $ICINGA2_USER -g $ICINGA2_COMMAND_GROUP -d "$ICINGA2_RUN_DIR"/icinga2/cmd
test -e "$ICINGA2_RUN_DIR"/icinga2 || install -m 755 -o $ICINGA2_USER -g $ICINGA2_COMMAND_GROUP -d "$ICINGA2_RUN_DIR"/icinga2

But once these things are handled safely, the value of $ICINGA2_USER and $ICINGA2_COMMAND_GROUP as runtime-configurable variables is in question... if you change them, the directories (with the now-wrong owner) will already exist and will be left alone.

Unrelated: is it just me, or is one of $ICINGA2_LOG_DIR and $ICINGA2_LOG redundant?

@Crunsher Crunsher changed the title Fix prepare-dirs permission exploit init script security fixes Jan 17, 2018
@Crunsher
Copy link
Contributor Author

Sadly no, as install -m 755 -o $ICINGA2_USER -g $ICINGA2_COMMAND_GROUP -d "$ICINGA2_RUN_DIR"/icinga2 would never run since test -e "$ICINGA2_RUN_DIR"/icinga2 always returns true (the previous install creates the sub directory).

The chown has to be recursive because theoretically you could delete icinga2/cmd and make it a symlink somewhere between two chowns.

@orlitzky
Copy link

Oh, duh, good catch. You can always pass --no-deference too, to ensure that symlinks won't be followed even when not operating recursively.

It looks like I did a bad job of explaining the "su" problem with humor. There are a few different implementations, and not all of them treat -s the same (su was never part of POSIX). GNU su and OpenBSD su both treat -s as the login shell. FreeBSD su on the other hand does something totally different with -s, and Solaris doesn't have it at all.

A cross-platform "su -s" would solve a lot of these problems straight away.

As far as I know, all of them generally work the same with su <user> though. The Postgres database server uses that, for example, but the trade-off is that then your user needs to have a login shell on the machine (that may be worth it, who knows).

@Crunsher
Copy link
Contributor Author

Won't work either :( We run adduser with --system in the debian packages, ie. no login shell

@dnsmichi
Copy link
Contributor

It is quite common to modify the application user to not have a terminal, for security reasons. That's not just Debian as default, likely this affects more setups. There are community packages where we don't have control over, and cannot just break this. Imho.

@Crunsher
Copy link
Contributor Author

A short update on the current state of things:
#5793 and the CVE seem to be fixed, but for #5991 no good solution has been found. Essentially we are looking for a way to run a few commands as the, su does not work because it possibly has no shell, su -s does not work because it's not implemented that way in a few cases.

I'll make sure the CVE fix will be in the 2.8.2, even if no epiphany for #5991 strikes me before we have a release.

chown $ICINGA2_USER:$ICINGA2_GROUP $ICINGA2_PID_FILE
if [ ! -e "$ICINGA2_RUN_DIR"/icinga2 ]; then
mkdir "$ICINGA2_RUN_DIR"/icinga2
mdkir "$ICINGA2_RUN_DIR"/icinga2/cmd

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: mdkir

(it might make sense to chain these all together with && ?)

chown $ICINGA2_USER:$ICINGA2_COMMAND_GROUP $ICINGA2_LOG
# Could be undefined in installations where sysconf is not overridden on upgrade
if [ -z "$ICINGA2_LOG_DIR" ]; then
$ICINGA2_LOG_DIR=dirname -- "$ICINGA2_LOG"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll bet this should be ICINGA2_LOG_DIR=$(dirname -- "$ICINGA2_LOG")

@Crunsher
Copy link
Contributor Author

Also fixes CVE-2018-6533

@Crunsher Crunsher merged commit aea43dd into master Feb 21, 2018
@Crunsher Crunsher added this to the 2.8.2 milestone Feb 23, 2018
Crunsher added a commit that referenced this pull request Feb 23, 2018
Crunsher added a commit that referenced this pull request Feb 23, 2018
@dnsmichi dnsmichi deleted the fix/prepare-dirs-5793 branch April 18, 2018 08:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs feedback We'll only proceed once we hear from you again
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants