Skip to content

Programs Allowed Through sudo

See Users and sudo for how to read sudo -l. This page follows what an allowed command trusts while running as root after that command has been found.

The key question with sudo is which low-privilege inputs a command trusts while running as root, rather than simply whether the command can be run.

Terminal window
sudo -l
ls -la <allowed-command>
sed -n '1,240p' <script>
  • The allowed command runs as root.
  • The program trusts a user-writable file, plugin directory, checkpoint, symlink, environment variable, or relative path.
  • If SETENV or env_keep is present, environment variables also become inputs.
Terminal window
sudo <allowed-command>
sudo <allowed-command> <extra-arg>
namei -l <path-read-by-command>
find <app-dir> -maxdepth 5 -writable -ls 2>/dev/null
  • Purpose: Check exact sudoers matching, whether extra arguments are allowed, files read during execution, and writable locations.
  • Prerequisites: Read the code before running a command that changes state. Actions such as restart, backup, train, and logs have side effects.
  • Interpreting output: If an added argument triggers a password prompt, it may not match the original NOPASSWD rule. An allowed command that reads a low-privilege user’s input as root is a candidate for privilege escalation.
  • Troubleshooting: Check for missing NOPASSWD, a required TTY, different PATH, reset environment variables, wildcard scope, and deny rules.
  • Alternative: sudo -V, strings <binary>, or strace -f -e file <command>. Use strace only when needed because it increases noise and logs.
  • State changes: sudo -l does not change the target, but may appear in authentication logs. Record changes made by an allowed command for cleanup. The recording fields are in Logs and Detection.

Check permissions on paths that are read in File and Directory Permissions and Writable Paths Read by root.

An allowed command can form a privilege boundary in the following ways. When making a claim, retain the full sudoers rule, the complete target script, and id output before and after execution.

  • The allowed command alone does not yield a root shell. Processing may proceed only when another service reaches a particular state, such as a maintenance window. The protocol that changes that state is not necessarily HTTP.
  • Even without command injection in an allowed Python command, a plugin read at startup (.pth and site.addsitedir()) can execute code as root. Trace the flow in Trust Boundaries in Custom Code.
  • If the rule forbids a subcommand, read only the implementation of permitted subcommands.
  • With an exact match on the interpreter and script, extra arguments cannot be used. The boundary lies in files read by the script.
  • If sudo is denied, stop trying variations of the allowed command. The next possibility is a root service on localhost.

Enumerate SUID and file capabilities in File and Directory Permissions. Check a process’s CapEff, and record the version, namespace, capability, and module when considering a kernel or local exploit, in Containers and Namespaces.