Krótko: Pliki kopii zapasowych w webroot, czyli zrzuty baz danych (.sql), archiwa (.zip, .tar.gz) i kopie zapasowe (.bak, .old, ~), może pobrać każdy, kto zna lub odgadnie nazwę pliku. Wyszukuj takie pliki regularnie za pomocą find, przenoś kopie poza katalog publiczny, blokuj typowe rozszerzenia w serwerze WWW i sprawdzaj w logach dostępu, czy zostały już pobrane.
Kopia zapasowa, która staje się wyciekiem
Tuż przed aktualizacją ktoś szybko tworzy kopię: backup.zip w katalogu głównym, obok datenbank.sql. Aktualizacja się udaje, pliki zostają. Miesiące później nadal tam są, z całym kodem, wszystkimi danymi klientów i danymi dostępowymi strony.
Ten wzorzec należy do najczęstszych ustaleń podczas kontroli serwerów WWW. Nie potrzeba do tego exploita ani luki w PHP. Serwer WWW wydaje z webroot to, co tam leży, a archiwów lub plików SQL nie wykonuje, tylko oferuje je do pobrania.
Archiwum strony zawiera przy tym nie tylko dane, ale także kod wraz z konfiguracją. Kto je pobierze, może w spokoju szukać słabych punktów i zna dane dostępowe do bazy danych.
Zautomatyzowane skanery szukają celowo typowych nazw, takich jak backup.zip, site.tar.gz lub dump.sql, często w połączeniu z nazwą domeny lub datą. Kto sądzi, że nietypowa nazwa pliku chroni, nie docenia, jak systematycznie przebiega to wyszukiwanie.
Jakie pliki mamy na myśli
Pliki kopii zapasowych w webroot występują w kilku postaciach:
| Rodzaj | Typowe rozszerzenia | Co zawierają |
|---|---|---|
| Zrzuty baz danych | .sql, .sql.gz, .dump |
dane klientów, zamówienia, skróty haseł, ustawienia |
| Archiwa strony | .zip, .tar, .tar.gz, .tgz, .rar, .7z |
cały kod, konfiguracja, uploady |
| Kopie pojedynczych plików | .bak, .old, .orig, .save, .php~, .copy |
często pliki konfiguracyjne z danymi dostępowymi |
| Pozostałości edytorów | .swp, .swo, ~ na końcu |
fragmenty aktualnie edytowanych plików |
| Kopie z wtyczek | własne podkatalogi w CMS | pełne kopie, częściowo z łatwymi do odgadnięcia nazwami |
Szczególnie delikatne są kopie plików konfiguracyjnych. Oryginalny plik config.php serwer wykonuje, a jego zawartość pozostaje ukryta. Kopię config.php.bak wydaje jako tekst, wraz z hasłem do bazy danych.
Znajdowanie backupu w webroot: wyszukiwanie na serwerze
Poniższe wyszukiwanie wypisuje podejrzane pliki poniżej webroot z datą i rozmiarem. Dostosuj ścieżki do swojego serwera:
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
Nie każde trafienie jest problemem. Niektóre archiwa są celowo udostępnione do pobrania, na przykład podręczniki. Każdy plik zasługuje jednak na świadomą decyzję. Zwróć szczególną uwagę na duże pliki i katalogi wtyczek do kopii zapasowych. Przy hostingu współdzielonym bez dostępu do powłoki pomaga przegląd plików w panelu hostingu lub podgląd przez SFTP.
Jeśli znajdziesz w webroot zrzut bazy danych z danymi klientów, natychmiast przenieś go z katalogu publicznego i zabezpiecz logi dostępu, zanim zostaną zrotowane. Dopiero potem ustal, czy plik został pobrany.
Czy plik został już pobrany?
Odpowiedź znajduje się w logach dostępu serwera WWW. Szukane są udane pobrania, czyli status 200, znalezionych plików:
# Udane pobrania typowych rozszerzeń kopii zapasowych (format logów 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}'
Wynik pokazuje czas, adres, ścieżkę i rozmiar odpowiedzi. Jeśli przesłany rozmiar odpowiada rozmiarowi pliku, plik został pobrany w całości. Jak daleko wstecz sięgają logi, zależy od rotacji. Jeśli nie sięgają do daty utworzenia pliku, wcześniejszego pobrania nie można wykluczyć. Szczegółowo opisuje to artykuł Analiza logów serwera WWW po ataku. Bez dostępu do surowych logów, na przykład przy hostingu współdzielonym, poproś firmę hostingową o logi z danego okresu.
Jeśli pobrano zrzut z danymi osobowymi albo nie można tego wykluczyć, zaczyna się sprawdzanie obowiązku zgłoszenia. Podstawy podsumowuje artykuł Obowiązek zgłoszenia na podstawie RODO: 72 godziny po incydencie; ocena w indywidualnym przypadku należy do Państwa inspektora ochrony danych. Dane dostępowe z pobranych plików wymieniasz w każdym przypadku.
Wtyczki do kopii zapasowych, panele i przeprowadzki
Wiele znalezisk wynika z wtyczek do kopii zapasowych w CMS i sklepach. Zapisują one kopie często w podkatalogu webroot, częściowo z nazwami z daty i domeny, które da się odgadnąć. Sprawdź w każdej wtyczce trzy ustawienia: Dokąd zapisywane są kopie? Czy lokalne kopie są usuwane po przesłaniu do zewnętrznego celu? Czy lokalny katalog jest chroniony przed bezpośrednim pobraniem?
Kopie z paneli hostingu leżą zwykle poza webroot, na przykład w katalogu domowym. Problem pojawia się, gdy ktoś skopiuje taką kopię do webroot, ponieważ pobranie w przeglądarce jest wygodniejsze niż przez SFTP. Przy przeprowadzkach obowiązuje więc zasada: przesyłanie przez SFTP lub bezpośrednio między serwerami, nigdy przez publiczny link.
Jeśli Państwa stronami opiekują się agencje lub usługodawcy, ta zasada powinna znaleźć się także w umowie, wraz z obowiązkiem sprzątania po pracach serwisowych. Wskazówki daje artykuł Umowy z dostawcami IT: jasne zasady dotyczące obowiązków bezpieczeństwa.
Zapobieganie na stałe: miejsce przechowywania i blokady
Aby problem się nie powtarzał, potrzebne są dwa poziomy. Pierwszy jest organizacyjny: kopie mają stałe miejsce poza webroot i dodatkowo poza serwerem. Jak wygląda niezawodna kopia, opisuje poradnik Kopie zapasowe według reguły 3-2-1.
Drugi poziom jest techniczny: serwer WWW zasadniczo odmawia typowych rozszerzeń kopii zapasowych, nawet jeśli jakiś plik jednak pozostanie.
location ~* \.(sql|sql\.gz|dump|bak|old|orig|save|swp|swo)$ {
return 404;
}
location ~ ~$ {
return 404;
}
Archiwa takie jak .zip blokujesz tylko wtedy, gdy Państwa strona nie oferuje pobrań w tym formacie, albo celowo w katalogach, w których nie leżą żadne pliki do pobrania. Pomagają dodatkowo regularne automatyczne wyszukiwanie z powiadomieniem i krótka zasada w zespole: żadnych kopii zapasowych ani kopii plików w webroot, także na pięć minut. Pokrewne przypadki, takie jak ukryte pliki konfiguracyjne, omawia artykuł Prawidłowa ochrona danych dostępowych i plików .env.
Jak konkretnie pomaga PHP SOS?
- Przeszukujemy Państwa webroot pod kątem zrzutów, archiwów, kopii i kopii z wtyczek i oceniamy każde znalezisko.
- Sprawdzamy na podstawie logów dostępu, czy pliki były pobierane, i dokumentujemy wynik na potrzeby Państwa oceny w zakresie ochrony danych.
- Wdrażamy blokady w serwerze WWW i regularne automatyczne wyszukiwanie.
- Przenosimy kopie zapasowe w chronione miejsce poza webroot.
Te prace są częścią naszego utwardzania serwerów PHP.
Częste pytania
Dlaczego kopie zapasowe w ogóle trafiają do webroot?
Zwykle z wygody: zrzut powstaje na potrzeby przeprowadzki, wtyczka zapisuje kopie we własnym katalogu albo przed zmianą szybko tworzona jest kopia pliku z rozszerzeniem .bak. Potem plik idzie w zapomnienie.
Jak niebezpieczny jest plik taki jak config.php.bak?
Bardzo. Plik z rozszerzeniem .php jest wykonywany przez serwer, a jego zawartość pozostaje ukryta. Kopię z innym rozszerzeniem serwer wydaje natomiast zwykle jako tekst, razem z hasłem do bazy danych i kluczami.
Czy publicznie dostępny zrzut bazy danych to naruszenie ochrony danych?
Jeśli zawiera dane osobowe i został pobrany albo nie można wykluczyć pobrania, w grę wchodzi obowiązek zgłoszenia na podstawie RODO. Ocenę w indywidualnym przypadku przejmują Państwa inspektor ochrony danych lub doradztwo prawne.
Gdzie zamiast tego powinny leżeć kopie zapasowe?
Poza webroot i dodatkowo poza serwerem, zgodnie z regułą 3-2-1. Co najmniej jedna kopia powinna być przechowywana tak, aby sam serwer WWW nie mógł jej usunąć ani zmienić.