Debian GNU/Linux · 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-DEB-AUDIT-004mediumactiveautomatedautomated fixprofile core

As released in v0.1.0 beta · pre-release. 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) 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-DEB-AUDIT-005).

On a fresh Debian 12 or 13 cloud image, dpkg.log, faillog and, on Debian 12, cloud-init.log are 0644. 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*dpkg.log*, alternatives.log*dpkg.log*, alternatives.log*dpkg.log*, alternatives.log*dpkg.log*, alternatives.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-18 by Sn0wAlice on 12, Proxmox VM, Debian 12 genericcloud image, kernel 6.1.0-54-cloud-amd64, BIOS boot. Fails on fresh install (dpkg.log, faillog, cloud-init.log 0644); fix restricts them; passes after AIDE install and reboot.
Verified2026-10-18 by Sn0wAlice on 13, Proxmox VM, Debian 13 genericcloud image, kernel 6.12.113+deb13-cloud-amd64, BIOS boot. Fails on fresh install (dpkg.log 0644); fix restricts it; passes after AIDE install and reboot.
Introduced inv0.1.0
Created, updated2026-10-18, 2026-10-18
Translationsfr