# yaml-language-server: $schema=../../../../schema/control.schema.json id: CB-DEB-AUDIT-016 title: Audit changes to sudo rights and commands run as another user finding: title: Changes to administrator rights and use of other identities are not recorded description: Without these records, nobody can tell who granted sudo rights or who acted under another account. status: active profiles: [server-hardened, desktop-hardened] risk: severity: medium assessment: automated tags: [auditd, sudo] description: | Three groups of auditd rules, written to `/etc/audit/rules.d/60-cirsec-scope.rules`: - writes and attribute changes on `/etc/sudoers` and `/etc/sudoers.d/` (key `scope`); - every program started with an effective user different from the real user, by a user who logged in (`execve` with `uid!=euid`, 64 and 32-bit calls, key `user_emulation`), which covers `sudo`, `su` and other setuid programs; - writes to the sudo log file `{{ sudo_log_file }}` (key `sudo_log_file`). rationale: | Granting oneself sudo rights is a classic persistence and privilege escalation step. Recording each change to the sudo policy, each command run under another identity and each attempt to edit the sudo log keeps administrative actions attributable to the person who logged in. impact: | Busy systems where users run many setuid programs produce more audit records. notes: | For each system call the kernel keeps the key of the first matching rule. Running `sudo` or `su` is usually recorded with the key `privileged` (CB-DEB-AUDIT-026), whose rules load first; `user_emulation` catches the other cases. setting: location: /etc/audit/rules.d/60-cirsec-scope.rules default_value: No audit rules recommended_value: "Rules loaded (auditctl -l) and present in /etc/audit/rules.d/60-cirsec-scope.rules" parameters: - name: sudo_log_file type: string description: Path of the sudo log file to watch (the logfile option of sudoers, see CB-DEB-AUTH-005). default: /var/log/sudo.log audit: manual: | 1. Run `auditctl -l` as root. It must list the rules shown below (keys `scope`, `sudo_log_file`, `user_emulation`). 2. Run `grep -h . /etc/audit/rules.d/*.rules`. The same rules must be present, so they load at boot. Expected rules, as `auditctl -l` prints them: ``` -w /etc/sudoers -p wa -k scope -w /etc/sudoers.d -p wa -k scope -a always,exit -F arch=b64 -S execve -C uid!=euid -F auid!=-1 -F key=user_emulation -a always,exit -F arch=b32 -S execve -C uid!=euid -F auid!=-1 -F key=user_emulation ``` checks: - id: rules engine: shell description: Rules loaded in the kernel and present in /etc/audit/rules.d. spec: script: | command -v auditctl >/dev/null 2>&1 || { echo "auditctl not found: auditd is not installed"; exit 1; } want() { cat <<'RULES' -w /etc/sudoers -p wa -k scope -w /etc/sudoers.d -p wa -k scope -a always,exit -F arch=b64 -S execve -C uid!=euid -F auid!=-1 -F key=user_emulation -a always,exit -F arch=b32 -S execve -C uid!=euid -F auid!=-1 -F key=user_emulation RULES printf -- '-w %s -p wa -k sudo_log_file\n' "$CB_SUDO_LOG_FILE" } loaded=$(auditctl -l 2>&1) || { echo "$loaded"; exit 3; } disk=$(cat /etc/audit/rules.d/*.rules 2>/dev/null) n=0 rc=0 while IFS= read -r r; do [ -n "$r" ] || continue n=$((n + 1)) printf '%s\n' "$loaded" | grep -Fxq -- "$r" || { echo "not loaded: $r"; rc=1; } printf '%s\n' "$disk" | grep -Fxq -- "$r" || { echo "not in /etc/audit/rules.d: $r"; rc=1; } done </dev/null 2>&1 || { echo "auditd is not installed" >&2; exit 1; } want() { cat <<'RULES' -w /etc/sudoers -p wa -k scope -w /etc/sudoers.d -p wa -k scope -a always,exit -F arch=b64 -S execve -C uid!=euid -F auid!=-1 -F key=user_emulation -a always,exit -F arch=b32 -S execve -C uid!=euid -F auid!=-1 -F key=user_emulation RULES printf -- '-w %s -p wa -k sudo_log_file\n' "$CB_SUDO_LOG_FILE" } f=/etc/audit/rules.d/60-cirsec-scope.rules t=$(mktemp) { echo '# Written by CIRSEC Baselines CB-DEB-AUDIT-016'; want; } >"$t" if ! cmp -s "$t" "$f"; then cb_backup "$f" cat "$t" >"$f" fi rm -f "$t" chmod 640 "$f" if auditctl -s | grep -q '^enabled 2'; then echo "audit rules are locked (-e 2): reboot to load $f" else augenrules --load >/dev/null fi references: - title: audit.rules(7), Debian manual pages url: https://manpages.debian.org/trixie/auditd/audit.rules.7.en.html publisher: Debian kind: vendor-doc accessed: 2026-10-18 - title: auditctl(8), Debian manual pages url: https://manpages.debian.org/trixie/auditd/auditctl.8.en.html publisher: Debian kind: vendor-doc accessed: 2026-10-18 - title: ANSSI-BP-028 v2.0 - Recommandations de configuration d'un système GNU/Linux (R73) url: https://messervices.cyber.gouv.fr/documents-guides/fr_np_linux_configuration-v2.0.pdf publisher: ANSSI kind: guide accessed: 2026-10-18 mappings: - framework: anssi-linux framework_version: "2.0" id: "R33" relation: partial note: R33 asks for accountability of administration actions; this control records them. - framework: anssi-linux framework_version: "2.0" id: "R73" relation: partial - framework: nist-800-53r5 framework_version: "5.1.1" id: "AU-12" relation: related - framework: nist-800-53r5 framework_version: "5.1.1" id: "AC-6(9)" relation: related - framework: cis-debian-12 framework_version: "2.0.0" id: "6.2.3.1" relation: equivalent - framework: cis-debian-12 framework_version: "2.0.0" id: "6.2.3.2" relation: equivalent - framework: cis-debian-12 framework_version: "2.0.0" id: "6.2.3.3" relation: equivalent - framework: cis-debian-13 framework_version: "1.1.0" id: "6.2.3.1" relation: equivalent - framework: cis-debian-13 framework_version: "1.1.0" id: "6.2.3.2" relation: equivalent - framework: cis-debian-13 framework_version: "1.1.0" id: "6.2.3.3" relation: equivalent threats: - framework: mitre-attack id: T1548.003 - framework: mitre-attack id: T1070.002 related_controls: - id: CB-DEB-AUDIT-011 type: requires - id: CB-DEB-AUDIT-029 type: related - id: CB-DEB-AUTH-005 type: related authors: - name: Alice github: Sn0wAlice verified: - date: 2026-10-18 by: Sn0wAlice versions: ["12"] environment: Proxmox VM, Debian 12 genericcloud image, kernel 6.1.0-54-cloud-amd64, auditd 1:3.0.9-1, BIOS boot notes: "Rules fail on fresh install; fix writes /etc/audit/rules.d/60-cirsec-scope.rules and loads it; rules match auditctl -l, kept after reboot; second run idempotent." - date: 2026-10-18 by: Sn0wAlice versions: ["13"] environment: Proxmox VM, Debian 13 genericcloud image, kernel 6.12.113+deb13-cloud-amd64, auditd 1:4.0.2-2+deb13u1, BIOS boot notes: "Rules fail on fresh install; fix writes /etc/audit/rules.d/60-cirsec-scope.rules and loads it; rules match auditctl -l, kept after reboot; second run idempotent." introduced_in: 0.1.0 created: 2026-10-18 updated: 2026-10-18