Stručně: Chcete-li najít neznámé klíče SSH, musíte zkontrolovat všechny soubory authorized_keys na serveru, nejen ten uživatele root. Pomocí sshd -T zjistěte, které soubory vaše služba SSH čte, vypište otisky každého klíče a porovnejte je se známými klíči. Cizí záznamy nejprve zajistěte, pak je odstraňte a přístup následně zabezpečte.
Klíč, který přežije každou změnu hesla
Po incidentu mnoho provozovatelů nejprve změní všechna hesla. Proti jednomu z nejnenápadnějších zadních vrátek to nepomůže: dalšímu veřejnému klíči v souboru authorized_keys. Kdo má odpovídající soukromý klíč, přihlásí se bez hesla, dokud někdo řádek nenajde.
Neznámé klíče SSH proto patří k příznakům, které by se po spuštění kódu měly kontrolovat vždy. Pro PHP2Shell neexistují zveřejněné, potvrzené indikátory kompromitace (Indicators of Compromise); detekce se opírá o analýzu chování. Cizí klíč není specifickým důkazem PHP2Shell, ale jasným znamením, že někdo chtěl trvalý přístup. Další příznaky popisuje článek Jsem už kompromitován?.
Kde na serveru leží klíče SSH
OpenSSH čte podle dokumentace standardně dva soubory v domovském adresáři každého uživatele: .ssh/authorized_keys a .ssh/authorized_keys2. Ten druhý se často zapomíná. Nastavení lze změnit a pomocí AuthorizedKeysCommand může server klíče dokonce získávat z externího programu. Nejprve proto zkontrolujte, co na vašem serveru skutečně platí:
# Vypsat efektivní konfiguraci SSH (jen čtení)
sudo sshd -T | grep -iE '^(authorizedkeysfile|authorizedkeyscommand|permitrootlogin|passwordauthentication|pubkeyauthentication)'
# Dodatečné konfigurační soubory a bloky Match
ls -la /etc/ssh/sshd_config.d/ 2>/dev/null
sudo grep -rn -iE '^\s*(Match|AuthorizedKeys)' /etc/ssh/
Zvláštním místem je domovský adresář uživatele webového serveru. U Debianu a Ubuntu je to pro www-data často /var/www. Je-li tento adresář pro PHP zapisovatelný, může vložený kód založit .ssh/authorized_keys. Zda se přihlášení poté podaří, závisí na přihlašovacím shellu a nastavení SSH, samotný soubor je ale už poplašným znamením.
Ne každý neznámý záznam je zlovolný. Nástroje pro nasazení, služby záloh nebo dřívější dodavatelé ukládají vlastní klíče. Takové záznamy by ale měly mít známého vlastníka a účel.
Kontrola authorized_keys krok za krokem
Následující příkazy nic nemění. Vypíší všechny soubory klíčů uživatelů a ukážou otisk každého klíče:
# Všechny soubory authorized_keys v domovských adresářích všech uživatelů
getent passwd | cut -d: -f1,6 | while IFS=: read -r user home; do
for f in "$home/.ssh/authorized_keys" "$home/.ssh/authorized_keys2"; do
[ -f "$f" ] && echo "== $user: $f" && sudo ls -la --time-style=full-iso "$f"
done
done
# Zobrazit otisky a komentáře jednoho souboru
sudo ssh-keygen -lf /root/.ssh/authorized_keys
# Další soubory klíčů mimo obvyklá místa
sudo find / -xdev -name 'authorized_keys*' 2>/dev/null
Projděte výsledek podle tohoto kontrolního seznamu:
- Patří každý klíč známé osobě nebo známé službě? Porovnávejte otisky, nejen komentář.
- Má uživatel klíč, který by vůbec mít neměl? Například uživatel webového serveru, databáze nebo servisní účty.
- Stojí před klíčem volby? Záznamy s
command=provádějí při každém přihlášení pevný příkaz. To je legitimní pro zálohy, ale i skrýš. - Kdy byl soubor naposledy změněn? Datum změny po 17. 10. 2026, prvním pozorovaném pokusu o útok PHP2Shell podle zpráv médií, zaslouží zvláštní pozornost. Časová razítka lze ale zfalšovat.
- Souhlasí vlastník a oprávnění? Soubor, který patří jinému uživateli než domovský adresář, je nápadný.
Cizí klíče bezpečně odstranit
Než řádek smažete, zajistěte soubor s časovým razítkem a kontrolním součtem mimo server. Poznamenejte si otisk cizího klíče. Pomůže později při otázce, zda se tentýž klíč objevuje i na jiných serverech, například u agentury s mnoha zákaznickými systémy.
Zkontrolujte navíc protokoly přihlášení. V /var/log/auth.log (Debian, Ubuntu) nebo /var/log/secure (rodina RHEL) protokoluje služba SSH úspěšná přihlášení s otiskem použitého klíče. Uvidíte tak, zda už byl cizí klíč použit a z jaké adresy.
Myslete i na opačný směr. Leží-li na serveru soukromé klíče, například pod ~/.ssh/id_* pro nasazení nebo zálohy, mohl je útočník zkopírovat. S nimi možná dosáhne na jiné servery, repozitáře Git nebo cíle záloh. Takové klíče se po průniku považují za spotřebované: vytvořit nové klíče a staré odstranit na všech cílových systémech.
Cizí klíč je zřídka jedinou stopou. Kdo jej uložil, měl práva zápisu a možná zřídil další cesty, například cron úlohy nebo dodatečné účty. Zkontrolujte proto i skryté cron úlohy a cizí účty správců. Měl-li útočník práva root, je nová výstavba serveru často spolehlivější než vyčištění.
Cizí klíče odstraňte až tehdy, když je PHP na opraveném stavu (8.5.12, 8.4.27, 8.3.36, 8.2.35 nebo potvrzený backport) a všichni workeři jsou restartováni. Jinak může útočník klíč přes tutéž zranitelnost ihned znovu zapsat.
Přístup SSH poté zabezpečit
Po vyčištění se vyplatí krátký hardening. Většina bodů se zavádí rychle, vždy je ale třeba je otestovat druhou, otevřenou relací, abyste se nevyloučili.
| Opatření | Nastavení nebo postup |
|---|---|
| Přihlášení jen klíčem | PasswordAuthentication no |
| Nepřipouštět přímé přihlášení root | PermitRootLogin no, práce přes osobní účty se sudo |
| Vypnout druhý soubor klíčů | AuthorizedKeysFile .ssh/authorized_keys |
| Omezit klíč podle původu | volba from= před klíčem, např. pro záložní server |
| Omezit servisní klíče | volba restrict a pevný command= pro automatizaci |
| Uživatel webového serveru bez přihlášení | přihlašovací shell nologin, žádné .ssh v domovském adresáři |
Veďte navíc seznam všech oprávněných klíčů s vlastníkem a účelem. Odchází-li zaměstnanec nebo dodavatel, jeho klíč se odstraní na všech serverech. Bez tohoto seznamu je další kontrola opět detektivní prací. Uznávané požadavky na hardening SSH obsahují také CIS Benchmarks.
Jak konkrétně pomáhá PHP SOS?
- Zjišťujeme, které soubory klíčů vaše služba SSH skutečně čte, a každý záznam kontrolujeme proti známým vlastníkům.
- Nálezy zajišťujeme a vyhodnocujeme protokoly přihlášení, abychom objasnili, zda byl cizí klíč použit.
- Klíče, účty a cron úlohy čistíme ve správném pořadí a předem uzavřeme zranitelnost.
- V rámci hardeningu serveru zavádíme nastavení SSH a zřizujeme správu klíčů se seznamem vlastníků.
Časté dotazy
Jak poznám, že je klíč SSH cizí?
Každý klíč má otisk a většinou komentář na konci řádku. Porovnejte otisky s klíči svých zaměstnanců a dodavatelů. Samotný komentář nic nedokazuje, protože je libovolně volitelný a lze jej zfalšovat.
Pomůže změna hesla root?
Proti vloženému klíči ne. Přihlášení klíčem heslo nepotřebuje. Proto je třeba zkontrolovat a vyčistit samotné soubory authorized_keys.
Proč může mít uživatel webového serveru klíč SSH?
Uživatel webového serveru má vlastní domovský adresář, u Debianu a Ubuntu často /var/www. Leží-li tam .ssh/authorized_keys a má-li účet přihlašovací shell, je přihlášení jako tento uživatel možné. U zapisovatelného webového adresáře může vložený kód PHP takový soubor založit.
Co je authorized_keys2?
Starší druhý soubor, který OpenSSH podle výchozího nastavení rovněž čte. Mnoho kontrolních návodů jej přehlíží. Pomocí sshd -T ověřte, které soubory váš server skutečně vyhodnocuje.