# yaml-language-server: $schema=../../../../schema/control.schema.json id: CB-UBU-AUDIT-023 title: Audit file deletions and renames by users finding: title: File deletions and renames by users are not recorded description: Evidence and data can be deleted or moved without a record. status: active profiles: [server-hardened, desktop-hardened] risk: severity: low assessment: automated tags: [auditd, files] description: | auditd rules in `/etc/audit/rules.d/60-cirsec-delete.rules`, key `delete`: `unlink`, `unlinkat`, `rename`, `renameat`, `renameat2` and `rmdir` called by users who logged in, 64-bit and 32-bit programs. rationale: | Deleting files is how an intruder removes tools and traces, and how data gets destroyed. The records keep the name of each deleted or renamed file and the user who did it. impact: | Interactive users produce many `delete` records (editors save through a rename, builds remove temporary files). Size the audit logs accordingly. setting: location: /etc/audit/rules.d/60-cirsec-delete.rules default_value: No audit rules recommended_value: "Rules loaded (auditctl -l) and present in /etc/audit/rules.d/60-cirsec-delete.rules" audit: manual: | 1. Run `auditctl -l` as root. It must list the rules shown below (keys `delete`). 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: ``` -a always,exit -F arch=b64 -S rename,rmdir,unlink,unlinkat,renameat,renameat2 -F auid>=1000 -F auid!=-1 -F key=delete -a always,exit -F arch=b32 -S unlink,rename,rmdir,unlinkat,renameat,renameat2 -F auid>=1000 -F auid!=-1 -F key=delete ``` 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' -a always,exit -F arch=b64 -S rename,rmdir,unlink,unlinkat,renameat,renameat2 -F auid>=1000 -F auid!=-1 -F key=delete -a always,exit -F arch=b32 -S unlink,rename,rmdir,unlinkat,renameat,renameat2 -F auid>=1000 -F auid!=-1 -F key=delete RULES } 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' -a always,exit -F arch=b64 -S rename,rmdir,unlink,unlinkat,renameat,renameat2 -F auid>=1000 -F auid!=-1 -F key=delete -a always,exit -F arch=b32 -S unlink,rename,rmdir,unlinkat,renameat,renameat2 -F auid>=1000 -F auid!=-1 -F key=delete RULES } f=/etc/audit/rules.d/60-cirsec-delete.rules t=$(mktemp) { echo '# Written by CIRSEC Baselines CB-UBU-AUDIT-023'; 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: cis-ubuntu-2004 framework_version: "3.0.0" id: "6.3.3.13" relation: equivalent - framework: cis-ubuntu-2204 framework_version: "3.0.0" id: "6.2.3.13" relation: equivalent - framework: cis-ubuntu-2404 framework_version: "2.0.0" id: "6.2.3.22" relation: equivalent - framework: cis-ubuntu-2604 framework_version: "1.0.0" id: "6.2.3.24" relation: equivalent - framework: cis-ubuntu-2604 framework_version: "1.0.0" id: "6.2.3.25" relation: equivalent threats: - framework: mitre-attack id: T1070.004 - framework: mitre-attack id: T1485 related_controls: - id: CB-UBU-AUDIT-011 type: requires - 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; rules written and loaded (augenrules), all present in auditctl -l with auditd 2.8.5; passes after reboot with enabled 2." - 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; rules written and loaded (augenrules), all present in auditctl -l with auditd 3.0.7; passes after reboot with enabled 2." - 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; rules written and loaded (augenrules), all present in auditctl -l with auditd 3.1.2; passes after reboot with enabled 2." - 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; rules written and loaded (augenrules), all present in auditctl -l with auditd 4.1.2; passes after reboot with enabled 2." introduced_in: 0.1.0 created: 2026-10-19 updated: 2026-10-19