Blog · 12 listopada 2026 · 8 min czytania

Publicznie dostępne pliki na stronie: phpinfo, logi, .git, kopie bazy – jak sprawdzić i zamknąć

Strona działa, certyfikat jest, sklep sprzedaje – a pod adresem twojsklep.pl/info.php od trzech lat leży pełna konfiguracja serwera, pod /wp-content/debug.log 190 MB komunikatów o błędach, a pod /.git/ cały kod strony z historią zmian. Nikt tego nie widzi, bo nikt tam nie wchodzi – poza skanerami, które robią to automatycznie, całą dobę. Gdy przeskanowaliśmy 255 małych sklepów internetowych, taki plik miał co jedenasty. Poniżej: które adresy sprawdzić, co każdy plik zdradza i jak go zamknąć.

Skąd się biorą takie pliki

Prawie nigdy z włamania. Zwykle to pozostałość po pracy nad stroną: wykonawca wgrał info.php, żeby sprawdzić wersję PHP na nowym hostingu, i zapomniał usunąć; ktoś włączył tryb debugowania w WordPressie i nigdy go nie wyłączył; strona była wdrażana przez git pull bezpośrednio w katalogu publicznym; przed migracją zrobiono kopię bazy „na chwilę” do public_html/backup.sql; panel Adminer wgrano, bo hosting nie miał phpMyAdmina. Każda z tych rzeczy ma sens przez godzinę. Problem w tym, że serwer WWW serwuje wszystko, co leży w katalogu publicznym, dopóki ktoś mu tego nie zabroni.

Sprawdzenie w 5 minut

Potrzebna jest tylko przeglądarka w trybie prywatnym (żeby nie korzystać z zalogowanej sesji). Pod każdym z poniższych adresów powinien pojawić się błąd 403 lub 404 (albo przekierowanie na stronę główną). Jeśli widać treść – plik jest publiczny.

Adres do sprawdzeniaCo to jest
/phpinfo.php, /info.php, /test.phpwydruk konfiguracji PHP
/wp-content/debug.log, /error_log, /error.loglogi błędów PHP / WordPressa
/.git/HEAD, /.git/configrepozytorium Git
/.envzmienne środowiskowe z hasłami
/wp-config.php.bak, /wp-config.php~, /wp-config.oldkopie pliku z hasłem do bazy
/backup.sql, /dump.sql, /backup.zip, /nazwadomeny.sqlzrzut bazy lub kopia strony
/adminer.php, /phpmyadmin/panel do bazy danych
/.DS_Storelista plików zostawiona przez macOS

To lista najczęstszych nazw, nie wszystkich możliwych. Skaner, który sprawdza kilkadziesiąt wariantów naraz i rozpoznaje treść (a nie tylko kod odpowiedzi – wiele hostingów odpowiada „200” stroną błędu), jest w darmowym skanie Webskan na dole tej strony.

Co każdy z tych plików zdradza

phpinfo.php / info.php

Jedna strona z pełną konfiguracją: dokładna wersja PHP i serwera, ścieżki na dysku (/home/klient123/domains/…), załadowane moduły, limity, czasem zmienne środowiskowe – a w nich bywają hasła do bazy i klucze API. Dla kogoś, kto szuka strony podatnej na konkretny błąd w konkretnej wersji, to gotowa odpowiedź na pytanie „czy warto tu próbować”.

Logi błędów (debug.log, error_log)

Komunikaty w rodzaju PHP Warning: … in /home/klient123/public_html/wp-content/plugins/nazwa-wtyczki/plik.php on line 212. Z logu można odczytać listę zainstalowanych wtyczek z wersjami, strukturę katalogów, a przy źle napisanych formularzach – fragmenty danych wpisanych przez klientów. Dodatkowo log rośnie bez końca: dwa z plików, które widzieliśmy w skanie 255 sklepów, miały po około 190 MB i spowalniały każdą stronę, która do nich dopisywała.

Katalog .git

Jeśli /.git/HEAD odpowiada tekstem ref: refs/heads/…, repozytorium jest do pobrania w całości – istnieją narzędzia, które robią to automatycznie. W repozytorium jest kod strony (z ewentualnymi własnymi błędami bezpieczeństwa), a w historii zmian często pliki konfiguracyjne z hasłami, które „kiedyś” ktoś dodał i potem usunął. Usunięcie z bieżącej wersji nie usuwa z historii.

.env, kopie wp-config, zrzuty bazy, archiwa

To już nie konfiguracja, tylko dane: hasło do bazy, a w zrzucie bazy – klienci, zamówienia, adresy, zahaszowane hasła. Publicznie dostępna kopia bazy sklepu to naruszenie ochrony danych osobowych w rozumieniu RODO, niezależnie od tego, czy ktoś ją pobrał. O tym, co to oznacza praktycznie, piszemy w tekście RODO na stronie firmowej.

Adminer, phpMyAdmin

Formularz logowania do bazy danych wystawiony na cały internet. Samo hasło go nie chroni: panel można atakować słownikowo bez ograniczeń, a znane wersje Adminera miały błędy pozwalające czytać pliki z serwera bez logowania.

.DS_Store

Najmniej groźny, ale wymowny: plik, który macOS tworzy w każdym katalogu otwartym w Finderze, zawiera listę plików i podkatalogów – także tych, których nazw nikt by nie zgadł (stara-wersja/, kopia_2023.zip). Jego obecność zwykle oznacza, że pliki wgrywano ręcznie i nikt nie przeglądał, co dokładnie trafiło na serwer.

Jak to zamknąć

Dwa kroki, w tej kolejności: usunąć plik z katalogu publicznego (albo przenieść poza niego), a potem zabronić serwerowi serwowania takich plików w ogóle – żeby następny info.php też był niewidoczny. Katalog publiczny to zwykle public_html, htdocs lub www w menedżerze plików hostingu albo przez FTP/SFTP.

Apache (większość hostingów współdzielonych) – plik .htaccess

W głównym katalogu strony (tam, gdzie jest index.php) dopisać na początku pliku .htaccess:

# Pliki konfiguracyjne, logi, kopie, repozytoria – nigdy publicznie
<FilesMatch "^(phpinfo|info|test)\.php$|\.(log|sql|bak|old|orig|env|ini|zip|tar|gz|7z)$|^(error_log|\.env|\.DS_Store|adminer\.php|wp-config\.php~)$">
  Require all denied
</FilesMatch>
RedirectMatch 404 /\.(git|svn|hg)(/|$)

Na starszych serwerach (Apache 2.2) zamiast Require all denied działa Order allow,deny + Deny from all. Po zapisaniu warto odświeżyć stronę główną: jeśli pojawi się błąd 500, w regule jest literówka – cofnąć zmianę i poprawić. Uwaga: reguła blokuje też wtyczki i narzędzia, które same nazywają się np. test.php, oraz wszystkie archiwa – jeśli sklep udostępnia klientom pliki .zip do pobrania, usunąć te rozszerzenia z listy; jeśli coś innego przestało działać, zawęzić regułę.

nginx

W bloku server konfiguracji witryny (zwykle dostęp ma do tego hosting lub administrator, nie właściciel sklepu):

location ~ /\.(git|svn|hg|env|DS_Store) { deny all; return 404; }
location ~* ^/(phpinfo|info|test)\.php$ { deny all; return 404; }
location ~* \.(log|sql|bak|old|orig|ini|zip|tar|gz|7z)$ { deny all; return 404; }
location ~* ^/(error_log|adminer\.php)$ { deny all; return 404; }

WordPress – wyłączyć zapis logu do katalogu publicznego

W wp-config.php sprawdzić linie z WP_DEBUG. Na sklepie produkcyjnym powinno być:

define('WP_DEBUG', false);
define('WP_DEBUG_LOG', false);
define('WP_DEBUG_DISPLAY', false);

Jeśli log jest potrzebny do diagnozy, można zamiast false podać ścieżkę poza katalogiem publicznym, np. define('WP_DEBUG_LOG', '/home/klient123/logs/wp-debug.log');. Plik debug.log i tak trzeba skasować ręcznie – wyłączenie opcji go nie usuwa.

Git – wdrażać bez .git w katalogu publicznym

Najprościej: repozytorium poziom wyżej, a katalog publiczny jako podkatalog lub dowiązanie (np. repo/public → public_html). Jeśli to niemożliwe – reguła Apache/nginx z poprzednich punktów blokuje dostęp, a dodatkowo: jeśli w historii repozytorium kiedykolwiek były hasła, trzeba je zmienić, bo każdy, kto zdążył pobrać repozytorium, nadal je ma.

Co zrobić po zamknięciu

  1. Sprawdzić ponownie każdy adres w trybie prywatnym – 403/404. Pamięć podręczna hostingu lub Cloudflare może przez chwilę pokazywać starą odpowiedź; wtedy wyczyścić cache.
  2. Zmienić hasła, jeśli publiczny był .env, kopia wp-config, zrzut bazy albo katalog .git z taką zawartością w historii: baza danych, panel administracyjny, FTP/SFTP, klucze API widoczne w pliku.
  3. Zajrzeć do logów serwera (panel hostingu → statystyki / logi dostępu) i sprawdzić, czy ktoś pobierał ten plik. Przy kopii bazy z danymi klientów to decyduje o tym, czy trzeba zgłosić naruszenie do UODO (72 godziny od stwierdzenia).
  4. Dopisać to do listy kontrolnej po każdym wdrożeniu – obok testu formularza i przekierowań; mamy taką w tekście Co sprawdzić po wdrożeniu nowej strony.

Sprawdź swoją stronę – za darmo, w minutę

Darmowy szybki skan Webskan sprawdza kilkadziesiąt typowych nazw plików konfiguracyjnych, logów, kopii i repozytoriów – i patrzy na treść odpowiedzi, nie tylko na kod HTTP, więc strona błędu zwracana jako „200” nie da fałszywego alarmu. Do tego szybkość na telefonie, przekierowanie i HSTS, nagłówki bezpieczeństwa i podstawy SEO. Bez e-maila, bez rejestracji.

Szybki skan patrzy na stronę główną i typowe adresy plików. Audyt pogłębiony (249 zł) sprawdza całą witrynę – do 30 podstron, bezpieczeństwo, szybkość, dostępność i błędy widoczne dla klientów – z ponownym sprawdzeniem po poprawkach i 30 dniami Webskan Monitora w cenie.

Najczęstsze pytania

Hosting mówi, że „to normalne” albo że plik jest potrzebny

Żaden z wymienionych plików nie jest potrzebny do działania sklepu. Jeśli panel hostingu sam tworzy info.php lub error_log, reguła w .htaccess rozwiązuje problem bez kłótni z hostingiem.

Czy samo zablokowanie w .htaccess wystarczy, bez usuwania pliku?

Dla phpinfo i logów – praktycznie tak, choć usunięcie jest czystsze. Dla kopii bazy, .env i .git – nie: plik z hasłami nie powinien leżeć w katalogu publicznym nawet zablokowany, bo jedna zmiana konfiguracji (migracja, nowy hosting, nadpisany .htaccess przez wtyczkę) odsłania go z powrotem.

Skąd mam wiedzieć, czy ktoś już to pobrał?

Tylko z logów dostępu serwera. Większość hostingów trzyma je od kilku dni do kilku tygodni, więc im szybciej, tym lepiej. Jeśli logów nie ma – założyć, że plik mógł zostać pobrany, i postąpić jak w punkcie „Co zrobić po zamknięciu”.