{
  "id": "CB-UBU-AUDIT-029",
  "standard": "ubuntu",
  "version": "0.1.2",
  "url": "https://baselines.cirsec.org/b/ubuntu/v0.1.2/CB-UBU-AUDIT-029",
  "json": "https://baselines.cirsec.org/b/ubuntu/v0.1.2/CB-UBU-AUDIT-029.json",
  "yaml": "https://baselines.cirsec.org/b/ubuntu/v0.1.2/CB-UBU-AUDIT-029.yml",
  "profiles_effective": [
    "server-hardened",
    "desktop-hardened"
  ],
  "license": "Text CC BY 4.0, code Apache-2.0",
  "attribution": "CIRSEC Baselines, https://baselines.cirsec.org",
  "control": {
    "id": "CB-UBU-AUDIT-029",
    "title": "Lock the audit configuration and load every valid rule",
    "finding": {
      "title": "The audit rules can be changed or disabled on the running system",
      "description": "Anyone with root can remove audit rules or turn auditing off without a reboot, and one bad rule stops the loading of all the rules after it."
    },
    "status": "active",
    "profiles": [
      "server-hardened",
      "desktop-hardened"
    ],
    "risk": {
      "severity": "medium"
    },
    "assessment": "automated",
    "tags": [
      "auditd"
    ],
    "description": "Three settings close the audit rule set:\n\n- `-c` at the start of the rules (`/etc/audit/rules.d/01-cirsec-initialize.rules`): if one rule\n  fails to load, `auditctl` reports it and carries on with the next ones;\n- `-e 2` as the last rule (`/etc/audit/rules.d/99-cirsec-finalize.rules`): once loaded, the\n  configuration is immutable, rules cannot be added or removed and auditing cannot be turned\n  off until the next reboot;\n- the compiled `/etc/audit/audit.rules` matches the files in `/etc/audit/rules.d/`\n  (`augenrules --check`), so what is on disk is what loads at boot.\n\nThe fix writes both files and loads the rules, which locks the configuration at once.\n",
    "rationale": "An intruder with root access first deletes the audit rules (`auditctl -D`) or stops auditing.\nWith an immutable configuration this needs a reboot, which is itself visible. `-c` keeps one\nwrong rule from silently dropping all the following ones.\n",
    "impact": "Changing the audit rules needs a reboot. Fixes of the rule controls CB-UBU-AUDIT-016 to 028 run\nafter this one has locked the configuration write their files and ask for a reboot.\n",
    "notes": "This control requires all the rule controls, so `remediate.sh` loads every rule before locking.\nThe check reports `enabled 2` only once the lock is loaded. While the configuration is locked,\n`augenrules` refuses to rebuild `/etc/audit/audit.rules`: after a rule file changes, the\n`rules-files` check fails until the next reboot, when auditd rebuilds and loads the rules.\n",
    "setting": {
      "location": "/etc/audit/rules.d/01-cirsec-initialize.rules, /etc/audit/rules.d/99-cirsec-finalize.rules",
      "default_value": "Not set (configuration can be changed at any time)",
      "recommended_value": "-c first, -e 2 last, audit.rules up to date"
    },
    "audit": {
      "manual": "1. Run `auditctl -s | grep enabled`. It must print `enabled 2`.\n2. Run `grep -hx -- '-c' /etc/audit/rules.d/*.rules`. It must print `-c`.\n3. Run `grep -v '^#' /etc/audit/audit.rules | grep . | tail -n 1`. It must print `-e 2`.\n4. Run `augenrules --check`. It must report no change.\n",
      "checks": [
        {
          "id": "immutable",
          "engine": "shell",
          "description": "Audit configuration locked in the kernel.",
          "spec": {
            "script": "command -v auditctl >/dev/null 2>&1 || { echo \"auditctl not found: auditd is not installed\"; exit 1; }\ns=$(auditctl -s 2>/dev/null | sed -n 's/^enabled //p')\necho \"enabled ${s:-unknown}\"\n[ \"$s\" = 2 ]\n"
          }
        },
        {
          "id": "rules-files",
          "engine": "shell",
          "description": "-c and -e 2 in the rules, compiled rules up to date.",
          "spec": {
            "script": "command -v augenrules >/dev/null 2>&1 || { echo \"augenrules not found: auditd is not installed\"; exit 1; }\nrc=0\nif grep -hqx -- '-c' /etc/audit/rules.d/*.rules 2>/dev/null; then echo \"-c set\"; else echo \"-c missing\"; rc=1; fi\nl=$(grep -v '^[[:space:]]*#' /etc/audit/audit.rules 2>/dev/null | grep . | tail -n 1)\necho \"last rule: ${l:-none}\"\n[ \"$l\" = \"-e 2\" ] || rc=1\no=$(augenrules --check 2>&1)\ncase $o in\n  *\"No change\"*) echo \"audit.rules matches rules.d\" ;;\n  *) echo \"audit.rules differs from rules.d: $o\"; rc=1 ;;\nesac\nexit \"$rc\"\n"
          }
        }
      ]
    },
    "remediation": {
      "manual": "1. Create `/etc/audit/rules.d/01-cirsec-initialize.rules` containing `-c`.\n2. Create `/etc/audit/rules.d/99-cirsec-finalize.rules` containing `-e 2`.\n3. Run `augenrules --load` once all the other rules are in place. The configuration is then\n   locked until the next reboot.\n",
      "effects": {
        "restart": "none",
        "disruption": "low",
        "lockout_risk": false
      },
      "rollback": "Delete `/etc/audit/rules.d/99-cirsec-finalize.rules` and `01-cirsec-initialize.rules`, run\n`augenrules` and reboot.\n",
      "scripts": [
        {
          "id": "finalize",
          "engine": "shell",
          "content": "command -v augenrules >/dev/null 2>&1 || { echo \"auditd is not installed\" >&2; exit 1; }\nfor x in 01-cirsec-initialize:-c '99-cirsec-finalize:-e 2'; do\n  f=/etc/audit/rules.d/${x%%:*}.rules\n  if [ \"$(grep -v '^#' \"$f\" 2>/dev/null)\" != \"${x#*:}\" ]; then\n    cb_backup \"$f\"\n    printf '%s\\n' '# Written by CIRSEC Baselines CB-UBU-AUDIT-029' \"${x#*:}\" >\"$f\"\n  fi\n  chmod 640 \"$f\"\ndone\nif auditctl -s | grep -q '^enabled 2'; then\n  echo \"audit rules are already locked: reboot to load changes\"\nelse\n  augenrules --load >/dev/null\nfi\n"
        }
      ]
    },
    "references": [
      {
        "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": "augenrules(8), Ubuntu manual pages",
        "url": "https://manpages.ubuntu.com/manpages/noble/man8/augenrules.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-9",
        "relation": "related"
      }
    ],
    "threats": [
      {
        "framework": "mitre-attack",
        "id": "T1562.012"
      }
    ],
    "related_controls": [
      {
        "id": "CB-UBU-AUDIT-011",
        "type": "requires"
      },
      {
        "id": "CB-UBU-AUDIT-016",
        "type": "requires"
      },
      {
        "id": "CB-UBU-AUDIT-017",
        "type": "requires"
      },
      {
        "id": "CB-UBU-AUDIT-018",
        "type": "requires"
      },
      {
        "id": "CB-UBU-AUDIT-019",
        "type": "requires"
      },
      {
        "id": "CB-UBU-AUDIT-020",
        "type": "requires"
      },
      {
        "id": "CB-UBU-AUDIT-021",
        "type": "requires"
      },
      {
        "id": "CB-UBU-AUDIT-022",
        "type": "requires"
      },
      {
        "id": "CB-UBU-AUDIT-023",
        "type": "requires"
      },
      {
        "id": "CB-UBU-AUDIT-024",
        "type": "requires"
      },
      {
        "id": "CB-UBU-AUDIT-025",
        "type": "requires"
      },
      {
        "id": "CB-UBU-AUDIT-026",
        "type": "requires"
      },
      {
        "id": "CB-UBU-AUDIT-027",
        "type": "requires"
      },
      {
        "id": "CB-UBU-AUDIT-028",
        "type": "requires"
      },
      {
        "id": "CB-UBU-AUDIT-036",
        "type": "requires"
      }
    ],
    "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 on stock image; after full remediation enabled 2, -c and -e 2 present, augenrules --check reports no change; locked again 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 on stock image; after full remediation enabled 2, -c and -e 2 present, augenrules --check reports no change; locked again 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 on stock image; after full remediation enabled 2, -c and -e 2 present, augenrules --check reports no change; locked again 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 on stock image; after full remediation enabled 2, -c and -e 2 present, augenrules --check reports no change; locked again after reboot."
      }
    ],
    "introduced_in": "0.1.0",
    "created": "2026-10-19",
    "updated": "2026-10-19"
  }
}