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¶
- Add a
NOPASSWDline for a test user withvisudo, confirm withsudo -l -U, remove it. - Break
/etc/sudoerssyntax invisudoon purpose and see whatvisudosays.
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.