Description
One auditd rule per setuid or setgid program found on the local file systems that allow
them (not mounted nosuid or noexec), key privileged, in
/etc/audit/rules.d/60-cirsec-privileged.rules. Each rule records every run of the program by a
user who logged in. The list is rebuilt from the file system each time the check or the fix runs.
The scan covers local file systems listed by findmnt --real. Programs on network file systems are not covered.
Snap images (squashfs mounts under /snap/) are skipped: they are read-only, replaced at each
snap refresh (which would make the check fail every time), and their setuid copies are not used
by the host. /usr/lib/snapd/snap-confine itself is on the root file system and is covered.
Rationale
passwd, su, sudo, mount, chsh and similar programs run as root on behalf of a user.
Recording each use shows who used them and is the first place to look after a privilege escalation.
Impact
Installing or removing a package that ships a setuid program makes the check fail until the fix runs again. Once the audit configuration is locked (CB-UBU-AUDIT-029), the new rule only loads at the next reboot.
Setting
| Location | /etc/audit/rules.d/60-cirsec-privileged.rules |
| Default | No audit rules |
| Recommended | Rules loaded (auditctl -l) and present in /etc/audit/rules.d/60-cirsec-privileged.rules |
Audit
- Run
auditctl -las root. It must list the rules shown below (keysprivileged). - 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:
-a always,exit -S all -F path=<program> -F perm=x -F auid>=1000 -F auid!=-1 -F key=privileged
Automated: every check must pass. Scanners report each check by its id.
rules
Rules loaded in the kernel and present in /etc/audit/rules.d.
script: |
command -v auditctl >/dev/null 2>&1 || { echo "auditctl not found: auditd is not installed"; exit 1; }
want() {
# every setuid or setgid file on local file systems mounted without nosuid or noexec, snaps excluded
for m in $(findmnt -rn --real -t nosquashfs -O nonosuid,nonoexec -o TARGET); do
find "$m" -xdev -type f \( -perm -4000 -o -perm -2000 \) 2>/dev/null
done | sort -u | while IFS= read -r p; do
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 <<EOF
$(want)
EOF
[ "$rc" = 1 ] || echo "$n rules loaded and present in /etc/audit/rules.d"
exit "$rc"
Remediation
- Write the expected rules to
/etc/audit/rules.d/60-cirsec-privileged.rules(mode 0640). - Run
augenrules --load. Ifauditctl -sshowsenabled 2, the configuration is locked: reboot to load the new rules.
| Restart | none |
| Disruption | none |
Rollback
Delete /etc/audit/rules.d/60-cirsec-privileged.rules and run augenrules --load (or reboot if the configuration is locked).
rules-file
command -v augenrules >/dev/null 2>&1 || { echo "auditd is not installed" >&2; exit 1; }
want() {
# every setuid or setgid file on local file systems mounted without nosuid or noexec, snaps excluded
for m in $(findmnt -rn --real -t nosquashfs -O nonosuid,nonoexec -o TARGET); do
find "$m" -xdev -type f \( -perm -4000 -o -perm -2000 \) 2>/dev/null
done | sort -u | while IFS= read -r p; do
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-privileged.rules
t=$(mktemp)
{ echo '# Written by CIRSEC Baselines CB-UBU-AUDIT-026'; 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
Handwritten code reads parameters from CB_<NAME> environment variables. Each release turns these fixes into remediate.sh and an Ansible role per profile: dry run by default, a fix runs only when its check fails.
References
- audit.rules(7), Ubuntu manual pages Canonical, vendor-doc, accessed 2026-10-19
- auditctl(8), Ubuntu manual pages Canonical, vendor-doc, accessed 2026-10-19
- ANSSI-BP-028 v2.0 - Recommandations de configuration d'un système GNU/Linux (R73) ANSSI, guide, accessed 2026-10-19
Mappings
| Framework | ID | Relation |
|---|---|---|
| ANSSI-BP-028 - Recommandations de configuration d'un système GNU/Linux2.0 | R33 | partial |
| ANSSI-BP-028 - Recommandations de configuration d'un système GNU/Linux2.0 | R73 | partial |
| NIST SP 800-53 Rev. 55.1.1 | AU-12 | related |
| NIST SP 800-53 Rev. 55.1.1 | AC-6(9) | related |
How this control relates to the other framework's: equivalent, stricter, looser, partial or related.
Threats mitigated
| Taxonomy | ID |
|---|---|
| MITRE ATT&CK | T1548.001 |
Related controls
- requires
CB-UBU-AUDIT-011Install and run the audit daemon - related
CB-UBU-AUDIT-029Lock the audit configuration and load every valid rule
People and lifecycle
| Authors |
|
| Verified | 2026-10-19 by Sn0wAlice on 20.04, Proxmox VM, Ubuntu 20.04 cloud image, kernel 5.4.0-216-generic. Fails after auditd install; rules written and loaded (augenrules), all present in auditctl -l with auditd 2.8.5; passes after reboot with enabled 2. Snap squashfs mounts skipped. |
| Verified | 2026-10-19 by Sn0wAlice on 22.04, Proxmox VM, Ubuntu 22.04 cloud image, kernel 5.15.0-198-generic. Fails after auditd install; rules written and loaded (augenrules), all present in auditctl -l with auditd 3.0.7; passes after reboot with enabled 2. Snap squashfs mounts skipped. |
| Verified | 2026-10-19 by Sn0wAlice on 24.04, Proxmox VM, Ubuntu 24.04 cloud image, kernel 6.8.0-147-generic. Fails after auditd install; rules written and loaded (augenrules), all present in auditctl -l with auditd 3.1.2; passes after reboot with enabled 2. Snap squashfs mounts skipped. |
| Verified | 2026-10-19 by Sn0wAlice on 26.04, Proxmox VM, Ubuntu 26.04 cloud image, kernel 7.0.0-38-generic. Fails after auditd install; rules written and loaded (augenrules), all present in auditctl -l with auditd 4.1.2; passes after reboot with enabled 2. Snap squashfs mounts skipped. |
| Introduced in | v0.1.0 |
| Created, updated | 2026-10-19, 2026-10-19 |
| Translations | fr |