None of the systems I administer or supervise have sudo installed with the
SUID bit set.

Every time I answer a question on how to do privileged work on these systems
(i.e. do tasks that require administrator privileges) with a proposal to SSH
under the privileged account directly to do such a work, whoever asked the
question starts to blabber how insecure that is, that one should use sudo,
and that nobody should ever login directly as root.

I have spent quite some time explaining the misconception behind so-called
“secure way to access systems through sudo”, so I decided to write up an
article that describes the issues of using that approach and why using sudo
is actually less secure than a direct SSH access.

History

The following is based on my personal recollection of the history around early
90’s with some references to documents I could quickly find. Unfortunately, this
is one of the topics that is not so easy to reconstruct in full detail.
Although there may be minor inaccuracies, the outlined view on the history
should be very close to the true events that took place.

Many years ago (but not that far in the past) system administrators were using
telnet and rsh to access and administer their servers. Networks were
simpler and traffic sniffing techniques were common. Therefore, it was very
easy to eavesdrop on a root account login and to automate the task of gathering
the credentials. To mitigate the issue to some extent the following approach
was proposed:

login as a non-privileged account first;

do some stuff;

if you need privileged account access (e.g. root) switch to it using su.

The idea behind this proposal was that such a sequence makes it harder for a
traffic listener to catch root’s credentials on the wire due to the login
sequence mixed in to the stream of other activities the systems administrator
was doing before escalating their account to the privileged user.

At approximately the same time discussions started in regard to the dangers
of working as root, that people were tending to work as root for prolonged
periods of time performing tasks that did not require escalated privileges
without proper justification for that behaviour. As the result of these
discussions the sudo utility was born. The utility allowed to bind root
privileges to a restricted set of commands and maintained access controls
through its configuration file in order to allow or deny access to the defined
functionality to specific users/groups. This allowed systems administrators to
delegate some of the privileged routines to less privileged user/groups. (See
more on the history of sudo if you are interested).

Somewhere in early 90’s the two approaches were merged, so the approach became:

login as a non-privileged account and do your every day tasks;

once a privileged operation is required execute it through sudo.

Although it seems like a minor optimisation, in fact, this introduced a major
security issue: previously, the attacker should have needed to listen for
traffic in attempt to figure out when the victim is executing su and is
providing root’s password, but now they did not need to do anything except of
capturing user’s password at the beginning of the session (the same problem the
“su-after-normal-login” approach was trying to solve just reappeared :) ) since
once you know user’s password you can use sudo which authenticates you with
user’s password!

In 1995, Tatu Ylönen as a response to the issues related to exchanging the
credentials over non-protected, easily sniffable networks released his first
implementation of the SSH protocol as freeware to the public. Over the next
five years SSH was adopted worldwide and it eventually replaced
telnet/rlogin/rsh for the remote access and management activities in most
places around the globe.

However, due to inertia the recommended approach of logging in as a
non-privileged account and escalating privileges later somehow survived, is
still followed, and often people don’t even try to analyse and see the flaws of
the approach.

People are saying “sudo” is good. Is it true?

(or looking critically into some common misconceptions re: “sudo”)

So let’s look at the most commonly used “pros” in favour of using sudo. For
example, Ubuntu’s community help page provides a nice, aggregated list of
benefits provided by sudo usage in their default installation. Let’s walk
through all of them and see if they are real benefits at all:

The installer has fewer questions to ask.

This is a very questionable “benefit” to the end user since it implies
that the system would do more stuff with escalated privileges behind the
scenes without the user even knowing it. From the security standpoint it
just silently expands the attack surface.

Users don’t have to remember an extra password for occasional use (i.e.
the root password). If they did, they’d be likely to forget it (or record
it unsafely, allowing anyone to easily crack into their system).

This is another hard to comprehend “benefit”. Given that we now have SSH
and the recommended best practice is to use SSH keys instead of passwords,
sudo requires users to memorise yet another password.

Moreover, the argument in regard to users’ likely behaviour is purely
speculative and assumptive — to the same extent we can assume that
password policies make it hard for users to memorise their passwords and
they would be likely to forget the password (or record it unsafely, …).

The truth is, the key based authentication solves the issue of the
requirement to have multiple passwords for multiple accounts.

There is one place, however, where the discussed “benefit” is actually
applicable — local console access (no key authentication there, usually),
but even there the best practice would be to login directly as root on
the virtual console if there is such a need (the reason for that is
quite complicated and in short could be described as the following: there
are multiple checks and assumptions in the kernel code and the
accompanying C library on allocating a terminal, spawning a process, etc.
for root over the same actions performed for a non-privileged user).

It avoids the “I can do anything” interactive login by default. You will
be prompted for a password before major changes can happen, which should
make you think about the consequences of what you are doing.

This statement also assumes that for some reason people would prefer to
always login as root and do all of their work under that account.

In reality users are so used to prefix almost any failed command with
sudo that this “benefit” can be considered as the quite opposite item,
against sudo.

On a properly configured environment you explicitly need to login as the
privileged account to do functions that require privileges.

sudo adds a log entry of the command(s) run (in /var/log/auth.log). If you
mess up, you can go back and see what commands were run.

This statement is also somewhat true, but it does not defend the sudo
usage. A proper auditing subsystem is what keeps audit logs no matter how
activity was performed. Logging of executed commands for user’s history
reasons is the job for the shell.

The ability of logging is so limited in sudo that it cannot be used for
anything except a substitute for the shell history. Just imagine the
following scenario — a user executes:

sudo less /var/log/messages

and then types “!” followed by the Enter/Return key — the user effectively
now in the root shell and what sudo will log into its logs has nothing
to do with what user actually did.

Instead of relying on sudo‘s logging abilities, one should configure
auditd and send events to a centralised log aggregator to get audit logs
that can be trusted.

On a server, every cracker trying to brute-force their way in will know it
has an account named root and will try that first. What they don’t know is
what the usernames of your other users are. Since the root account
password is locked, this attack becomes essentially meaningless, since
there is no password to crack or guess in the first place.

This is such a weak attempt to bring host security into the play that it
is hard to comment on it without dropping a tear :).

First, use SSH keys and disable the password authentication on the server
— this (and not some security through obscurity) will defend the system
from the brute force attacks.

Second, protect your remote access entry points with properly configured
firewall and allow remote access from a defined list of locations only
(i.e. whitelist authorised locations) — this will shrink the possible
attack surface of the SSH service considerably.

Allows easy transfer for admin rights by adding and removing users from
groups. When you use a single root password, the only way to de-authorize
users is to change the root password.

This is an interesting one: half of the statement is true, another is
misleading.

The true part is that you can easily delegate privileged operations using
sudo. All in all, it was the primary goal and requirement of the tool
creation to provide access delegation.

The misleading part is that the alternative is to use a single root
account/password. The truth is that nobody is limited by a single root
account: you can create as many as you want and each of them could have
their own distinct password, e.g.

[root@localhost ~]# useradd -om -o 0 -g 0 -s /bin/sh new_root

[root@localhost ~]# passwd new_root

Better yet, do not set the password and lock the account instead with
usermod -L new_root since we are using keys, remember?

This approach also provides additional accountability since users will
have separate shell histories, their login attempts will be clearly logged
under separate names, etc.

sudo can be setup with a much more fine-grained security policy.

Another half-truth in the list of “benefits”. The statement is incomplete
and lacks the part it is comparing the functionality to. If we are
comparing a legacy Unix access control system with sudo, then yes sudo
is much more configurable. If we compare sudo with, say, SELinux or
GRsecurity’s RBAC – sudo will lose since both have much more
fine-grained security controls than sudo.

The root account password does not need to be shared with everybody who
needs to perform some type of administrative task(s) on the system (see
the previous bullet).

As with item #6 this statement assumes for some obscure reason that there
can be just a single root account in the system. Therefore, the result of
such a logical exercise is also questionable since it is based on a wrong
assumption.

The authentication automatically expires after a short time (which can be
set to as little as desired or 0); so if you walk away from the terminal
after running commands as root using sudo, you will not be leaving a root
terminal open indefinitely.

This statement also compares sudo with something reader cannot compare
to. Moreover, it mixes up two logically unrelated things: the credentials
expiration and terminal security. While it is great that sudo implements
the former, the latter is usually addressed by entirely different means:
starting with auto-logout functionality, lock screen, physical security,
etc.

Well, we can continue to critically assess other common statements in regard to
sudo made mostly by people who do not have any strong Information Security
background, but it would be a waste of time for the readers.

You can always raise a question regarding some particular claim and/or
assumption related to sudo and if it is interesting I would add it (and the
corresponding response) to this article.

What is the problem with the “sudo” approach?

Well, there are several in fact. The most pressing issue is that the usage of
sudo (or su, or any other utility that has its SUID bit set) is crossing
the security boundary from the less privileged account to the more privileged
account. This opens doors (or widens the attack surface) to privilege
escalation techniques. In plain English it makes the non-privileged account to
be essentially equal to the privileged one, let me explain by a fairly simple
example:

imagine if you are a developer and you work on a server under your
non-privileged account;

as a part of your daily routine you need to download some third party
package and install it (we are going to leave out all the security
complexities involved with such an activity like verifying signatures,
using a separate instance to prepare a package for deployment, etc.);

the installation of the package usually requires executing some third
party code under your non-privileged account. This code was not written by
you and there is a high chance that you did not read/verify the foreign
code line by line in order to ensure that it does not do anything
malicious since this would be quite time consuming, would require a lot of
effort, and your team has more important priorities than this (remember,
this is an example based on situations you would encounter in the real
world, which is by no means perfect);

it happens, that that particular third party was compromised and some
malicious code has been injected into the package installation routines;

after the execution of the installation routine (and the malicious code
for that matter) your ~/.bashrc (for example) is modified in such a way
that each time you login it starts up a key logger or some other kind of
remotely controllable piece of software that talks back to its master;

So far we just got an issue localised to this non-privileged account only (with
a possibility to spread across the entire fleet of servers that non-privileged
account has access to in case of the NFS mounted home directories). Is this
bad? Yes, it is since it may disrupt this particular project, steal reachable
sensitive information, could be used as a trampoline to jump start further
research and exploitation of other vulnerable resources. Is it critically bad?
Not necessarily. If the systems are built properly with host-based security in
mind, if the proper privilege separation techniques are used throughput the
company infrastructure, etc. the impact is localised and with proper monitoring
systems it would be detected eventually and investigated (keep in mind that it
is really hard for a non-privileged account to hide their activities from more
privileged processes).

Now, let’s add sudo to the mix, e.g. suddenly the developer decided to
install an additional library package into the system. So, what would happen
next? You guessed it: the developer would need to type in their password to
convince sudo that they are “allowed” to do such a privileged thing as
installing a system package, the malicious software installed by the attacker
would happily intercept that and send it back to its master.

From this point on, the attacker has the account password of the account where
their software runs and which they control. The attacker can now utilise sudo
powers at their will. The security impact would be ranging from “high” to
“extreme” depending on how committed the attackers are.

Following the logic, why would we want to introduce an additional complexity
that does not address the issue it was supposed to address, which is “to limit
exposure of the root account”?

The light side of “sudo”. Is there one?

So, is sudo any good for anything? Actually, yes, it is. All in all, sudo
is a tool that attracts a lot of attention from the security researchers and
auditors, its codebase got numerous peer reviews and the functionality the tool
provides can be used for good. The following scenarios come to my mind right
away:

On a SELinux enabled system it seems that sudo is the only properly
implemented and reliable way to assume a different SELinux role. All other
mechanisms are either lacking in the functionality or just do it half way
leaving some artefacts behind;

Unless some effort is put into tweaking the way PAM (Pluggable
Authentication Modules, an authentication framework used on Linux, Solaris,
and some other Unix-like systems) authenticates users on LDAP enabled
systems there is no easy way to have two separate accounts (a privileged and
a non-privileged account) for the same LDAP user. This could be addressed
administratively (e.g. by defining additional privileged users in LDAP) or
technically by implementing account names’ prefixes. However, if there are
budgetary and/or time constraints to implement the proper security framework
sudo with a quite restricted configuration would be an acceptable
compromise.

Unfortunately, personally, I failed to find any other justified applications of
sudo in a secure environment and would be happy to get some feedback if you
have something in mind worth including into the list above.

How can we improve the security of our systems in relation to the “sudo” usage?

OK, so we got to the point where we are standing at a crossroad and we kind
of established that excessive usage of sudo is a bad thing (for
security-paranoid readers - read: “almost any usage of sudo except for
changing SELinux roles on a SELinux-enabled system is a bad thing”). So, what
is the alternative way of doing things? Well, there is a complex approach on
addressing and minimising the privilege escalation risks and roughly it can be
summarised as follows:

For example, if you need to work on content, the account you use to log
into the remote server should be allowed to do just that. This sounds a bit
extreme, so we may re-phrase it as follows:

Each account should be provided the least number of required privileges
to do specific tasks under that account and should not be used for
anything else outside the defined set of activities.

Again, if you include “becoming root” into the list of defined activities
it would kind of defeat the purpose, so please resist this temptation. :)

there should be a defined list of accounts which are allowed to do
system-wide modifications (e.g. privileged accounts)

In line with the previous bullet point, these accounts must be used for
these activities only (system updates, installing new software, modifying
system-wide configuration). The expectation is that the privileged
accounts are used on occasion only;

privileged accounts during their activities should not cross the security
boundary with the less privileged accounts.

This is needed to avoid attacks from the less privileged accounts toward
more privileged (e.g. process hijacking, file races, etc.). Unfortunately,
this point is a bit confusing without a proper explanation that may take
several blog posts to be fully covered, but in a nutshell it means that
root should not touch anything writable by the less privileged account.
Some examples of the bad and insecure behaviour include:

changing directory to a directory writable by non-root,

executing scripts from a directory writable by non-root accounts or
scripts that are writable by non-root,

copying a file/directory from/to a directory writable by non-root
accounts,

and so on.

if possible (and this is highly recommended) privileged accounts should be
accessed from the trusted and secure machines.

It is really hard to define what the “trusted and secure machine” is, but
generally it should be assumed

that it is a laptop or a desktop station that is used entirely for the
work purposes (no free time surfing on the leisure sites and stuff :) ),

that proper firewall rules and protection techniques were used to secure
the machine, and

that the operator is security-minded and does everything they can to
ensure integrity and security of their machine and software installed
on it.

I would be really happy to answer any question in regard to this article and
provide any possible help in making our everyday system level activities more
secure, so do not hesitate to comment or contact me.