Ubuntu · Logging & auditing

Restrict access to log files

When it fails: Log files are readable or writable by too many users. Logs hold user names, addresses, commands and sometimes secrets; files readable by everyone leak them, and writable files can be falsified.

CB-UBU-AUDIT-004mediumactiveautomatedautomated fixprofile core

As released in v0.1.2 (beta). Current state.

Description

Every regular file under /var/log/, including the journal files in /var/log/journal/, must have no permission for other users, no write permission for its group and no execute bit (mode 0640 or stricter).

Two exceptions:

  • the session records wtmp, btmp and lastlog (and their rotated copies) must stay writable by the utmp group, and wtmp and lastlog readable by everyone for last and lastlog to work: for them only execute bits and writes by other users are forbidden (mode 0664 or stricter);
  • the package manager logs in /var/log/apt/, which apt recreates readable by everyone at each run, may be 0644;
  • the files matching tolerated_0644 (by default dpkg.log* and alternatives.log*, which logrotate recreates with create 0644, and the daily sysstat data files sa?? and sar??, which sadc creates readable by everyone) may be 0644 too. They must never be writable by group or others.

journald creates its files with mode 0640 (set in /usr/lib/tmpfiles.d/systemd.conf), and rsyslog with $FileCreateMode (CB-UBU-AUDIT-005).

On a fresh Ubuntu cloud image, dpkg.log, alternatives.log, the files of /var/log/apt/ and unattended-upgrades/unattended-upgrades-shutdown.log are 0644, and on Ubuntu 20.04 also ubuntu-advantage.log and the dmesg files, and from 24.04 the sysstat files of /var/log/sysstat/. A file recreated by its program or by logrotate with a create 0644 directive goes back to the wider mode until the fix runs again: list such files in tolerated_0644, or change the create mode in /etc/logrotate.d/.

Rationale

Logs record failed logins (sometimes with a password typed in the user name field), source addresses, commands and application data. Readable logs help an attacker map the system; writable logs let them erase or forge their traces.

Impact

Users who are not in the adm group can no longer read files such as /var/log/cloud-init.log. Grant access with group membership (adm) instead of wider modes.

Setting

Location/var/log/
DefaultSeveral files 0644
Recommended0640 or stricter; 0664 for wtmp, btmp and lastlog; 0644 in /var/log/apt and for {{ tolerated_0644 }}

Parameters

ParameterCoreServerServer hardenedDesktopDesktop hardenedBounds
tolerated_0644list. File name patterns under /var/log allowed to be 0644 (never group or world writable).dpkg.log*, alternatives.log*, sa[0-9][0-9], sar[0-9][0-9], Xorg.*.log*dpkg.log*, alternatives.log*, sa[0-9][0-9], sar[0-9][0-9], Xorg.*.log*dpkg.log*, alternatives.log*, sa[0-9][0-9], sar[0-9][0-9], Xorg.*.log*dpkg.log*, alternatives.log*, sa[0-9][0-9], sar[0-9][0-9], Xorg.*.log*dpkg.log*, alternatives.log*, sa[0-9][0-9], sar[0-9][0-9], Xorg.*.log*

The value used is your override (tailoring file), else the profile's, else the one of the profile it extends, else the default. Bounds limit what an override may set.

Audit

Run, as root:

find /var/log -type f ! -path '/var/log/apt/*' ! -name 'wtmp*' ! -name 'btmp*' ! -name 'lastlog*' -perm /0137 -ls
find /var/log -type f \( -name 'wtmp*' -o -name 'btmp*' -o -name 'lastlog*' \) -perm /0113 -ls
find /var/log/apt -type f -perm /0133 -ls

The commands must print nothing, except files matching {{ tolerated_0644 }} reported by the first command with mode 0644 (they must not be writable by group or others).

Automated: every check must pass. Scanners report each check by its id.

var-log

Files under /var/log with more access than allowed.

script: |
  [ -d /var/log ] || exit 2
  set -f
  ex= tol=
  for p in $CB_TOLERATED_0644; do ex="$ex ! -name $p"; tol="$tol -o -name $p"; done
  bad=$( { find /var/log -type f ! -path '/var/log/apt/*' ! -name 'wtmp*' ! -name 'btmp*' ! -name 'lastlog*' $ex -perm /0137
    find /var/log -type f \( -name 'wtmp*' -o -name 'btmp*' -o -name 'lastlog*' \) -perm /0113
    find /var/log/apt -type f -perm /0133
    [ -z "$tol" ] || find /var/log -type f \( ${tol# -o } \) -perm /0133; } 2>/dev/null)
  set +f
  if [ -n "$bad" ]; then
    printf '%s\n' "$bad" | while IFS= read -r f; do stat -c '%n %a' "$f"; done
    exit 1
  fi
  echo "no log file under /var/log is more permissive than allowed"

Remediation

Run, as root:

find /var/log -type f ! -path '/var/log/apt/*' ! -name 'wtmp*' ! -name 'btmp*' ! -name 'lastlog*' -perm /0137 -exec chmod u-x,g-wx,o-rwx {} +
find /var/log -type f \( -name 'wtmp*' -o -name 'btmp*' -o -name 'lastlog*' \) -perm /0113 -exec chmod u-x,g-x,o-wx {} +
find /var/log/apt -type f -perm /0133 -exec chmod u-x,g-wx,o-wx {} +

For files rotated by logrotate, also change the create mode in the matching /etc/logrotate.d/ file.

Restartnone
Disruptionlow

Rollback

Run chmod 644 on the files that need to be readable by everyone again.

chmod

set -f
ex= tol=
for p in $CB_TOLERATED_0644; do ex="$ex ! -name $p"; tol="$tol -o -name $p"; done
find /var/log -type f ! -path '/var/log/apt/*' ! -name 'wtmp*' ! -name 'btmp*' ! -name 'lastlog*' $ex -perm /0137 -exec chmod u-x,g-wx,o-rwx {} +
find /var/log -type f \( -name 'wtmp*' -o -name 'btmp*' -o -name 'lastlog*' \) -perm /0113 -exec chmod u-x,g-x,o-wx {} +
find /var/log/apt -type f -perm /0133 -exec chmod u-x,g-wx,o-wx {} +
[ -z "$tol" ] || find /var/log -type f \( ${tol# -o } \) -perm /0133 -exec chmod u-x,g-wx,o-wx {} +
set +f

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

Mappings

FrameworkIDRelationNote
ANSSI-BP-028 - Recommandations de configuration d'un système GNU/Linux2.0R71partialR71 asks for protected logs; this control covers local file permissions.
NIST SP 800-53 Rev. 55.1.1AU-9related

How this control relates to the other framework's: equivalent, stricter, looser, partial or related.

Threats mitigated

People and lifecycle

Authors
Verified2026-10-19 by Sn0wAlice on 20.04, Proxmox VM, Ubuntu 20.04 cloud image, kernel 5.4.0-216-generic. Fails on stock image (ubuntu-advantage.log, dmesg*, unattended-upgrades-shutdown.log 0644); fix chmods, passes after reboot.
Verified2026-10-19 by Sn0wAlice on 22.04, Proxmox VM, Ubuntu 22.04 cloud image, kernel 5.15.0-198-generic. Fails on stock image (unattended-upgrades-shutdown.log 0644); fix chmods, passes after reboot.
Verified2026-10-19 by Sn0wAlice on 24.04, Proxmox VM, Ubuntu 24.04 cloud image, kernel 6.8.0-147-generic. Fails on stock image (sysstat sa file, unattended-upgrades-shutdown.log 0644); fix chmods, passes after reboot; sa?? now tolerated.
Verified2026-10-19 by Sn0wAlice on 26.04, Proxmox VM, Ubuntu 26.04 cloud image, kernel 7.0.0-38-generic. Fails on stock image (sysstat sa file, unattended-upgrades-shutdown.log 0644); fix chmods, passes after reboot; sa?? now tolerated.
Introduced inv0.1.0
Created, updated2026-10-19, 2026-10-19
Translationsfr