Skip to content

auth.log and secure Forensics: SSH, sudo and su

Read /var/log/auth.log and /var/log/secure in an investigation: SSH brute force and logins, sudo and su root shells, password and account changes, time formats.

Published on 4 min read

TL;DR. auth.log (Debian, Ubuntu) and secure (RHEL family) are where rsyslog writes the auth and authpriv facilities: sshd, sudo, su, PAM, passwd, useradd, cron sessions. Group sshd lines by PID to rebuild each connection, count failures per source address, look for the first success after them, then follow the session into sudo. Identify the timestamp format before converting anything.

Which file, which format

DistributionAuthenticationEverything elseTimestamp
Ubuntu 24.04, Debian 12+/var/log/auth.log/var/log/syslogRFC 3339, microseconds, offset
Older Debian and Ubuntu/var/log/auth.log/var/log/syslogTraditional, local time, no year
RHEL, Rocky, Alma, Fedora/var/log/secure/var/log/messagesTraditional, local time, no year

The two formats side by side:

Sep 14 10:02:11 fin-jump-01 sshd[3071]: Accepted password for svc_backup from 203.0.113.45 port 51544 ssh2
2026-09-14T10:02:11.482113+00:00 fin-jump-01 sshd[3071]: Accepted password for svc_backup from 203.0.113.45 port 51544 ssh2

For the first form (RFC 3164 style), read the zone from /etc/localtime and infer the year from the file's modification time and rotation order. A file that spans New Year contains December lines followed by January lines; the January ones belong to the next year. Around daylight-saving changes, local times can repeat or skip an hour.

Debian 12 and some Fedora installs have no rsyslog at all. An absent auth.log is not proof of deletion; check the systemd journal.

SSH: rebuild each connection by PID

Every connection gets its own sshd process (on OpenSSH 9.8 and later, the per-connection process is sshd-session, so search for both names). All lines of one connection share that PID:

sshd[2381]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=198.51.100.23  user=svc_backup
sshd[2381]: Failed password for svc_backup from 198.51.100.23 port 40135 ssh2
sshd[2381]: Connection closed by authenticating user svc_backup 198.51.100.23 port 40135 [preauth]

Key messages:

MessageMeaning
Invalid user admin from IPAccount does not exist on the host
Failed password for [invalid user] X from IPWrong password (or nonexistent user)
Accepted password for X from IPPassword login succeeded
Accepted publickey for X from IP ... ED25519 SHA256:...Key login; the fingerprint identifies the key
pam_unix(sshd:session): session opened for user XSession start, same PID as the Accepted line
pam_unix(sshd:session): session closed for user XSession end, same PID
Connection closed by ... [preauth]Disconnected before authenticating

The pam_unix lines come from the pam_unix module; systemd-logind: New session 7 of user X follows within milliseconds and gives the session a number that also appears in the journal as session-7.scope.

Password guessing, then a success

The pattern that matters is not "many failures" (every internet-facing SSH server has those) but failures followed by a success:

  1. Count Failed password and Invalid user lines per source address and list the account names tried.
  2. Look for an Accepted line for any of those accounts after the last failure, from the same address or from another one. A different address minutes later is common: the guessing ran from one machine, the login from another.
  3. Check whether the successful method is password for an account that normally logs in with publickey. A service account that always used a key and suddenly uses a password is a strong lead.
  4. Compare the source address with the account's history. A login from an address never seen before for that account deserves a question to its owner.
zgrep -hE 'sshd(-session)?\[[0-9]+\]: (Failed password|Invalid user)' auth.log* | grep -oE 'from [0-9a-f.:]+' | sort | uniq -c | sort -rn
zgrep -hE 'sshd(-session)?\[[0-9]+\]: Accepted' auth.log*

Remember that on a host running both rsyslog and journald each line exists twice; counting the journal and auth.log together doubles the numbers. btmp holds a third copy of failed attempts.

sudo and su

sudo writes one line per command:

sudo:   svc_backup : TTY=pts/1 ; PWD=/home/svc_backup ; USER=root ; COMMAND=list
sudo:   svc_backup : TTY=pts/1 ; PWD=/home/svc_backup ; USER=root ; COMMAND=/bin/bash
sudo:   pam_unix(sudo-i:session): session opened for user root(uid=0) by svc_backup(uid=1001)
  • COMMAND=list is sudo -l: the user checking which rights they have. Often the first thing an intruder runs.
  • COMMAND=/bin/bash with the sudo-i PAM service is sudo -i, an interactive root shell. From that point, auth.log no longer sees individual commands; only commands run through sudo again are logged. Follow the session through auditd, where auid keeps the original user.
  • Failures: user NOT in sudoers, command not allowed, N incorrect password attempts, and pam_unix(sudo:auth): authentication failure.
  • su logs pam_unix(su:session): session opened for user root by X (or su-l for su -) and FAILED SU style messages on failure, depending on the distribution.

Spaces in sudo arguments are logged as-is, which makes some command lines ambiguous (/srv/finance/Q3 close is one argument or two?). The audit USER_CMD record hex-encodes such values and settles it.

Accounts and passwords

  • useradd[PID]: new user: name=..., groupadd, usermod and gpasswd lines for account changes.
  • passwd[PID]: pam_unix(passwd:chauthtok): password changed for X when a password is changed. An intruder changing the password of the account they came in with locks out the owner and keeps access.
  • chpasswd and chage for bulk and expiry changes.

Cron

CRON[PID]: pam_unix(cron:session): session opened for user X appears in auth.log for each job run; the command itself is in syslog (CRON[PID]: (X) CMD (...)), and a crontab edit shows as crontab[PID]: (root) REPLACE (X). A new user crontab installed during an interactive session is a persistence lead.

Doing it faster

Linux Log Parser reads auth.log, secure, syslog and messages in all three formats, including rotated and .gz files, rebuilds sessions from the sshd PID pairs and logind, marks lines that also exist in the journal, and reports password guessing followed by a success, logins from a new address, root SSH logins, sudo and su root shells, failed sudo and account changes. The investigation walkthrough shows these findings on a sample.

Reference tables: auth.log and syslog, sudo logs and SSH artifacts on linuxforensics.app.

Related articles

A worked Linux log investigation on a synthetic jump host: SSH password guessing, a login from a new IP, sudo -i, cron and systemd persistence, log tampering.
How the four Linux log families fit together in an investigation, what each one proves, where they disagree, and how to merge them into one timeline.
Reconstruct command lines from Linux audit.log: grouping records by event, EXECVE argument reassembly, hex-encoded arguments, auid and ses across sudo.