+
firebase
+
+
+
+
+
aws
+
neo4j
+
+
+
+
+
phoenix
htmx
+
0b
+
pandas
+
+
+
prettier
alpine
nest
kali
graphdb
git
+
+
ionic
sse
sql
ionic
kotlin
android
++
gin
packer
+
arch
+
!=
wsl
wasm
+
android
riot
pytest
+
+
+
clj
+
elasticsearch
yaml
d
+
php
sqlite
sql
+
+
+
circle
+
+
λ
+
+
+
+
cypress
atom
+
css
fortran
torch
lisp
spring
+
astro
Back to Blog
Configuring sudo Access and Privilege Escalation in AlmaLinux
AlmaLinux Security Linux

Configuring sudo Access and Privilege Escalation in AlmaLinux

Published Jul 26, 2025

Master sudo configuration and privilege escalation in AlmaLinux. Learn how to set up secure sudo policies, manage sudoers file, implement time-based access, and follow security best practices.

20 min read
0 views
Table of Contents

The sudo (superuser do) command is one of the most critical security components in Linux systems, allowing authorized users to execute commands with elevated privileges. Proper sudo configuration is essential for maintaining system security while providing necessary administrative access. This comprehensive guide covers everything you need to know about configuring sudo access and managing privilege escalation in AlmaLinux.

Understanding sudo and Privilege Escalation

What is sudo?

sudo allows authorized users to run commands as another user (typically root) based on policies defined in the sudoers file. Unlike logging in as root directly, sudo provides:

  • Accountability: All commands are logged with the user who executed them
  • Granular Control: Specific commands can be allowed or denied
  • Temporary Elevation: Privileges are elevated only for specific commands
  • Password Verification: User’s own password is used (not root password)

How sudo Works

When a user runs a sudo command:

  1. sudo checks the /etc/sudoers file for permissions
  2. Prompts for the user’s password (if required)
  3. Verifies the user has permission for the specific command
  4. Executes the command with elevated privileges
  5. Logs the action to the system log

Default sudo Behavior

# Check sudo version
sudo -V

# List current user's sudo privileges
sudo -l

# Run command as root
sudo command

# Run command as specific user
sudo -u username command

# Run shell as root
sudo -i
sudo -s

# Edit file with sudo
sudo -e /etc/hosts
sudoedit /etc/hosts

sudo Configuration Files

Primary Configuration Files

  1. /etc/sudoers: Main configuration file
  2. /etc/sudoers.d/: Directory for additional configuration files
  3. /etc/sudo.conf: sudo front-end configuration

Editing sudoers Safely

Always use visudo to edit sudoers files:

# Edit main sudoers file
sudo visudo

# Edit specific file in sudoers.d
sudo visudo -f /etc/sudoers.d/custom

# Check sudoers syntax
sudo visudo -c

# Use specific editor
sudo EDITOR=nano visudo

sudoers File Structure

# /etc/sudoers basic structure
# User privilege specification
root    ALL=(ALL:ALL) ALL

# Group privilege specification
%wheel  ALL=(ALL:ALL) ALL

# User alias specification
User_Alias ADMINS = john, jane, bob

# Command alias specification
Cmnd_Alias SHUTDOWN = /sbin/shutdown, /sbin/reboot

# Host alias specification
Host_Alias SERVERS = server1, server2, 192.168.1.0/24

Basic sudo Configuration

Granting Basic sudo Access

# Method 1: Add user to wheel group
sudo usermod -aG wheel username

# Method 2: Create user-specific rule
sudo visudo
# Add line:
username ALL=(ALL) ALL

# Method 3: Create file in sudoers.d
echo "username ALL=(ALL) ALL" | sudo tee /etc/sudoers.d/username
sudo chmod 440 /etc/sudoers.d/username

Password Configuration

# In sudoers file:

# Require password (default)
username ALL=(ALL) ALL

# No password required
username ALL=(ALL) NOPASSWD: ALL

# No password for specific commands
username ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart httpd

# Password timeout (in minutes)
Defaults timestamp_timeout=30

# Always require password
Defaults timestamp_timeout=0

# Require password for each command
Defaults timestamp_type=global

Basic Restrictions

# Allow specific commands only
username ALL=(ALL) /usr/bin/systemctl, /usr/bin/journalctl

# Deny specific commands
username ALL=(ALL) ALL, !/usr/bin/su, !/usr/bin/passwd root

# Allow command with specific arguments
username ALL=(ALL) /usr/bin/systemctl restart httpd
username ALL=(ALL) /usr/bin/systemctl reload httpd

# Prevent shell escapes
username ALL=(ALL) NOEXEC: /usr/bin/vi

Advanced sudoers Syntax

User and Host Specifications

# Syntax: user host=(runas_user:runas_group) commands

# Allow on specific host only
john server1=(ALL) ALL

# Allow from specific network
john 192.168.1.0/24=(ALL) ALL

# Run as specific user
john ALL=(apache) /usr/bin/apachectl

# Run as specific user and group
john ALL=(apache:apache) /var/www/scripts/*

Using Aliases

# User aliases
User_Alias ADMINS = john, jane, %sysadmin
User_Alias DEVELOPERS = alice, bob, charlie
User_Alias OPERATORS = dave, eve

# Command aliases
Cmnd_Alias SHUTDOWN_CMDS = /sbin/shutdown, /sbin/reboot, /sbin/halt
Cmnd_Alias NETWORK_CMDS = /sbin/ifconfig, /sbin/ip, /usr/bin/netstat
Cmnd_Alias SERVICE_CMDS = /usr/bin/systemctl start *, \
                          /usr/bin/systemctl stop *, \
                          /usr/bin/systemctl restart *

# Host aliases
Host_Alias WEBSERVERS = web1, web2, web3
Host_Alias DBSERVERS = db1, db2
Host_Alias DMZ = 10.0.1.0/24

# Using aliases in rules
ADMINS ALL=(ALL) ALL
DEVELOPERS WEBSERVERS=(apache) SERVICE_CMDS
OPERATORS ALL=(ALL) SHUTDOWN_CMDS, NETWORK_CMDS

Complex Rules

# Multiple commands with different runas
john ALL=(root) /usr/bin/yum, (apache) /usr/bin/apachectl

# Wildcards and patterns
john ALL=(ALL) /bin/cat /var/log/messages*
john ALL=(ALL) /usr/bin/systemctl * httpd

# Negation
john ALL=(ALL) ALL, !/usr/bin/passwd root, !/usr/bin/su -

# Combining conditions
ADMINS WEBSERVERS=(ALL) NOPASSWD: SERVICE_CMDS, \
                        PASSWD: SHUTDOWN_CMDS

User and Group Management

Group-Based Access

# Grant sudo to wheel group members
%wheel ALL=(ALL) ALL

# Custom group with limited access
%webadmin ALL=(ALL) /usr/bin/systemctl * httpd, \
                    /usr/bin/systemctl * nginx

# Nested groups
%sysadmin ALL=(ALL) ALL
%junior_admin ALL=(ALL) /usr/bin/systemctl, /usr/bin/journalctl

# AD/LDAP groups (with space)
%"domain admins" ALL=(ALL) ALL

Per-User Configuration

# Create individual user files
sudo touch /etc/sudoers.d/john
sudo chmod 440 /etc/sudoers.d/john
sudo visudo -f /etc/sudoers.d/john

# Content example:
# User-specific sudo rules for john
john ALL=(ALL) NOPASSWD: /usr/bin/docker *
john ALL=(ALL) PASSWD: /usr/bin/systemctl

Defaults for Users and Groups

# Set defaults for specific users
Defaults:john !lecture, timestamp_timeout=60

# Set defaults for groups
Defaults:%developers env_keep += "JAVA_HOME MAVEN_HOME"

# Different defaults per host
Defaults@WEBSERVERS log_input, log_output

Command Aliases and Restrictions

Creating Useful Command Aliases

# Package management
Cmnd_Alias PACKAGE_MGMT = /usr/bin/yum install *, \
                          /usr/bin/yum update *, \
                          /usr/bin/yum remove *, \
                          /usr/bin/rpm -*, \
                          /usr/bin/dnf *

# Container management
Cmnd_Alias DOCKER = /usr/bin/docker *, \
                    /usr/bin/docker-compose *, \
                    !/usr/bin/docker exec * /bin/bash, \
                    !/usr/bin/docker exec * /bin/sh

# Database administration
Cmnd_Alias DB_ADMIN = /usr/bin/mysql, \
                      /usr/bin/mysqldump, \
                      /usr/bin/psql, \
                      /usr/bin/pg_dump

# Monitoring commands
Cmnd_Alias MONITORING = /usr/bin/top, \
                       /usr/bin/htop, \
                       /usr/bin/iotop, \
                       /usr/bin/nethogs, \
                       /usr/bin/ss, \
                       /usr/bin/netstat

Restricting Dangerous Commands

# Prevent privilege escalation
Cmnd_Alias DANGEROUS = /usr/bin/su -, \
                       /usr/bin/su root, \
                       /usr/bin/passwd root, \
                       /usr/bin/visudo, \
                       /usr/bin/vim /etc/sudoers, \
                       /usr/bin/nano /etc/sudoers

# Allow all except dangerous
developers ALL=(ALL) ALL, !DANGEROUS

# Restrict shell access
Cmnd_Alias SHELLS = /bin/bash, /bin/sh, /bin/zsh, \
                    /usr/bin/fish, /usr/bin/csh

operators ALL=(ALL) ALL, !SHELLS

Safe Editor Configuration

# Prevent shell escapes from editors
Cmnd_Alias EDITORS = /usr/bin/vim, /usr/bin/vi, \
                     /usr/bin/nano, /usr/bin/emacs

# Use NOEXEC to prevent shell escapes
developers ALL=(ALL) NOEXEC: EDITORS

# Safe editing with sudoedit
developers ALL=(ALL) sudoedit /etc/httpd/conf/httpd.conf, \
                             sudoedit /etc/nginx/nginx.conf

Environment Variables and Security

Managing Environment Variables

# Default environment behavior
Defaults env_reset
Defaults env_keep = "COLORS DISPLAY HOSTNAME HISTSIZE LS_COLORS"
Defaults env_keep += "MAIL PS1 PS2 QTDIR USERNAME LANG LC_*"
Defaults env_keep += "XAUTHORITY"

# Secure path
Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin

# Keep specific variables for users
Defaults:developers env_keep += "JAVA_HOME PATH PYTHONPATH"

# Remove dangerous variables
Defaults env_delete += "LD_PRELOAD LD_LIBRARY_PATH"

# Check environment
Defaults env_check += "TERM TZ"

Security Options

# Require TTY
Defaults requiretty

# Disable for specific users (for automation)
Defaults:automation !requiretty

# Use pty
Defaults use_pty

# Lecture users
Defaults lecture = always
Defaults lecture_file = /etc/sudo_lecture.txt

# Insults for wrong password
Defaults insults

# Mail on sudo usage
Defaults mail_always
Defaults mailto = "[email protected]"

Time-Based Access Control

Implementing Time Restrictions

# Basic time restrictions (requires sudo compiled with timeout support)
john ALL=(ALL) TIMEOUT=8:00-17:00 ALL

# Using external script for time checking
#!/bin/bash
# /usr/local/bin/check_time.sh
HOUR=$(date +%H)
if [ $HOUR -ge 8 ] && [ $HOUR -lt 17 ]; then
    exit 0
else
    exit 1
fi

# In sudoers:
john ALL=(ALL) /usr/local/bin/check_time.sh && /usr/bin/command

Temporary Access

# Create temporary sudo access
#!/bin/bash
# /usr/local/sbin/grant_temp_sudo.sh
USER=$1
HOURS=$2
EXPIRE=$(date -d "+${HOURS} hours" +%s)

cat > /etc/sudoers.d/temp_$USER << EOF
# Temporary sudo access until $(date -d @$EXPIRE)
# This file will be auto-removed
$USER ALL=(ALL) ALL
EOF

# Schedule removal
echo "rm -f /etc/sudoers.d/temp_$USER" | at now + $HOURS hours

Logging and Auditing

Configure sudo Logging

# Enable logging in sudoers
Defaults logfile = /var/log/sudo.log
Defaults log_input
Defaults log_output
Defaults iolog_dir = /var/log/sudo-io

# Syslog configuration
Defaults syslog = authpriv
Defaults syslog_goodpri = notice
Defaults syslog_badpri = alert

# Per-command logging
john ALL=(ALL) LOG_INPUT: LOG_OUTPUT: /usr/bin/mysql

Setting Up Comprehensive Logging

# Create sudo log directory
sudo mkdir -p /var/log/sudo-io
sudo chmod 700 /var/log/sudo-io

# Configure rsyslog for sudo
echo "authpriv.*  /var/log/sudo.log" | sudo tee -a /etc/rsyslog.d/sudo.conf
sudo systemctl restart rsyslog

# Logrotate configuration
cat << EOF | sudo tee /etc/logrotate.d/sudo
/var/log/sudo.log {
    weekly
    rotate 52
    compress
    delaycompress
    missingok
    notifempty
    create 0640 root root
}
EOF

Monitoring sudo Usage

# View sudo logs
sudo grep sudo /var/log/secure
sudo journalctl -u sudo

# Parse sudo log
sudo cat /var/log/sudo.log | grep -E "COMMAND|USER"

# Real-time monitoring
sudo tail -f /var/log/secure | grep sudo

# Audit sudo usage report
#!/bin/bash
echo "=== Sudo Usage Report ==="
echo "Date: $(date)"
echo -e "\n--- Commands by User ---"
sudo grep "COMMAND" /var/log/sudo.log | awk '{print $6}' | sort | uniq -c | sort -rn

echo -e "\n--- Failed sudo Attempts ---"
sudo grep "incorrect password" /var/log/secure | tail -20

Security Best Practices

1. Principle of Least Privilege

# Bad: Too permissive
developer ALL=(ALL) NOPASSWD: ALL

# Good: Specific permissions
developer ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart httpd, \
                             /usr/bin/systemctl reload httpd, \
                             /usr/bin/tail -f /var/log/httpd/*

2. Use Aliases for Clarity

# Define clear aliases
User_Alias DBA = oracle, postgres
Cmnd_Alias DB_BACKUP = /usr/local/bin/backup_db.sh
Cmnd_Alias DB_RESTORE = /usr/local/bin/restore_db.sh

# Use aliases in rules
DBA ALL=(ALL) NOPASSWD: DB_BACKUP, PASSWD: DB_RESTORE

3. Secure Default Configuration

# Secure defaults
Defaults requiretty
Defaults !visiblepw
Defaults always_set_home
Defaults match_group_by_gid
Defaults use_pty
Defaults env_reset
Defaults secure_path = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
Defaults timestamp_timeout = 15
Defaults passwd_tries = 3
Defaults loglinelen = 0
Defaults insults

4. Regular Auditing

#!/bin/bash
# /usr/local/sbin/audit_sudo.sh
# Audit sudo configuration

echo "=== Sudo Security Audit ==="
echo "Date: $(date)"

echo -e "\n--- Users with full sudo access ---"
sudo grep -E "ALL=(ALL).*ALL" /etc/sudoers /etc/sudoers.d/* 2>/dev/null | grep -v "^#"

echo -e "\n--- NOPASSWD rules ---"
sudo grep -i "NOPASSWD" /etc/sudoers /etc/sudoers.d/* 2>/dev/null | grep -v "^#"

echo -e "\n--- sudoers.d files ---"
ls -la /etc/sudoers.d/

echo -e "\n--- Last sudo usage ---"
sudo journalctl -u sudo -n 20 --no-pager

5. Implement sudo Policies

# Create organization-wide policy
cat << EOF | sudo tee /etc/sudoers.d/00-policy
# Organization Sudo Policy
# Last updated: $(date)

# Global defaults
Defaults requiretty
Defaults !visiblepw
Defaults timestamp_timeout=15
Defaults passwd_tries=3
Defaults lecture=always
Defaults log_input
Defaults log_output
Defaults logfile=/var/log/sudo.log

# Banned commands
Cmnd_Alias FORBIDDEN = /usr/bin/su -, \
                       /usr/bin/su root, \
                       /usr/bin/passwd root, \
                       /usr/bin/visudo, \
                       /bin/bash -c *, \
                       /bin/sh -c *

# No one should run these
ALL ALL=(ALL) !FORBIDDEN
EOF

Troubleshooting sudo Issues

Common Problems and Solutions

1. User Not in sudoers File

# Error: user is not in the sudoers file

# Solution 1: Add to wheel group
sudo usermod -aG wheel username

# Solution 2: Add specific entry
echo "username ALL=(ALL) ALL" | sudo tee /etc/sudoers.d/username
sudo chmod 440 /etc/sudoers.d/username

2. Syntax Errors

# Check syntax before saving
sudo visudo -c

# If locked out, boot in single user mode
# Add to kernel parameters: init=/bin/bash
# Then:
mount -o remount,rw /
visudo
# Fix the error
reboot

3. TTY Required

# Error: sorry, you must have a tty to run sudo

# Fix for specific user
echo "Defaults:username !requiretty" | sudo tee -a /etc/sudoers.d/username

# Fix for automation
echo "Defaults:automation !requiretty" | sudo tee -a /etc/sudoers.d/automation

Debugging sudo

# Enable debug mode
echo "Debug sudo /var/log/sudo_debug all@debug" | sudo tee /etc/sudo.conf

# Test sudo rules
sudo -l -U username

# Validate specific command
sudo -l -U username /usr/bin/command

# Check effective permissions
sudo -k  # Clear cached credentials
sudo -v  # Validate and cache credentials

Recovery Procedures

# If locked out of sudo:

# Method 1: Use root account (if enabled)
su -
visudo

# Method 2: Boot from live media
# Mount the system partition
mount /dev/sda1 /mnt
chroot /mnt
visudo

# Method 3: Single user mode
# Edit grub, add: systemd.unit=rescue.target
# or: init=/bin/bash

Alternative Privilege Escalation Methods

Using su Command

# Switch to root (requires root password)
su -

# Switch to specific user
su - username

# Run single command
su -c "command" - username

Polkit (PolicyKit)

# Check polkit policies
pkaction

# Create custom polkit rule
cat << EOF | sudo tee /etc/polkit-1/rules.d/50-custom.rules
polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.systemd1.manage-units" &&
        subject.isInGroup("wheel")) {
        return polkit.Result.YES;
    }
});
EOF

Using setuid Programs

# Create setuid wrapper (use with caution)
cat << EOF > /tmp/wrapper.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
    setuid(0);
    system("/usr/local/bin/specific_command");
    return 0;
}
EOF

gcc -o /usr/local/bin/wrapper /tmp/wrapper.c
sudo chown root:root /usr/local/bin/wrapper
sudo chmod 4755 /usr/local/bin/wrapper

Capabilities

# Grant specific capability instead of full sudo
sudo setcap cap_net_bind_service=+ep /usr/bin/python3

# View capabilities
getcap /usr/bin/python3

# Remove capabilities
sudo setcap -r /usr/bin/python3

Advanced sudo Features

Using sudo with Scripts

#!/bin/bash
# Script that requires selective sudo

# Check if running with sudo for specific parts
if [[ $EUID -ne 0 ]]; then
   echo "This script must be run with sudo" 
   exit 1
fi

# Drop privileges for non-critical parts
sudo -u $SUDO_USER command_as_original_user

# Elevate again for critical parts
critical_admin_command

sudo in Automation

# Ansible playbook example
- name: Configure sudo for automation
  lineinfile:
    path: /etc/sudoers.d/ansible
    line: "ansible ALL=(ALL) NOPASSWD: ALL"
    create: yes
    mode: '0440'
    validate: '/usr/sbin/visudo -cf %s'

# Puppet example
sudo::conf { 'puppet':
  ensure  => present,
  content => 'puppet ALL=(ALL) NOPASSWD: ALL',
}

Integration with LDAP/AD

# Configure sudo LDAP
cat << EOF | sudo tee -a /etc/sudo-ldap.conf
uri ldap://ldap.example.com
sudoers_base ou=SUDOers,dc=example,dc=com
binddn cn=sudo,dc=example,dc=com
bindpw secret
ssl start_tls
tls_checkpeer yes
tls_cacertfile /etc/ssl/certs/ca-cert.pem
EOF

# NSS configuration
echo "sudoers: files ldap" | sudo tee -a /etc/nsswitch.conf

Conclusion

Proper sudo configuration is essential for maintaining security while providing necessary administrative access. Key takeaways:

  • Always use visudo to edit sudoers files
  • Follow the principle of least privilege
  • Use aliases for clarity and maintainability
  • Enable comprehensive logging and auditing
  • Regular review and update sudo policies
  • Test configurations thoroughly before deployment
  • Document your sudo policies and procedures

Remember that sudo is a powerful tool that, when properly configured, provides a secure and auditable way to manage administrative access. Regular reviews and updates of sudo policies ensure they continue to meet security requirements while supporting operational needs.