# yaml-language-server: $schema=../../../../schema/control.schema.json id: CB-UBU-AUDIT-036 title: Audit administrative commands that are not setuid finding: title: Use of administrative commands is not recorded description: Commands that partition disks, load AppArmor profiles, create accounts or hold SSH keys run without a record of who used them. status: active profiles: [server-hardened, desktop-hardened] risk: severity: medium assessment: automated tags: [auditd, privileged] description: | Some administrative commands are not setuid or setgid, so CB-UBU-AUDIT-026 does not cover them, yet their use matters in an investigation. This control adds one auditd rule per command in `{{ commands }}`, key `privileged`, in `/etc/audit/rules.d/60-cirsec-admin-cmds.rules`. Each rule records every run of the program by a user who logged in. By default: - `fdisk`: changes to disk partitions; - `apparmor_parser`: loading, replacing or removing AppArmor profiles; - `useradd`: account creation; - `ssh-agent`: an agent that holds private keys for the session; - `unix_update`: the PAM helper that changes local passwords. Each command is looked up in `/usr/sbin`, `/usr/bin`, `/sbin` and `/bin`, and its real path is used. Commands that are not installed are skipped, and so are setuid or setgid ones, which CB-UBU-AUDIT-026 already audits (`ssh-agent` is setgid on Ubuntu 20.04 and 22.04). rationale: | Repartitioning a disk, unloading an AppArmor profile, creating a back-door account or reusing a forwarded SSH agent are steps of an intrusion that leave no other trace. Recording each run, with the identity of the person who logged in, keeps them attributable. impact: | Few records: these commands are rarely run. Once the audit configuration is locked (CB-UBU-AUDIT-029), a changed rule only loads at the next reboot. notes: | `ssh-agent` is started at each graphical login on desktops, which adds one record per session. setting: location: /etc/audit/rules.d/60-cirsec-admin-cmds.rules default_value: No audit rules recommended_value: "Rules loaded (auditctl -l) and present in /etc/audit/rules.d/60-cirsec-admin-cmds.rules" parameters: - name: commands type: list description: Names of the administrative commands to audit, looked up in /usr/sbin, /usr/bin, /sbin and /bin. default: [fdisk, apparmor_parser, useradd, ssh-agent, unix_update] audit: manual: | 1. For each command, find its real path with `readlink -f /usr/sbin/` (or `/usr/bin/`), and skip it if `stat -c %A` shows an `s` (CB-UBU-AUDIT-026 covers it). 2. Run `auditctl -l` as root. It must list, for each remaining command: ``` -a always,exit -S all -F path= -F perm=x -F auid>=1000 -F auid!=-1 -F key=privileged ``` 3. Run `grep -h . /etc/audit/rules.d/*.rules`. The same rules must be present, so they load at boot. 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() { for c in $CB_COMMANDS; do for d in /usr/sbin /usr/bin /sbin /bin; do [ -f "$d/$c" ] && { readlink -f "$d/$c"; break; } done done | sort -u | while IFS= read -r p; do # setuid and setgid programs are audited by CB-UBU-AUDIT-026 [ -u "$p" ] || [ -g "$p" ] || echo "-a always,exit -S all -F path=$p -F perm=x -F auid>=1000 -F auid!=-1 -F key=privileged" done } 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() { for c in $CB_COMMANDS; do for d in /usr/sbin /usr/bin /sbin /bin; do [ -f "$d/$c" ] && { readlink -f "$d/$c"; break; } done done | sort -u | while IFS= read -r p; do # setuid and setgid programs are audited by CB-UBU-AUDIT-026 [ -u "$p" ] || [ -g "$p" ] || echo "-a always,exit -S all -F path=$p -F perm=x -F auid>=1000 -F auid!=-1 -F key=privileged" done } f=/etc/audit/rules.d/60-cirsec-admin-cmds.rules t=$(mktemp) { echo '# Written by CIRSEC Baselines CB-UBU-AUDIT-036'; 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), Ubuntu manual pages url: https://manpages.ubuntu.com/manpages/noble/man7/audit.rules.7.html publisher: Canonical kind: vendor-doc accessed: 2026-10-19 - title: auditctl(8), Ubuntu manual pages url: https://manpages.ubuntu.com/manpages/noble/man8/auditctl.8.html publisher: Canonical kind: vendor-doc accessed: 2026-10-19 - 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-19 mappings: - 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 threats: - framework: mitre-attack id: T1136.001 - framework: mitre-attack id: T1562.001 - framework: mitre-attack id: T1563.001 related_controls: - id: CB-UBU-AUDIT-011 type: requires - id: CB-UBU-AUDIT-026 type: related - id: CB-UBU-AUDIT-029 type: related authors: - name: Alice github: Sn0wAlice verified: - date: 2026-10-19 by: Sn0wAlice versions: ["20.04"] environment: Proxmox VM, Ubuntu 20.04 cloud image, kernel 5.4.0-216-generic notes: "Fails after auditd install; 4 rules written (ssh-agent setgid, left to AUDIT-026), loaded and locked; passes after reboot." - date: 2026-10-19 by: Sn0wAlice versions: ["22.04"] environment: Proxmox VM, Ubuntu 22.04 cloud image, kernel 5.15.0-198-generic notes: "Fails after auditd install; 4 rules written (ssh-agent setgid, left to AUDIT-026), loaded and locked; passes after reboot." - date: 2026-10-19 by: Sn0wAlice versions: ["24.04"] environment: Proxmox VM, Ubuntu 24.04 cloud image, kernel 6.8.0-147-generic notes: "Fails after auditd install; 4 rules written (ssh-agent setgid, left to AUDIT-026), loaded and locked; passes after reboot." - date: 2026-10-19 by: Sn0wAlice versions: ["26.04"] environment: Proxmox VM, Ubuntu 26.04 cloud image, kernel 7.0.0-38-generic notes: "Fails after auditd install; 4 rules written (ssh-agent setgid, left to AUDIT-026), loaded and locked; passes after reboot." introduced_in: 0.1.0 created: 2026-10-19 updated: 2026-10-19