Sudo Policy Fixes and Fails – The Cmnd Alias

So we’ve covered the User_Alias, Host_Alias, and Runas_Alias labels up to this point.  Today, we’re going to cover the Cmnd_Alias label.  This one takes a comma separated list of commands that the policy will allow.  It can contain defaults overrides, TAGs, command flags, and command arguments.  It can use special keywords in place of commands.  It is the most complex label in the policy, and it is critical to get this “right” if you don’t want to accidentally grant more privilege than you intended.

Most of our examples (after we go over the Defaults in detail) will be identifying problem policies, and most of those problems will relate to this label.

To define the label as an alias, we use the Cmnd_Alias entry like so:

Cmnd_Alias C_DOSTUFF = /usr/bin/stuff

This would grant policy to call the command “/usr/bin/stuff” (or just “stuff” if /usr/bin is in the PATH environment variable,) without restricting the flags or arguments that can be passed to it.  If we want to force it to never allow any arguments, we can change the policy like this:

Cmnd_Alias C_DOSTUFF = /usr/bin/stuff ""

This tells the policy to make the argument list “empty,” which means “no arguments are allowed.”   We can similarly restrict the flags that may be passed.

Cmnd_Alias C_DOSTUFF = /usr/bin/stuff [!-]* ""

This is the place where it is important to remember that “whitelisting” is the way to go.  Trying to “blacklist” often leads to heartache and pain killers.  The biggest example of a failed “blacklist” mentality is this:

Cmnd_Alias SHELLS = /bin/bash, /usr/bin/ksh, /bin/zsh
Cmnd_Alias SU = /bin/su
Cmnd_Alias C_BABYADMIN=ALL, !SU, !SHELLS

This is even mentioned in the man page, and yet, it is seen in the wild all too often.  This command appears to say “the user can run any command except the listed shells or su.”  However, by being able to run any command, the user is able to make a copy of any of the shells under a different name, and then use sudo to execute them.  This does not work the way people seem to think it does.  Even the man page has a “valid” entry that is dangerous.  The “valid” example it provides is this:

jill SERVERS = /usr/bin/, !SU, !SHELLS

On the surface, it looks like “jill” can execute anything within “/usr/bin” except the SU and SHELLS commands.  Since “cp” and “mv” and the like are in “/bin” but not “/usr/bin” on many systems, this looks like it might work, right?  Here’s the problem.  The “at” command often resides in “/usr/bin” so something as simple as this could be used to also bypass this problem:

echo "cp -p /bin/bash /usr/bin/myshell" | sudo at now

This is why it is always better to whitelist as much as possible, not give any kind of “blanket” policy with dumbed down “blacklist-like” restrictions.  My preference when dealing with Cmnd_Alias issues is to have the user write a script, (or write one for them) that handles the exact command that will need privileged access, then make that be owned by root and not writable by anyone.  Grant sudo policy to that script, instead.  You can control what flags are always passed, what arguments are always passed, and so on, if you do it this way.

We won’t look at the “Defaults” overrides this week, since we’re going to being covering Defaults next week, but we will look at the TAGs again.

So the defined TAGs are listed below.  The log related ones will be covered when we go over the Defaults, but I’ll list them, anyway.

PASSWD: | NOPASSWD:  -  Force a user to authenticate, or don't force authentication for this command.
EXEC: | NOEXEC:  -  Allow or attempt to prevent the command from forking a child process.
SETENV: | NOSETENV:  -  Override the value of the "setenv" Default on a per-command basis.
LOG_INPUT: | NOLOG_INPUT:  -  Override the value of the "log_input" Default on a per-command basis.
LOG_OUTPUT: | NOLOG_OUTPUT:  -  Override the value of the "log_output" Default on a per-command basis.

Remember that the “NOEXEC:” TAG only works if the binary was compiled as a shared object binary.  Statically compiled programs (such as “ed”) will not be blocked by this hooking mechanism.  This is why the special “sudoedit” command entry is recommended for any kind of file editing situation.  We covered this here.

I know this was a lot, but it’s not nearly enough.  We’ll go into more detail as we rip apart “bad sudo” policy examples later on.  Before we get to that, though, we need to look at the Defaults, and we’ll begin that next week.

Leave a Reply

Your email address will not be published. Required fields are marked *