Stručně: Záložní soubory ve webrootu, tedy výpisy databází (.sql), archivy (.zip, .tar.gz) a záložní kopie (.bak, .old, ~), si může stáhnout každý, kdo zná nebo uhodne název souboru. Takové soubory pravidelně vyhledávejte pomocí find, zálohy přesuňte mimo veřejný adresář, ve webserveru zablokujte typické přípony a v přístupových lozích zkontrolujte, zda už byly staženy.
Záloha, která se stane únikem
Krátce před aktualizací někdo rychle vytvoří zálohu: backup.zip v hlavním adresáři, vedle datenbank.sql. Aktualizace se podaří, soubory zůstanou ležet. O měsíce později tam pořád jsou, s kompletním kódem, všemi daty zákazníků a přístupovými údaji webu.
Tento vzor patří k nejčastějším nálezům při kontrolách webserverů. Nepotřebuje žádný exploit ani zranitelnost v PHP. Webserver doručuje z webrootu to, co tam leží, a archivy nebo soubory SQL neprovádí, ale nabízí je ke stažení.
Archiv webu přitom neobsahuje jen data, ale i kód včetně konfigurace. Kdo ho stáhne, může v klidu hledat slabiny a zná přístupové údaje k databázi.
Automatizované skenery cíleně hledají typické názvy jako backup.zip, site.tar.gz nebo dump.sql, často v kombinaci s názvem domény nebo datem. Kdo věří, že neobvyklý název souboru chrání, podceňuje, jak systematicky toto hledání probíhá.
Jaké soubory se myslí
Záložní soubory ve webrootu se vyskytují v několika podobách:
| Druh | Typické přípony | Co v nich je |
|---|---|---|
| Výpisy databází | .sql, .sql.gz, .dump |
data zákazníků, objednávky, hashe hesel, nastavení |
| Archivy webu | .zip, .tar, .tar.gz, .tgz, .rar, .7z |
veškerý kód, konfigurace, uploady |
| Kopie jednotlivých souborů | .bak, .old, .orig, .save, .php~, .copy |
často konfigurační soubory s přístupovými údaji |
| Zbytky editorů | .swp, .swo, ~ na konci |
části právě upravovaných souborů |
| Zálohy pluginů | vlastní podsložky v CMS | úplné zálohy, částečně s uhodnutelnými názvy |
Obzvlášť citlivé jsou kopie konfiguračních souborů. Původní soubor config.php server provede a jeho obsah zůstane skrytý. Kopii config.php.bak doručí jako text, včetně hesla k databázi.
Najít zálohy ve webrootu: hledání na serveru
Následující vyhledávání vypíše podezřelé soubory pod webrooty s datem a velikostí. Cesty upravte podle svého serveru:
find /var/www /srv/www -type f \( \
-iname '*.sql' -o -iname '*.sql.gz' -o -iname '*.dump' -o \
-iname '*.zip' -o -iname '*.tar' -o -iname '*.tar.gz' -o -iname '*.tgz' -o \
-iname '*.rar' -o -iname '*.7z' -o \
-iname '*.bak' -o -iname '*.old' -o -iname '*.orig' -o -iname '*.save' -o \
-iname '*~' -o -iname '*.swp' \) \
-printf '%TY-%Tm-%Td %10s %p\n' 2>/dev/null | sort
Ne každý nález je problém. Některé archivy jsou záměrně nabízeny ke stažení, například příručky. Každý soubor si ale zaslouží vědomé rozhodnutí. Dávejte zvláštní pozor na velké soubory a na složky záložních pluginů. U sdíleného hostingu bez přístupu k shellu pomůže přehled souborů v panelu hostingu nebo stažení přes SFTP.
Pokud ve webrootu najdete výpis databáze s daty zákazníků, okamžitě ho přesuňte z veřejného adresáře a zajistěte přístupové logy dříve, než se rotují. Teprve poté zjišťujte, zda byl soubor stažen.
Byl soubor už stažen?
Odpověď je v přístupových lozích webserveru. Hledají se úspěšná stažení, tedy stav 200, nalezených souborů:
# Úspěšná stažení typických záložních přípon (formát logu Combined)
zgrep -hE '\.(sql|sql\.gz|zip|tar|tgz|gz|bak|old|7z|rar)[ ?]' /var/log/nginx/access.log* \
| awk '$9 == 200 {print $4, $1, $7, $10}'
Výstup ukazuje čas, adresu, cestu a velikost odpovědi. Pokud přenesená velikost odpovídá velikosti souboru, byl soubor stažen celý. Jak daleko logy sahají do minulosti, závisí na rotaci. Pokud nesahají až k datu vytvoření souboru, nelze dřívější stažení vyloučit. Podrobně to popisuje Vyhodnocení logů webserveru po útoku. Pokud nemáte přístup k surovým logům, například u sdíleného hostingu, požádejte poskytovatele hostingu o logy za dané období.
Pokud byl výpis s osobními údaji stažen nebo to nelze vyloučit, začíná posuzování oznamovací povinnosti. Základy shrnuje stránka Oznamovací povinnost podle GDPR: 72 hodin po incidentu; posouzení v jednotlivém případě patří vašemu pověřenci pro ochranu osobních údajů. Přístupové údaje ze stažených souborů vyměňte v každém případě.
Záložní pluginy, panely a přesuny
Mnoho nálezů pochází ze záložních pluginů CMS a e-shopů. Zálohy ukládají často do podsložky webrootu, částečně s názvy z data a domény, které lze uhodnout. V každém pluginu zkontrolujte tři nastavení: Kam se zálohuje? Mažou se místní kopie po nahrání na externí cíl? Je místní složka chráněna proti přímému stažení?
Zálohy z panelů hostingu leží zpravidla mimo webroot, například v domovském adresáři. Problematické to je, když někdo takovou zálohu zkopíruje do webrootu, protože stažení v prohlížeči je pohodlnější než přes SFTP. Pro přesuny proto platí: přenos přes SFTP nebo přímo mezi servery, nikdy přes veřejný odkaz.
Pokud vaše weby spravují agentury nebo dodavatelé, mělo by toto pravidlo stát i ve smlouvě, včetně povinnosti uklidit po údržbových pracích. Poznámky najdete v článku Smlouvy s IT dodavateli: jasně upravit bezpečnostní povinnosti.
Trvale předcházet: místo uložení a blokování
Aby se problém neopakoval, jsou potřeba dvě úrovně. První je organizační: zálohy mají pevné místo mimo webroot a navíc mimo server. Jak vypadá spolehlivá záloha, popisuje příručka Zálohy podle pravidla 3-2-1.
Druhá úroveň je technická: webserver typické záložní přípony zásadně odmítá, i když nějaký soubor přece jen zůstane ležet.
location ~* \.(sql|sql\.gz|dump|bak|old|orig|save|swp|swo)$ {
return 404;
}
location ~ ~$ {
return 404;
}
Archivy jako .zip blokujte jen tehdy, pokud váš web nenabízí ke stažení soubory v tomto formátu, nebo cíleně v adresářích, kde žádná stažení neleží. Pomáhá také pravidelné automatické vyhledávání s upozorněním a krátké pravidlo v týmu: žádné zálohy a kopie ve webrootu, ani na pět minut. Příbuzné případy jako skryté konfigurační soubory řeší Správná ochrana přístupových údajů a souborů .env.
Jak konkrétně pomáhá PHP SOS?
- Prohledáme vaše webrooty na výpisy, archivy, kopie a zálohy pluginů a každý nález posoudíme.
- Na základě přístupových logů zkontrolujeme, zda byly soubory staženy, a výsledek zdokumentujeme pro vaše posouzení ochrany osobních údajů.
- Nastavíme blokování ve webserveru a pravidelné automatické vyhledávání.
- Zálohy přesuneme na chráněné místo mimo webroot.
Tyto práce jsou součástí našeho hardeningu serveru pro webservery s PHP.
Časté dotazy
Proč zálohy vůbec končí ve webrootu?
Většinou z pohodlnosti: výpis se vytvoří pro přesun, plugin ukládá zálohy do vlastní složky, nebo se před změnou rychle vytvoří kopie souboru s příponou .bak. Poté soubor upadne v zapomnění.
Jak nebezpečný je soubor jako config.php.bak?
Velmi. Soubor s příponou .php server provede a jeho obsah zůstane skrytý. Kopii s jinou příponou naproti tomu server většinou doručí jako text, včetně hesla k databázi a klíčů.
Je veřejně dostupný výpis databáze porušením zabezpečení osobních údajů?
Pokud obsahuje osobní údaje a byl stažen, nebo nelze stažení vyloučit, přichází v úvahu oznamovací povinnost podle GDPR. Posouzení v jednotlivém případě provede váš pověřenec pro ochranu osobních údajů nebo váš právní poradce.
Kde by zálohy měly ležet místo toho?
Mimo webroot a navíc mimo server, podle pravidla 3-2-1. Alespoň jedna kopie by měla být uložena tak, aby ji sám webserver nemohl smazat ani změnit.