Skip to content

Sudoers

sudo is how a normal account becomes root for one command (the benchmark's first item in this area, CIS 5.1.1, is simply that it's installed; on a Debian image where it isn't, su - then apt install sudo). Who may do that, and whether they need a password, is in /etc/sudoers and every file in /etc/sudoers.d/. On an image, that's where a quiet backdoor lives: one line that lets a user, or a whole group, run anything as root with no password.

Read everything

sudo cat /etc/sudoers
sudo ls -l /etc/sudoers.d/
sudo cat /etc/sudoers.d/*

Or in one pass, comments stripped:

sudo grep -rhvE '^\s*(#|$)' /etc/sudoers /etc/sudoers.d/

What a normal file looks like

Defaults        env_reset
Defaults        mail_badpass
Defaults        secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
Defaults        use_pty
root    ALL=(ALL:ALL) ALL
%admin  ALL=(ALL) ALL
%sudo   ALL=(ALL:ALL) ALL
@includedir /etc/sudoers.d

%sudo ALL=(ALL:ALL) ALL is the line that makes the sudo group work. root has its own line. Everything else is either a Defaults option (Sudo Defaults) or something someone added.

What to remove

Pattern Meaning Action
NOPASSWD anywhere Root without typing a password (CIS 5.1.4, Level 2) Remove the word, or the whole line if the user shouldn't have sudo at all
!authenticate anywhere Same thing spelled differently, usually as Defaults !authenticate (CIS 5.1.5) Remove
bob ALL=(ALL) ALL A user granted sudo outside the group Remove the line unless the README names bob as an administrator; then either keep it or put bob in the sudo group instead, not both
%staff ALL=(ALL) ALL A whole group granted sudo Remove unless the README says so
ALL ALL=(ALL) ALL Everyone Remove
bob ALL=(ALL) /bin/bash or /usr/bin/vim A "limited" command that gives a root shell anyway Remove
A file in sudoers.d with an odd name (README, .hidden, zz-backup) Included files are read regardless of name Read it; remove what it grants

Edit safely

Never edit /etc/sudoers with a plain editor. A syntax error locks everyone out of sudo. visudo checks the syntax before saving:

sudo visudo                         # main file
sudo visudo -f /etc/sudoers.d/bob   # a file in the include directory
sudo rm /etc/sudoers.d/bob          # or delete the include file entirely
sudo visudo -c                      # check every file parses

visudo opens in nano; Ctrl+O saves, Ctrl+X exits, and if the file is broken it asks "What now?"; press e to go back and fix it.

Verify

sudo grep -rE 'NOPASSWD|!authenticate' /etc/sudoers /etc/sudoers.d/    # nothing
sudo grep -rhvE '^\s*(#|$|Defaults)' /etc/sudoers /etc/sudoers.d/        # only root, %sudo, %admin, and the include line
sudo visudo -c                                                          # parsed OK
sudo -l -U bob                                                          # what bob may run

sudo -l -U user is the real test: it prints what sudo will let that user do after all files are combined.

Example

sudo grep -r NOPASSWD /etc/sudoers.d/ finds /etc/sudoers.d/dave containing dave ALL=(ALL) NOPASSWD:ALL, and /etc/sudoers has %games ALL=(ALL) ALL. Dave isn't an administrator in the README; delete the file. Nobody in the README is in games; remove the line with visudo. sudo -l -U dave now says dave may not run sudo.

Try it

  1. Add a NOPASSWD line for a test user with visudo, confirm with sudo -l -U, remove it.
  2. Break /etc/sudoers syntax in visudo on purpose and see what visudo says.

Build it

A sudocheck.sh that greps /etc/sudoers and /etc/sudoers.d for NOPASSWD, !authenticate, and any line granting a user or group not in your admin list, then runs visudo -c.

Next

Sudo Defaults