Ukratko: Da biste pronašli nepoznate SSH ključeve, morate provjeriti sve datoteke authorized_keys na poslužitelju, ne samo onu od roota. Naredbom sshd -T utvrdite koje datoteke čita Vaša SSH usluga, navedite otiske prstiju svakog ključa i usporedite ih s poznatim ključevima. Strane unose najprije osigurajte, zatim ih uklonite i potom ojačajte pristup.
Ključ koji preživljava svaku promjenu lozinke
Nakon incidenta mnogi operateri kao prvo mijenjaju sve lozinke. Protiv jednih od najneupadljivijih stražnjih vrata to ne pomaže: dodatnog javnog ključa u datoteci authorized_keys. Tko posjeduje odgovarajući privatni ključ, prijavljuje se bez lozinke, sve dok netko ne pronađe redak.
Nepoznati SSH ključevi stoga spadaju među znakove koje nakon izvršavanja koda uvijek treba provjeriti. Za PHP2Shell nema objavljenih, potvrđenih Indicators of Compromise; prepoznavanje se temelji na analizi ponašanja. Strani ključ nije specifičan dokaz PHP2Shella, ali je jasan znak da je netko želio trajan pristup. Daljnje znakove opisuje članak Jesam li već kompromitiran?.
Gdje se SSH ključevi nalaze na poslužitelju
OpenSSH prema dokumentaciji standardno čita dvije datoteke u matičnom direktoriju svakog korisnika: .ssh/authorized_keys i .ssh/authorized_keys2. Druga se često zaboravlja. Postavka se može promijeniti, a pomoću AuthorizedKeysCommand poslužitelj ključeve može čak dohvaćati iz vanjskog programa. Zato najprije provjerite što na Vašem poslužitelju doista vrijedi:
# Ispisati efektivnu SSH konfiguraciju (samo čitanje)
sudo sshd -T | grep -iE '^(authorizedkeysfile|authorizedkeyscommand|permitrootlogin|passwordauthentication|pubkeyauthentication)'
# Dodatne konfiguracijske datoteke i Match blokovi
ls -la /etc/ssh/sshd_config.d/ 2>/dev/null
sudo grep -rn -iE '^\s*(Match|AuthorizedKeys)' /etc/ssh/
Posebno je mjesto matični direktorij korisnika web-poslužitelja. Na Debianu i Ubuntuu to je za www-data često /var/www. Ako PHP može pisati u taj direktorij, ubačeni kod tamo može stvoriti .ssh/authorized_keys. Hoće li prijava tada uspjeti, ovisi o prijavnoj ljusci i SSH postavkama, ali sama datoteka već je znak upozorenja.
Nije svaki nepoznati unos zlonamjeran. Alati za isporuku, usluge sigurnosnih kopija ili raniji pružatelji usluga pohranjuju vlastite ključeve. No takvi unosi trebali bi imati poznatog vlasnika i svrhu.
Provjera authorized_keys: korak po korak
Sljedeće naredbe ništa ne mijenjaju. Popisuju sve datoteke s ključevima korisnika i za svaki ključ prikazuju otisak prsta:
# Sve datoteke authorized_keys u matičnim direktorijima svih korisnika
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
# Prikazati otiske prstiju i komentare jedne datoteke
sudo ssh-keygen -lf /root/.ssh/authorized_keys
# Daljnje datoteke s ključevima izvan uobičajenih mjesta
sudo find / -xdev -name 'authorized_keys*' 2>/dev/null
Rezultat prođite ovim kontrolnim popisom:
- Pripada li svaki ključ poznatoj osobi ili poznatoj usluzi? Usporedite otiske prstiju, ne samo komentar.
- Ima li korisnik ključ koji uopće ne bi smio imati? Primjerice korisnik web-poslužitelja, baze podataka ili uslužni računi.
- Stoje li opcije ispred ključa? Unosi s
command=pri svakoj prijavi izvršavaju čvrstu naredbu. To je legitimno za sigurnosne kopije, ali i skrovište. - Kada je datoteka zadnji put izmijenjena? Datum izmjene nakon 17. 10. 2026., prema medijskim izvješćima prvog zabilježenog pokušaja napada na PHP2Shell, zaslužuje osobitu pažnju. Vremenski žigovi se ipak mogu krivotvoriti.
- Slažu li se vlasnik i prava? Datoteka koja pripada drugom korisniku nego matični direktorij je upadljiva.
Sigurno ukloniti strane ključeve
Prije nego obrišete redak, datoteku s vremenskim žigom i kontrolnim zbrojem osigurajte izvan poslužitelja. Zabilježite otisak prsta stranog ključa. Kasnije pomaže u pitanju pojavljuje li se isti ključ i na drugim poslužiteljima, primjerice kod agencije s mnogo sustava klijenata.
Provjerite i zapisnike prijava. U /var/log/auth.log (Debian, Ubuntu) ili /var/log/secure (RHEL obitelj) SSH usluga bilježi uspješne prijave s otiskom prsta korištenog ključa. Tako vidite je li strani ključ već korišten i s koje adrese.
Pomislite i na suprotan smjer. Ako na poslužitelju leže privatni ključevi, primjerice pod ~/.ssh/id_* za isporuke ili sigurnosne kopije, napadač ih je mogao kopirati. Njima možda dolazi do drugih poslužitelja, Git repozitorija ili odredišta sigurnosnih kopija. Takvi se ključevi nakon provale smatraju potrošenima: izraditi nove i stare ukloniti na svim ciljnim sustavima.
Strani ključ rijetko je jedini trag. Tko ga je pohranio, imao je prava pisanja i možda je postavio daljnje putove, primjerice cron poslove ili dodatne račune. Zato provjerite i skrivene cron poslove i tuđe administratorske račune. Ako je napadač imao root prava, ponovna izgradnja poslužitelja često je pouzdanija od čišćenja.
Strane ključeve uklanjajte tek kad je PHP na ispravljenom stanju (8.5.12, 8.4.27, 8.3.36, 8.2.35 ili potvrđeni backport) i svi workeri ponovno pokrenuti. Inače napadač ključ može odmah ponovno upisati putem iste ranjivosti.
Nakon toga ojačati SSH pristup
Nakon čišćenja isplati se kratko ojačavanje. Većina točaka brzo se provodi, ali ih uvijek treba testirati drugom, otvorenom sesijom da se ne biste sami zaključali.
| Mjera | Postavka ili postupak |
|---|---|
| Prijava samo ključem | PasswordAuthentication no |
| Ne dopustiti izravnu prijavu roota | PermitRootLogin no, rad preko osobnih računa sa sudo |
| Isključiti drugu datoteku s ključevima | AuthorizedKeysFile .ssh/authorized_keys |
| Ograničiti ključ prema podrijetlu | opcija from= ispred ključa, primjerice za poslužitelj sigurnosnih kopija |
| Ograničiti uslužne ključeve | opcija restrict i čvrst command= za automatizaciju |
| Korisnik web-poslužitelja bez prijave | prijavna ljuska nologin, nema .ssh u matičnom direktoriju |
Uz to vodite popis svih ovlaštenih ključeva s vlasnikom i svrhom. Kad zaposlenik ili pružatelj usluga ode, njegov se ključ uklanja na svim poslužiteljima. Bez tog popisa sljedeća je provjera opet detektivski posao. Priznate smjernice za ojačavanje SSH-a sadrže i CIS Benchmarks.
Kako PHP SOS konkretno pomaže?
- Utvrđujemo koje datoteke s ključevima Vaša SSH usluga doista čita i provjeravamo svaki unos prema poznatim vlasnicima.
- Nalaze osiguravamo i analiziramo zapisnike prijava da razjasnimo je li strani ključ korišten.
- Ključeve, račune i cron poslove čistimo pravim redoslijedom, a prethodno zatvaramo ranjivost.
- U okviru ojačavanja poslužitelja provodimo SSH postavke i uspostavljamo upravljanje ključevima s popisom vlasnika.
Česta pitanja
Kako prepoznati je li SSH ključ tuđ?
Svaki ključ ima otisak prsta i uglavnom komentar na kraju retka. Usporedite otiske prstiju s ključevima svojih zaposlenika i pružatelja usluga. Sam komentar ništa ne dokazuje, jer se slobodno bira i može se krivotvoriti.
Pomaže li promjena root lozinke?
Protiv ubačenog ključa ne. Prijava ključem ne treba lozinku. Zato se same datoteke authorized_keys moraju provjeriti i očistiti.
Zašto korisnik web-poslužitelja može imati SSH ključ?
Korisnik web-poslužitelja ima vlastiti matični direktorij, na Debianu i Ubuntuu često /var/www. Ako tamo leži .ssh/authorized_keys i račun ima prijavnu ljusku, prijava kao taj korisnik je moguća. Kod direktorija web-stranice u koji se može pisati ubačeni PHP kod može stvoriti takvu datoteku.
Što je authorized_keys2?
Starija druga datoteka koju OpenSSH prema zadanoj postavci također čita. Mnoge upute za provjeru je previđaju. Naredbom sshd -T provjerite koje datoteke Vaš poslužitelj doista evaluira.