PRACTITIONER GUIDE
Practitioner Guide11 min read

Linux sudo and sudoers Security Hardening: Restricting Privilege Escalation and Auditing sudo Usage

0
recommended timestamp_timeout value for high-security systems, requiring password re-entry for every sudo invocation rather than caching credentials for the default 15-minute window
> 100
binaries with documented shell escape paths on GTFOBins, including vi, less, find, awk, perl, and python; every binary in sudoers should be checked against this list before granting access
NOPASSWD
sudoers directive that removes the authentication requirement entirely, allowing any process running as the user to escalate to root without a password; should be removed from all entries except technically required service accounts
/var/log/sudo-io/
default directory where sudo I/O session transcripts are stored when log_input and log_output are enabled in sudoers Defaults; replaying these with sudoreplay supports security investigations and compliance audits

SponsoredRetool

Retool's new app builder is where AI-generated code ships safely

Building apps with AI is easy. Getting them to production safely is another story.

Start building for free today

The sudoers file is modified once to grant a developer access to restart a service, and then never reviewed again. Over years, entries accumulate: NOPASSWD grants added because an automated script needed root access, ALL command grants added because it was easier than figuring out the exact command path, and entries for user accounts that no longer exist at the organization. The result is a privilege escalation menu that any attacker who reaches a user account on the system can exploit.

Sudoers hardening is one of the higher-leverage security improvements for Linux environments: removing NOPASSWD entries, replacing ALL grants with specific command lists, auditing GTFOBins for shell escape paths in allowed commands, and enabling sudo logging. The changes are low-risk when implemented carefully and eliminate an entire class of local privilege escalation paths.

Immediate cleanup: the highest-risk sudoers patterns

The most dangerous sudoers misconfigurations share a common trait: they were created for operational convenience and never reviewed from a security standpoint. This section covers the two highest-priority cleanup actions — replacing broad ALL command grants and removing text editor grants — using visudo, Cmnd_Alias definitions, and sudoedit. Completing these two changes eliminates the most commonly exploited privilege escalation paths before tackling logging and monitoring.

Replace ALL command grants with specific Cmnd_Alias entries for each role

For each user or group that currently has ALL=(ALL) ALL access, work with the system owners to identify what commands they actually need for their role. Application administrators typically need systemctl commands for their specific services, log file read access, and possibly application binary execution — not full root shell access. Replace the ALL grant with a Cmnd_Alias listing the exact commands with full paths. For administrators who genuinely need unrestricted root access, convert them to the wheel group (which has full sudo access) and ensure they are using interactive authentication (no NOPASSWD), audit their sudo usage, and require MFA for their account authentication if possible. The goal is that no service account or non-administrator user account has unrestricted root access.

Remove or replace sudoedit for file editing rather than granting sudo to vi or nano

Granting sudo access to a text editor (vi, nano, vim, emacs) provides a trivial shell escape on any system where the editor's shell invocation feature is available. Replace all text editor grants in sudoers with sudoedit (also called sudo -e): in sudoers, configure SUDOEDIT = sudoedit /etc/nginx/nginx.conf then grant the user access to sudoedit /etc/nginx/nginx.conf specifically. sudoedit copies the file to a temporary location, opens it with the user's own editor (running as the user, not as root), and copies the edited file back as root. There is no root shell process running the editor, preventing shell escape attacks. This also means the editor runs with the user's environment and configuration rather than root's, which is safer.

Detection: logging and monitoring sudo privilege use

Logging without forwarding is not detection: sudo session transcripts that live only on the local system can be deleted by a user with the right sudo access. This section covers enabling sudo I/O logging in the sudoers Defaults block using log_input and log_output, configuring auditd to capture execve calls with euid=0, and shipping auth log entries to a SIEM the sudoer cannot reach. A quarterly review cadence using visudo and account inventory comparison catches stale entries before attackers do.

Enable sudo I/O logging and ship transcripts to a system the sudoer cannot modify

Configure Defaults log_input, log_output, log_host in /etc/sudoers and forward sudo auth log entries (/var/log/auth.log on Debian/Ubuntu, /var/log/secure on RHEL/CentOS) to a centralized SIEM using a log forwarder running as a system service (not as the user with sudo access). The key security requirement is that the user who has sudo access cannot delete or modify the audit trail of their own sudo usage — forwarding to an external SIEM controlled by the security team satisfies this. Configure a SIEM alert for sudoers file modification events (auth.log entries containing COMMAND=/usr/sbin/visudo or file system audit events on /etc/sudoers) so that any change to the privilege configuration is immediately visible.

Run a quarterly sudoers audit to remove stale entries and catch drift

Schedule a quarterly review of all sudoers configuration: compare the current user and group entries against the current HR employee list and active service account inventory to identify entries for users who no longer work at the organization or service accounts that have been decommissioned. Review all NOPASSWD entries and confirm each has a documented business justification and owner. Check all command entries against GTFOBins for any newly documented shell escape paths that were not known when the entry was originally created. Automate the stale account check using a script that reads sudoers entries and compares against the output of getent passwd for existing accounts — entries for non-existent accounts should be removed immediately.

Free daily briefing

Briefings like this, every morning before 9am.

Threat intel, active CVEs, and campaign alerts, distilled for practitioners. 50,000+ subscribers. No noise.

The bottom line

Linux sudo hardening addresses the most exploited local privilege escalation path on Linux systems: the overly permissive sudoers configuration that was created for convenience and never reviewed for security implications. The hardening actions — removing NOPASSWD where not required, replacing ALL grants with specific command lists, auditing allowed commands against GTFOBins for shell escape paths, replacing text editor sudo grants with sudoedit, and enabling I/O logging forwarded to an external SIEM — each independently reduce the attack surface, and together close most of the common sudo privilege escalation paths that attackers and penetration testers find routinely in Linux environments.

Frequently asked questions

How do I audit the sudoers file for dangerous configurations?

Audit the sudoers configuration by reading both /etc/sudoers and all files in /etc/sudoers.d/ (sudo reads both locations). Run sudo visudo -c to check the syntax of the current configuration without modifying it — visudo -c reports any syntax errors that would cause sudo to fail. Check for the following dangerous patterns: any line containing NOPASSWD (grants password-free root access), any line containing (ALL) ALL or (root) ALL that grants unrestricted command access, lines containing wildcards in command paths such as /usr/bin/* which can be exploited with path manipulation, and lines granting sudo access to interactive shells (/bin/bash, /bin/sh) directly. Export all sudoers content with cat /etc/sudoers /etc/sudoers.d/* and review the complete effective configuration, since the modular sudoers.d directory may contain entries added by package installations that were never reviewed.

How do I restrict sudo access to specific commands rather than all commands?

Replace broad ALL command grants with specific Cmnd_Alias entries that list only the exact commands the user or role needs. In sudoers, define: Cmnd_Alias WEBSERVER_CMDS = /usr/bin/systemctl restart nginx, /usr/bin/systemctl status nginx, /usr/bin/journalctl -u nginx then grant this alias to the webops group: %webops ALL=(root) NOPASSWD: WEBSERVER_CMDS to allow only those specific systemctl commands for nginx without granting general root access. For each command granted, check GTFOBins for shell escape paths: systemctl can spawn shells via systemctl edit which opens a text editor with root privileges, so restrict to specific unit names with the full command string rather than systemctl with wildcards. Use the absolute path to each binary (not just the binary name) to prevent PATH manipulation attacks.

How do shell escape privilege escalation attacks work through sudo-allowed binaries?

Shell escape attacks exploit the shell spawning capabilities built into many Linux binaries. If a user has sudo access to vi (/etc/sudoers: user ALL=(root) NOPASSWD: /usr/bin/vi /etc/nginx/nginx.conf), they can run sudo vi /etc/nginx/nginx.conf and then type :!bash from within vi to spawn a root bash shell, despite the sudoers rule appearing to only allow editing the nginx config file. Similar escapes exist in less (run !bash), find (run -exec /bin/bash -p ;), awk (run BEGIN {system("/bin/bash")}), and many others documented at gtfobins.github.io. To prevent this: restrict the command to the specific file argument (sudo vi /etc/nginx/nginx.conf provides less attack surface than sudo vi without a path restriction), use sudoedit instead of sudo vi for file editing (sudoedit uses the user's editor rather than spawning root vi, preventing the shell escape), and audit GTFOBins for every binary before granting it in sudoers.

How do I enable sudo session logging and forward it to a SIEM?

Enable sudo session I/O logging by adding Defaults log_input, log_output, log_host, log_year to the /etc/sudoers Defaults section. This stores complete sudo session transcripts in /var/log/sudo-io/ organized by user, date, and sequence number. The log files are binary format readable with sudoreplay: sudoreplay /var/log/sudo-io/user/date/sequence replays the session. For SIEM forwarding, configure a log shipper (Filebeat, Fluentd) to also collect /var/log/auth.log or /var/log/secure which contains sudo syslog entries in a parseable format: sudo invocations appear with the format sudo[PID]: USER : TTY=tty PWD=path USER=root COMMAND=command. Parse these fields in the SIEM to create alerts for sudo usage outside of expected maintenance windows, sudo usage by unexpected user accounts, and multiple rapid sudo invocations that might indicate automated privilege escalation.

How do I configure auditd to monitor sudo privilege escalation?

Configure auditd rules to capture privilege escalation events by monitoring the execve syscall with euid=0 (effective user ID 0 = root) to detect processes running as root, and by monitoring writes to sudoers files that would modify the privilege configuration. Add these rules to /etc/audit/rules.d/sudo.rules: -a always,exit -F arch=b64 -S execve -F euid=0 -k root_command to log all commands run as root (which includes sudo-invoked commands), and -w /etc/sudoers -p wa -k sudoers_change and -w /etc/sudoers.d/ -p wa -k sudoers_change to alert on sudoers file modifications. Load the rules with augenrules --load. Forward auditd logs to a SIEM and create alerts for sudoers file write events (key sudoers_change) and for root command executions outside of normal maintenance windows. Note that logging all root execve calls generates high log volume — filter by specific users or commands in the SIEM if volume is excessive.

How do I manage sudo access for service accounts and automated scripts?

Service accounts that run automated scripts requiring root access present a specific sudoers challenge: interactive password authentication is not possible for automated scripts, leading to NOPASSWD entries. Mitigate NOPASSWD risks for service accounts by: restricting the command to the absolute minimum required (the specific script path with exact arguments, not a shell or interpreter), setting the service account to be a system account (nologin shell, no interactive login possible) that cannot be used interactively by an attacker who might compromise it, restricting which host and which target user the command can be run as (specific host = specific server, target = root only for the specific command rather than all users), and enabling sudo logging for the service account so every automated execution is recorded. Consider whether the automated task can be restructured to run as a less-privileged user with specific file capabilities (cap_net_bind_service, cap_dac_override) rather than full root access via sudo.

What is the sudoers timestamp_timeout and how should I configure it?

The sudoers timestamp_timeout Defaults setting controls how long a sudo authentication credential is cached after the user enters their password: timestamp_timeout=15 (the default) means the user does not need to re-enter their password for additional sudo commands within 15 minutes. Set this in /etc/sudoers Defaults: Defaults timestamp_timeout=5 for a 5-minute cache window, which balances usability (administrators doing multiple operations do not need to re-enter the password for every command) with security (a shorter window limits the period during which a malware process running as the user could call sudo without prompting). Set Defaults timestamp_timeout=0 for environments where every sudo invocation must be authenticated independently, appropriate for highly sensitive systems where the additional authentication friction is acceptable. The timestamp is per-terminal (tty) by default — setting Defaults timestamp_type=global applies the cache across all terminals, which is less secure since one authenticated terminal enables sudo in all others.

Sources & references

  1. sudo Security Best Practices
  2. GTFOBins sudo Privilege Escalation
  3. Linux auditd Configuration Guide
  4. CIS Ubuntu Linux Benchmark sudo Controls

Free resources

25
Free download

Critical CVE Reference Card 2025–2026

25 actively exploited vulnerabilities with CVSS scores, exploit status, and patch availability. Print it, pin it, share it with your SOC team.

No spam. Unsubscribe anytime.

Free download

Ransomware Incident Response Playbook

Step-by-step 24-hour IR checklist covering detection, containment, eradication, and recovery. Built for SOC teams, IR leads, and CISOs.

No spam. Unsubscribe anytime.

Free newsletter

Get threat intel before your inbox does.

50,000+ security professionals read Decryption Digest for early warnings on zero-days, ransomware, and nation-state campaigns. Free, daily, no spam.

Unsubscribe anytime. We never sell your data.

Eric Bang
Author

Founder & Cybersecurity Evangelist, Decryption Digest

Cybersecurity professional with expertise in threat intelligence, vulnerability research, and enterprise security. Covers zero-days, ransomware, and nation-state operations for 50,000+ security professionals every morning.

Black Hat Giveaway

Win a $2,495 Black Hat pass.

Full-access to Black Hat USA 2026 in Las Vegas. Subscribe free to enter.

Joins Decryption Digest daily briefing. Unsubscribe anytime.

Giveaway: Black Hat USA 2026 Full-Access Pass ($2,495 value)

Details →
Daily Briefing

Subscribe to enter the giveaway

Every subscriber is automatically entered. You also get daily threat intel every morning: zero-days, ransomware, and nation-state campaigns. Free. No spam.

Already subscribed? You're already entered.

Giveaway

Win a $2,495 Black Hat USA 2026 pass.