Skip to content

ExecutionLogsUser activity

sudo Logs: Linux Privilege Use Records

How sudo records who ran what as root on Linux: syslog and journal lines, optional log files and I/O session recordings, plus sudoers policy files.

Location
/var/log/auth.log, /var/log/secure
Proves
Which account ran which command as which target user, from which terminal and directory, and failed attempts
Timestamps
Syslog/journal time of the host (see syslog formats); I/O logs keep relative timing per session
Access
root (or adm group for auth.log on Debian/Ubuntu)
Retention
Follows auth.log/secure rotation and journal limits; I/O logs until deleted
Collection
UAC, Velociraptor, cp -a, journalctl

What it is

sudo's sudoers policy plugin logs every accepted and rejected request. By default it sends one line per event to syslog, using the authpriv facility where available (priority notice for allowed, alert for denied). Those lines land in the authentication text log and in the journal. Optional settings add a dedicated log file, JSON output, exit status, logging of sub-commands, and full keystroke and screen recordings of sessions.

The policy itself (/etc/sudoers and its include directories) is also evidence: an attacker who adds a NOPASSWD rule has created persistence and removed the password prompt that would otherwise show up as an authentication event.

Where it lives

ItemDebian / UbuntuRHEL / FedoraNotes
Syslog lines/var/log/auth.log/var/log/securePlus the journal (SYSLOG_IDENTIFIER=sudo)
Policy/etc/sudoers, /etc/sudoers.d/*same@includedir/#includedir; files containing . or ending in ~ are skipped
Optional log fileDefaults logfile=... (off by default)sameAny path, for example /var/log/sudo.log
I/O session logs/var/log/sudo-io/sameOnly with log_input/log_output
Credential cache/run/sudo/ts/<user>/run/sudo/ts/ or /var/run/sudo/ts/Cleared at boot
Lecture status/var/lib/sudo/lectured/<user>/var/db/sudo/lectured/ or /var/lib/sudo/lectured/Zero-length file per user, depends on build
Audit recordsUSER_CMD in audit.logsameWhen sudo is built with Linux audit support and auditd runs
First-use marker~/.sudo_as_admin_successful (Ubuntu)noneCreated on first successful sudo

What it proves

  • The invoking account, target user (USER=), terminal, working directory and full command line of each allowed command.
  • Denials: user NOT in sudoers, user NOT authorized on host, command not allowed, N incorrect password attempts, a password is required.
  • PAM context around it: pam_unix(sudo:session): session opened for user root(uid=0) by deploy(uid=1001) and pam_unix(sudo:auth): authentication failure.
  • With I/O logging: exactly what was typed and displayed, replayable.
  • It does not show what happened inside sudo -i, sudo -s or sudo bash: the log records only the shell. Use auditd (auid), shell history, log_subcmds or I/O logs for that.
  • A user with root can edit these logs, and anyone can inject look-alike lines with logger.

Key fields

Accepted command, sudo log format:

Sep 20 03:15:30 web-prod-03 sudo:   deploy : TTY=pts/0 ; PWD=/home/deploy ; USER=root ; COMMAND=/usr/bin/bash
Sep 20 03:16:02 web-prod-03 sudo:   deploy : TTY=pts/0 ; PWD=/tmp ; USER=root ; TSID=000001 ; COMMAND=/usr/bin/tar -xf /tmp/x.tar
Sep 20 03:17:44 web-prod-03 sudo:   intern : user NOT in sudoers ; TTY=pts/1 ; PWD=/home/intern ; USER=root ; COMMAND=/usr/bin/id
FieldMeaning
user before :Login name of the user who ran sudo
denial reasonPresent only for rejected requests
TTY=Terminal, or unknown without a tty (scripts, some remote commands)
PWD=Working directory when sudo ran
USER= / GROUP=Target user and optional group
CHROOT=Root directory if one was requested
TSID=I/O log ID, present only when I/O logging is on
ENV=Environment variables set on the command line
COMMAND=Resolved command path and arguments

Control characters are logged in octal with a leading # (#011 for tab), and spaces in the command path appear as #040. With log_format=json the file log holds JSON objects with the full user details and environment.

Audit record for the same action (RHEL family):

type=USER_CMD msg=audit(1789874130.201:8830): pid=4302 uid=1001 auid=1001 ses=12 msg='cwd="/home/deploy" cmd="/usr/bin/bash" terminal=pts/0 res=success'

cmd and cwd are hex encoded when they contain spaces; ausearch -i decodes them.

Timestamps

Syslog lines inherit the syslog daemon's format: traditional local time without year on RHEL defaults, RFC 3339 with offset on Debian 12+ and Ubuntu 24.04 (see auth.log). The journal copy has a UTC microsecond timestamp and is the easier anchor. sudo's own log file uses a Mmm dd HH:MM:SS style date and adds the year only with log_year. I/O logs record the session start in the log/log.json file and relative delays in timing.

Retention

The syslog copy lives as long as auth.log/secure (about four weekly generations by default) and the journal copy as long as the journal's size limits allow. I/O logs are never rotated by sudo; the six-character base-36 session ID (00/00/01) wraps at maxseq, after which old sessions are overwritten. The lecture files and ~/.sudo_as_admin_successful persist until deleted.

Collection

E=/mnt/evidence
tar -C "$E" -cpf /cases/2026-017/sudo.tar \
  etc/sudoers etc/sudoers.d var/log/sudo-io var/lib/sudo var/db/sudo 2>/dev/null
journalctl -D "$E/var/log/journal" SYSLOG_IDENTIFIER=sudo -o json --utc > sudo-journal.json
zgrep -h 'sudo:' "$E"/var/log/auth.log* "$E"/var/log/secure* 2>/dev/null > sudo-lines.txt

UAC collects /var/log, /etc and the sudo lecture timestamps (sudo_lectured artifact). On a live system, sudo -l -U <user> shows the effective rights of an account without editing anything.

Parsing

# Allowed commands per invoking user
zgrep -h 'COMMAND=' auth.log* | sed -E 's/.*sudo: +([^ ]+) : .*USER=([^ ]+) ; .*COMMAND=(.*)/\1 -> \2 : \3/' | sort | uniq -c
# Failures
zgrep -hE 'sudo:.*(NOT in sudoers|not allowed|incorrect password)' auth.log*
# Replay a recorded session (read-only)
sudoreplay -d /cases/2026-017/var/log/sudo-io -l
sudoreplay -d /cases/2026-017/var/log/sudo-io 000001
# Audit copy
ausearch -if audit.log -m USER_CMD -i

Each I/O session directory holds log, log.json, timing, ttyin, ttyout, stdin, stdout and stderr. Plaso picks up sudo lines through its syslog parsers. Linux Log Parser reads auth.log / secure, syslog, journal files, audit.log and wtmp / btmp / lastlog in the browser and merges them into one timeline with rebuilt login sessions; nothing is uploaded.

Investigator tips

  • Review every file in /etc/sudoers.d/ and its mtime/ctime. New NOPASSWD: ALL entries, Defaults !syslog, !log_allowed or syslog_goodpri=none silence logging and are strong indicators.
  • COMMAND=/usr/bin/bash, /bin/su, editors, find, less, vi or interpreters mean the real activity happened in a child process; follow auid in audit.log and the account's shell history.
  • sudo success without a preceding pam_unix(sudo:auth) prompt is normal within timestamp_timeout (5 minutes by default) or with NOPASSWD; the files in /run/sudo/ts/ exist only on a live system.
  • The lecture file is created the first time sudo shows its lecture with a password prompt (default lecture=once). Its timestamps and Ubuntu's ~/.sudo_as_admin_successful give a first-use date for sudo per account, useful for newly created attacker accounts (see accounts).
  • Lines with TTY=unknown come from scripts, cron or non-interactive SSH; correlate with cron and sshd lines.
  • Compare text log, journal and audit copies: a sudo event in the journal but not in auth.log points to editing of the text file.

See also