Passwords or SSH keys leaked: rotate everything, in order

Updated November 2026

Assume a leaked secret has already been used. Change credentials from the most powerful to the least powerful, and work from a computer you trust. Remove the old secret everywhere before you look for damage, so that an attacker can't come back in while you investigate.

Do this first.

  1. Use a clean device. If the leak came from your laptop (malware, a stolen disk), don't create new keys or passwords on it.
  2. Change root and all admin passwords, and remove any SSH key you don't trust from every authorized_keys file.
  3. Revoke leaked API tokens and cloud access keys in the provider's dashboard. Revoking stops them working at once.
  4. Keep the logs. Don't delete or reinstall anything until you have checked for misuse (see below).

Symptoms

1. Root and admin accounts

Set new, unique passwords for root and every user with sudo rights. Lock accounts nobody should be using. Locking the password alone does not stop SSH key logins, so also set the expiry date:

sudo passwd root
sudo passwd alice
awk -F: '$3 == 0 {print $1}' /etc/passwd     # every UID 0 account; should be only root
getent group sudo wheel                      # who can use sudo
sudo ls -la /etc/sudoers.d/
sudo usermod -L --expiredate 1 olduser       # lock password AND block key logins
sudo loginctl list-sessions                  # active sessions

End sessions that aren't yours with sudo loginctl terminate-session ID.

2. SSH keys and authorized_keys

On your clean device, create a new key with a passphrase: ssh-keygen -t ed25519 -C "alice 2026-11". Then audit every authorized_keys file on every server, not only your own. As root:

sudo sshd -T | grep -iE '^authorizedkeys(file|command)'
sudo bash -c 'for h in $(getent passwd | cut -d: -f6 | sort -u); do
  for f in "$h/.ssh/authorized_keys" "$h/.ssh/authorized_keys2"; do
    [ -f "$f" ] && { echo "== $f"; ssh-keygen -lf "$f"; }
  done
done'

This prints a fingerprint and comment for every key. Compare them with the fingerprints of keys you trust (ssh-keygen -lf ~/.ssh/id_ed25519.pub). Delete every line you can't explain, add the new public key, and test a login in a second session before you remove the old key. If the attacker may have had root, also check for keys in unusual places such as AuthorizedKeysFile paths and service accounts with homes under /var. See Find backdoors.

3. API tokens and cloud keys

Revoke and reissue cloud provider access keys, DNS and registrar API tokens, CI/CD tokens, payment and email-service keys, and backup service credentials. Most providers let you create the new key first, deploy it, then delete the old one. Change the account passwords and turn on two-factor login for the provider accounts themselves. Check the provider's audit or activity log for actions you didn't take, such as new instances, new keys or changed DNS.

4. Database passwords

Change the database password, update the application's config file, and restart the application (this restarts a service):

# MySQL / MariaDB
ALTER USER 'app'@'localhost' IDENTIFIED BY 'new-long-random-password';

# PostgreSQL (in psql: \password app avoids the password in history and logs)
ALTER ROLE app WITH PASSWORD 'new-long-random-password';

MySQL can keep the old password working while you update the application: add RETAIN CURRENT PASSWORD, then run ALTER USER 'app'@'localhost' DISCARD OLD PASSWORD; once every client uses the new one. Also make sure the database port isn't open to the internet.

5. Panel and web accounts

Change the passwords for hosting control panels, the provider's customer portal, the domain registrar, the DNS host, CMS admin accounts and webmail. Turn on two-factor login where it is offered, and remove admin users you don't recognise. The registrar and DNS accounts matter most: with them, an attacker can redirect your whole domain (see Domain or DNS hijacked).

6. TLS private keys

If a private key for a certificate leaked, revoke the certificate and get a new one with a new key, in that order and within the same few minutes. With Certbot (Let's Encrypt):

sudo certbot certificates                    # find the certificate name and path
sudo certbot revoke --cert-path /etc/letsencrypt/live/example.com/cert.pem --reason keycompromise
sudo certbot renew --cert-name example.com --force-renewal --new-key
sudo systemctl reload nginx                  # or apache2 / httpd

When certbot revoke asks whether to delete the certificate, answer no, so that the renew command can replace it. The last line reloads the web server so that it serves the new certificate. For certificates from other authorities, use that authority's revocation process.

7. Secrets in git

Rotate the secret first. Once it is revoked, it no longer works, even though it stays in old commits. Then, if needed, remove it from history with git filter-repo (version 2.47 or later has --sensitive-data-removal) and force-push. Forks, clones and cached pages can still hold the old commit, so never rely on a history rewrite alone.

Check for misuse

# Successful SSH logins in the last 30 days (RHEL family: -u sshd)
sudo journalctl -u ssh --since "30 days ago" -g 'Accepted (password|publickey)'

# New users, recent changes to key files, cron and systemd units
sudo journalctl --since "30 days ago" -g 'new user|useradd|usermod'
sudo find /etc /root /home -xdev -mtime -30 \( -name authorized_keys -o -name '*.service' -o -path '*cron*' \) -ls
sudo crontab -l; sudo ls -laR /etc/cron.d /var/spool/cron

On Debian 13, last and lastlog no longer come with the base system (the replacements are the wtmpdb and lastlog2 packages), so the journal is the most reliable record. Look for logins from addresses or at times you don't recognise. If you find any, the server may be compromised. Follow Signs of compromise and Incident response, and consider whether personal data was exposed (Personal data breach).

Confirm it is done

Prevent it next time

When to call a professional

Bring in an incident response specialist if you find signs that the leaked credentials were used, especially root logins, new keys or users, or cloud resources you didn't create. Do the same if the systems hold personal or payment data, because legal reporting duties may apply. Tell your hosting provider if their portal or API credentials were part of the leak.

Sources