Detecting credential dumping on Linux endpoints
Linux credential dumping spans /proc/mem scraping, /etc/shadow theft and ptrace injection - here is what to log, what to detect, and why context matters.
Credential dumping on Linux isn’t one technique. It’s four or five, each targeting a different part of the credential store. MITRE ATT&CK groups them under T1003 (OS Credential Dumping), but the sub-techniques behave differently enough that a single rule set won’t catch all of them.
The main attack paths
| Technique | What it targets | MITRE ID |
|---|---|---|
/proc/PID/mem scraping |
In-memory credentials from sshd, sudo, PAM | T1003.007 |
/etc/shadow read or copy |
Password hashes for offline cracking | T1003.008 |
ptrace memory attachment |
Process memory from any running credential daemon | T1003.007 |
SSSD cache (/var/lib/sss/db/) |
Cached Active Directory credentials | T1003.006 |
Understanding which path fired tells you a lot about what comes next. /etc/shadow theft followed by silence is usually offline cracking - the attacker has what they need and is working elsewhere. ptrace on sshd or PAM suggests the host itself is the target and they want credentials that work right now, not hashes to crack later.
What telemetry you actually need
None of this is detectable without the right log sources. You need:
open()/openat()syscall auditing for sensitive paths:/etc/shadow,/etc/gshadow,/proc/*/mem,/proc/*/maps,/var/lib/sss/db/*ptrace()syscall logging - all calls, not just from unknown processes.gdband strace are legitimate, but legitimate ptrace use almost never targets sshd, sudo or polkit- Process tree context - who spawned the process that made the call? A
python3process opened from a reverse shell session that then reads/proc/1234/memis categorically different from a debugger started from a terminal
Linux audit daemon (auditd) covers the syscall layer. A minimal rule set to start with:
# Shadow and credential store access
-a always,exit -F arch=b64 -S open,openat -F path=/etc/shadow -F perm=r -k cred_shadow
-a always,exit -F arch=b64 -S open,openat -F path=/etc/gshadow -F perm=r -k cred_shadow
-a always,exit -F arch=b64 -S open,openat -F dir=/var/lib/sss/db -F perm=r -k cred_sssd
# ptrace - log all calls
-a always,exit -F arch=b64 -S ptrace -k ptrace_call
The raw audit log is not enough on its own. You need the process tree - executable path, parent PID, command line, session ID - to correlate the syscall with the context. That is the gap that auditd doesn’t fill and an EDR agent does.
A Sigma rule for /proc memory access
title: Suspicious /proc/PID/mem access
id: c4e1a9b2-0f3d-4a8e-9c5f-1b7d2e3a4f6c
status: experimental
description: >
Process opens another process's /proc/PID/mem or maps,
a technique used in T1003.007 memory scraping
logsource:
category: file_access
product: linux
detection:
selection:
EventType: 'open'
FilePath|re: '^/proc/[0-9]+/(mem|maps)$'
filter_debuggers:
ProcessName|in:
- 'gdb'
- 'strace'
- 'perf'
condition: selection and not filter_debuggers
falsepositives:
- Legitimate profiling tools accessing their own process
- Some JVM garbage collectors on older kernels
level: high
tags:
- attack.credential_access
- attack.t1003.007
The false positive list matters here. JVMs and some profiling tools do legitimately read /proc/self/maps. Filter by parent process and terminal session before escalating.
The /etc/shadow case is subtler
/etc/shadow has mode 640, owned by root:shadow. A read from a non-root process is an immediate alarm. A read from a root process is noisier - backup tools, configuration management, and some monitoring agents all need it legitimately.
The signal is in the context. What spawned the process? Was it an interactive session or a cron job? Is this host a bastion or a developer workstation? That context compresses a flood of “root opened /etc/shadow” events down to the two or three that deserve a ticket.
Baseline before you alert
Credential dumping detections fire frequently on misconfigured or overly broad rules. The mistake most teams make is tuning for false positive rate before they understand what legitimate looks like.
Baseline first:
- Log for a week without alerting
- Catalogue every process that legitimately touches your credential stores
- Build a per-host allowlist of expected callers
- Alert on deviation from that baseline, not on the raw event
The open rule set coverage for T1003 on Linux is solid - Sigma’s built-in rules cover most of these paths. The tuning work is still yours, and it cannot be skipped.
If you want to see how LightEDR handles process memory access and credential store events alongside the full process tree, get in touch.