skip to content

An authorized_keys entry's mtime is 40 days old but auditd retains 14 days — how do you set your lookback window?

level: middleimportance: should knowfreq 52%

answer

  1. one file, many key lines, one mtime
  2. mtime dates the file's last write
  3. a watch rule had to exist first
  4. each source has its own horizon
  5. sshd auth lines carry the key fingerprint

basics

~20 s

Set the window per source, not once for the case. auditd answers only its 14 days; reach further with config-management history, archived sshd authentication logs, bastion logs and host backups, and record whatever stays unreachable as a stated gap.

solid answer

~50 s

There is no single lookback window — each source has its own horizon, so I set one per source and state the union. `auditd` covers 14 days and only for paths a watch rule was actually configured for, so it may hold nothing about this file at all. Sources that outlive it: configuration-management run history and the config repository's git log, centrally shipped `sshd` authentication records (the `Accepted publickey` lines carry the key fingerprint, so I can search for uses of *this* key), bastion or VPN session logs, and host backups or snapshots of `~/.ssh`. On the mtime itself I am careful: it dates the last write to the *file*, which holds several key lines, so it tells me the key existed by then, not that it was added then. Whatever period no source can cover becomes a written gap in the case, not a blocker.

code

text · 3 lines
text
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH8k... deploy@build01
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC7v...
...

go deeper

for a junior

Know that logs expire and that a file's timestamp is not a reliable creation date. Be able to say which other sources might reach further back rather than concluding the question is unanswerable.

for a middle

Explain the mechanics: one mtime for a multi-line file, auditd recording only what a rule watches, rotation by size, and retention not being retroactive. Name two or three longer-horizon sources.

for a senior

Show that you set a window per source and turn the uncovered period into an explicit, bounded statement the case can carry, rather than either guessing a date or declaring the whole question unknowable.

for a principal

Be ready to argue what the retention gap costs the organisation and where the money should go — which sources deserve longer horizons for investigations of this shape, and which do not.

## Why the time axis is the one that breaks Hosts and accounts you can enumerate on demand. "Since when" is answerable only if something wrote it down and kept it, and retention is decided months before your investigation by someone optimising storage. This is the axis where scoping runs into a wall, and the interview question is what you do at the wall. ## What the file's mtime actually says `authorized_keys` is **one file containing many key lines**. The filesystem stores one modification time for the file, not a timestamp per line. So a 40-day-old mtime supports one claim: the file was last written 40 days ago, and therefore every line currently in it existed by that date. It does **not** say the unexplained key was added on that date — if a second key was appended later, the mtime belongs to the later write and the suspicious key is older still. Two more caveats worth knowing: - `mtime` can be set to an arbitrary value by anyone who can write the file, so it is attacker-controllable. - Setting `mtime` backwards updates `ctime` (the inode-change time) to the present, so a `ctime` far newer than `mtime` is itself an oddity worth noting. Treat the timestamp as a hypothesis to corroborate off the host, not as a fact to build on. ## What auditd can and cannot cover `auditd` records syscalls and file accesses **only where a rule told it to** — a watch on the path, or a syscall rule. If nobody configured a watch on `/home/*/.ssh/authorized_keys`, the 14 days you do have contain nothing about the file being written, and that is a configuration fact, not evidence about the adversary. On top of that, its on-disk logs rotate by size and file count, so "14 days" is itself an estimate that shortens on a noisy host. The common wrong move is to raise the retention setting and re-run the query. Retention is not retroactive: rotated logs are gone, and changing the config helps the *next* investigation. ## Sources that outlive auditd The productive answer is to stop treating the case as having one window and start listing sources by horizon: | Source | What it can answer here | | --- | --- | | Config-management run history / config repo git log | Whether the key was deployed by automation, by which commit and when — git history is effectively permanent | | Central `sshd` authentication logs | `Accepted publickey for <user> from <ip> ... SHA256:<fingerprint>` — searchable by *this key's* fingerprint, often retained far longer than host audit logs | | Bastion / jump-host session logs | Whether anyone reached the host at all in a period, and from where | | Identity-provider or VPN sign-in logs | Which human sessions existed around a candidate window | | Host backups or snapshots | Whether the key was present in a snapshot from before the retention edge — a cheap binary search on the date | | Network flow records | That bytes moved between two addresses; flow carries no payload, so never what they were | The backup search is the underrated one: if last quarter's snapshot of `~/.ssh` already contains the key, "since when" just got answered from outside the log estate entirely. ## Direction of the claims An `Accepted publickey` line proves the key was **accepted**, not who held the private half. The absence of such a line within the retained window proves only that no retained record shows it; it is not evidence the key was never used. Encoding that inversion into a case note is how a scoping gap silently becomes a conclusion. ## Writing the gap down The output of this axis is usually a bounded statement rather than a date: *the key existed by \<mtime\>; usage is verifiable from \<retention edge\> forward, where none was seen; the period before that is not covered by any available source.* That sentence is what the rest of the investigation, and any later decision to close, has to work from — and it also tells you where **not** to spend more hours, because no amount of extra effort makes a rotated log come back.

  • How do the sshd authentication logs help beyond auditd's horizon?
    An accepted public-key authentication is logged with the key's SHA256 fingerprint and the source address. If those logs are shipped centrally with longer retention, you can search for uses of this specific key across the fleet and further back. It proves the credential was accepted, not who presented it.
  • The file's ctime is today but the mtime is 40 days ago — what does that suggest?
    Setting a modification time backwards updates ctime to the current time, so this pattern is consistent with the timestamp having been altered. Do not treat it as proof, but stop leaning on the mtime and corroborate the date from sources off the host, such as backups or config history.
  • Would raising auditd retention now help this case?
    No. Retention is not retroactive — rotated records are gone, and the new setting only helps the next investigation. Note it as a follow-up action rather than a step in this one, and spend the time on sources that still hold the period you need.

saying these in an interview costs you the question

  • Treats the file's mtime as the date the key was added
  • Assumes auditd logged the file write without a watch rule
  • Raises retention and expects the missing days to reappear
  • Applies one lookback window to every log source
  • Reads the absence of an auditd record as proof the key was unused

context