In a well controlled environment you typically do not want people logging
into servers with privileged access (absent of additional external
processes, such as a keystroke logged session manager). If you have 5
SAs all logging in as
root then how can you audit activity and determine
if it was Tom, Dick or Harry that rebooted the server? Similarly you don’t
want DBAs directly logging in as
oracle; how do you know who dropped
the production table?
Typically this is solved by having the SA (or DBA, or AppOp, or…) login as themselves and then use a privilege escalation method. This method can use alternative authentication processes (e.g. 2FA), audit activity and, if properly configured, limit activity.
On Unix the standard tool is
sudo. Some vendors may provide alternatives
(e.g. Centrify has
dzdo, Fox Technology’s Server Control has
but the principles apply.
Business As Usual vs Elevated privileges
Any discussion of privilege escalation needs to consider the user’s work role. What an organisation considers privileged may not be the same as the operating system.
One simple example of this is the
df command. If a normal user runs
this then they may not see every file system mount.
$ df | grep dir1 $ sudo df | grep dir1 /dev/shm 249720 0 249720 0% /tmp/dir1/mountpoint
This situation may occur because the mountpoint may not be reachable from the normal user
drwx------ 3 root root 4096 Aug 26 15:42 /tmp/dir1
So from a Unix perspective, we need elevated permissions to run the
command and get a full listing. But from a business perspective it
would seem reasonable to allow all the SAs to run
The distinction between what the platform considers privileged and what the business considers privileged really needs to be kept in mind, especially when formulating policies and procedures around how to manage this stuff.
Read-only vs Read-write
A number of commands may be obviously read-only;
cat is a great example
of this; it can read files, but not write to them.
Side Bar: I’ve seen people ask for
sudo echobecause they think they can do things like
sudo echo hello > /etc/my.file. That’s a misunderstanding of how the shell evaluates things; the
>redirection happens at the current shell level, with the normal user privileges. Similarly
sudo cat myfile > /etc/my.filedoesn’t work; the
catmay have elevated permissions, but the
Some commands can operate in both modes. For example
ethtool can be used to see the state of the network adapter, including
the negotiated speed and duplex. However it can also change the
adapter settings, force renegotiation or even break network connectivity.
Similarly, on some OS’s,
ifconfig will only show the MAC addresses if
root. But now the SA has the ability to change IP addresses
and other settings on the fly.
Typically commands that can make changes should not be part of a BAU profile because they may require a change control process before they can be used.
However, commands that can operate in read and write mode may be able to
ifconfig, for example, could be limited to
sudo ifconfig -a
which would allow the SA to see the MAC addresses but not change things;
sudo fdisk -l may be permitted because it allows listing of the
partition tables, without making changes.
A number of commands can be limited to read-only access, and so may be considered part of the BAU scope.
Read-only may also be bad!
At a first glance, it might make sense to be able to grant lots of read-only access commands to people. After all, an SA may need to read a root-only configuration file. For example…
$ cat /etc/securetty cat: /etc/securetty: Permission denied
What would be the harm in allowing the SA to
cat every file?
Unfortunately there may be files on the system that should be protected
from the SA. Should the SA be allowed to read
/opt/my_app/etc/super_secret.txt ? Unlimited
cat would allow this.
Unlimited read access may also allow a pivot to another server; for
example if there is an
ssh key used by a process to send data to another
server then this key is probably passphrase-less (it’s a common scenario).
cat would allow the SA to take a copy of the key and
then try and access the remote server.
Obviously we may have audit logs of the abuse of this privilege, but prevention is always better than detection!
We need to be aware of how
sudo parses commands. The
might be mitigated by only allowing read access to files in
%sa_group ALL=(root) /bin/cat /etc/*
$ sudo -l User sweh may run the following commands on test1: (root) /bin/cat /etc/* $ cat /tmp/dir1/secret.txt cat: /tmp/dir1/secret.txt: Permission denied $ sudo cat /tmp/dir1/secret.txt Sorry, user sweh is not allowed to execute '/bin/cat /tmp/dir1/secret.txt' as root on test1.spuddy.org. $ sudo cat /etc/../tmp/dir1/secret.txt hidden $ sudo cat /etc/subgid /tmp/dir1/secret.txt hidden
In this case I was able to make use of how filenames work to display the protected file, and just to use two filenames (one permitted) to match the pattern. Two problems with one configuration entry!
If you plan on using wildcards then determine if that will allow for excessive
privileges this may expose. In some cases this might be mitigated with the
! configuration, which will deny commands.
Some commands allow for the user to drop into a subshell to perform
activity and then
exit back to the program. A common example of this
$ sudo less test myfile !sh sh-4.2# id uid=0(root) gid=0(root) groups=0(root)
Now while the
less command itself was logged, all activity performed
inside the subshell isn’t properly tracked. The SA has full
level permissions on the machine and we can’t audit their activity.
This may, sometimes, be mitigated with the
NOEXEC option in the
$ sudo -l User sweh may run the following commands on test1: (root) NOEXEC: /bin/less $ sudo less test myfile !sh !done (press RETURN)
This isn’t infallible, however, and may block functionality the application needs. It may also not work on every operating system.
Sometimes the most unexpected of commands allows for a shell escape; the
one that surprised me was the Solaris
Open additional files.
This is related to shell escapes, but allows for files to be read or modified unexpectedly.
For example, we might want to allow for
vi to be run on a single file,
but the user can open additional files.
$ sudo -l User sweh may run the following commands on test1: (root) /bin/cat (root) NOEXEC: /bin/vi /home/sweh/test
We’ve NOEXEC’d this, but the user can still do
:r inside the session
to read protected content. (This is hard to screen shot…)
$ sudo vi /home/sweh/test myfile :r /tmp/dir1/secret.txt myfile hidden :w! /tmp/dir1/secret.txt "/tmp/dir1/secret.txt" 2L, 14C written :q! $ sudo cat /tmp/dir1/secret.txt myfile hidden
Editing of files is a common requirement, so
sudo adds another option,
sudoedit. This can be invoked as
sudo -e. The
way it works is clever; it makes a copy of the file you want to edit
in a temporary directory, then runs your editor as your real user, and
if changes have been detected copies the file back (with the correct
permissions, ownership, etc). In this way any shell escape or file
reads are done as the real user, and not privileged.
There are other limitations on
sudoedit (eg not in a writeable directory)
but it can handle a number of cases where BAU write-file access is
Functional access (passwordless)
I’ve mostly been focusing on human level access (I’ve described SAs, but
this would also work for DBAs, AppOp, and similar, and the target user
need not be
Sometimes there may be a need for a functional (or service) account to
need to perform privileged activity. Examples abound, but a simple one
might be a polling look that wants to see what servers have listening ports,
and what processes these are. Consider this job being
cron every hour:
for host in test1 test2 test3 do ssh svc_acct@$host sudo netstat -anp | grep -w LISTEN done
root here because of the
-p option to
Obviously we can’t enter the password each time (indeed there may not be a
valid password, because we use key based authentication). Fortunately there’s
$ sudo -l (root) NOPASSWD: /bin/netstat -anp $ ssh test1 sudo netstat -anp | grep -w LISTEN tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 859/master tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 759/sshd tcp6 0 0 ::1:25 :::* LISTEN 859/master tcp6 0 0 :::22 :::* LISTEN 759/sshd
NOPASSWD: entries can also be applied to human user accounts if
you consider the activity to be sufficiently low risk that the human
doesn’t need to re-authenticate (the
df example from earlier may
Blacklists don’t work – Example of a bad setup
I was working with a team some time back who wanted to perform centralised
data collection and some of the data required
root level permissions.
Now, naturally, I refused them
ALL access; having a tool with access to
every server and having unlimited
root on all those servers was an
unacceptable concentration of risk.
They went away and came back with the following request:
#List of commands svc_acct is not allowed to execute via sudo Cmnd_Alias SVCNOEXEC= adduser*, chmod*, chown*, cp*, ...and so on svc_acct ALL=NOPASSWD: ALL, !SVCNOEXEC
(In all there were 30 commands listed in the SVCNOEXEC alias).
Apart from the fact this wasn’t a valid
sudoers file, these blacklist
setups provide ZERO security in the environment. I was able to think
of three approaches within a few minutes:
First obvious way to bypass those restrictions:
Run the command under
/bin/sh, which wasn’t restricted:
sudo /bin/sh -c '<any_command_in_that_list>'
sudo /bin/sh -c 'halt'
Second less obvious way to bypass these restrictions:
copy the file to a tmp directory and run that:
cp /sbin/halt /tmp/myprogram sudo /tmp/myprogram
A third way
Create a wrapper and call that
echo halt > /tmp/myprogram chmod 755 /tmp/myprogram sudo /tmp/myprogram
I could probably come up with more esoteric variations as well (symlinks,
ld.so, perl, python… even use
sed to update the sudoers file,
Basically, blacklists like this can be bypassed with zero effort and should not be used.
The secure way of setting up a sudo profile is to default-deny and then only permit the minimum necessary commands.
These commands should be restricted with options to ensure they are
read-only and do not allow further privileges. So, for example, on
sudo format may not be permitted because you can shell out
of it. Similarly
hbacmd may not be permitted without restriction
because it can be used to reset HBAs, change binding rules, etc. but
hbacmd ListHBAs is OK.
Of course, understanding business requirements and not blocking efficiency also needs to feed into the decision of what commands you allow an SA to run BAU.
You may decide that
sudo cat is OK, trusting on the audit log to be a
sufficient activity trail (perhaps with reporting triggered from it if
a restricted file is accessed). That’s a definite productivity gain!
Also you may be able to use additional tools; e.g.
SELinux maybe able
to lock down access to
secret.txt, even to users running
If you have any additional guidelines for
sudo entry creation, please
leave a message in the contents! I know I haven’t covered every
scenario (e.g. wrapper scripts) because some of those could be a post