Ekspozycja plików wrażliwych
ważność wysokamierzonysposób exposure
Dostępność wp-config.php.bak, wp-config.php~, debug.log, listingu katalogów. Częsty błąd przy migracji hostingu.
WIKI
artykuł z 16.09.2026 · źródeł 10Ekspozycja plików wrażliwych to parametr monitoringu stron internetowych, który sprawdza, czy serwer WWW oddaje publicznie pliki pozostawione obok kodu strony: kopie pliku konfiguracyjnego wp-config.php z innym rozszerzeniem (wp-config.php.bak, wp-config.php~), dziennik błędów wp-content/debug.log oraz automatycznie wygenerowany spis zawartości katalogu. Pomiar kończy się jednym z trzech wyników: plik lub spis dostępny, niedostępny albo nie udało się uzyskać odpowiedzi. Przewodnik testowania OWASP zalicza stare kopie, pliki nieużywane i logi pozostawione w katalogach serwera do typowych źródeł wycieku informacji [1].
Jak działa
Kopie powstają na dwa sposoby. Część tworzą narzędzia: OWASP podaje przykład edytora emacs, który przy edycji pliku file zapisuje kopię file~ [1], a Vim trzyma zmiany w pliku wymiany o nazwie edytowanego pliku z rozszerzeniem .swp, na systemach uniksowych poprzedzonej kropką, w tym samym katalogu [5]. Resztę tworzą ludzie. MITRE opisuje kopie przemianowane automatycznie albo ręcznie przez administratora, np. na rozszerzenie .~bk, i pozostawione w katalogu dokumentów serwera [2]. Taki sam charakter ma kopia wp-config.php.bak zrobiona przed edycją lub przeniesieniem strony.
Plik wp-config.php leży w katalogu głównym instalacji WordPressa i zawiera dane połączenia z bazą (DB_NAME, DB_USER, DB_PASSWORD, DB_HOST) oraz unikalne klucze i sole uwierzytelniania [3]. Przy żądaniu tego pliku serwer przekazuje go interpreterowi PHP i odsyła wynik wykonania, a nie kod. Decyduje o tym dopasowanie nazwy: zalecana w dokumentacji PHP konfiguracja Apache kieruje do interpretera tylko pliki pasujące do wyrażenia \.php$ [4]. Nazwa wp-config.php.bak kończy się na .bak, więc wyrażenie jej nie obejmuje i serwer podaje plik jak każdy inny plik statyczny. OWASP opisuje ten sam mechanizm: żądanie viewdoc.bak może zwrócić kod źródłowy viewdoc.jsp [1].
Dziennik błędów powstaje z ustawienia. Stała WP_DEBUG_LOG zapisuje wszystkie błędy do pliku debug.log, domyślnie w katalogu treści, zwykle wp-content/debug.log; można też podać inną ścieżkę [6]. Działa tylko przy włączonym WP_DEBUG [6]. Dokumentacja zaleca łączenie jej z WP_DEBUG_DISPLAY ustawionym na false, żeby błędy nie trafiały do HTML strony, lecz dało się je przejrzeć później [6].
Spis katalogu to funkcja serwera. W Apache opcja Indexes sprawia, że gdy adres wskazuje katalog bez pliku z listy DirectoryIndex, moduł mod_autoindex zwraca sformatowaną listę jego zawartości [7]. Domyślny plik konfiguracyjny Apache ustawia dla katalogu dokumentów Options Indexes FollowSymLinks [8]. W nginx spis tworzy moduł autoindex dla żądań zakończonych ukośnikiem, zwykle wtedy, gdy nie ma pliku indeksu; dyrektywa autoindex jest domyślnie wyłączona [9].
Standardy i specyfikacje
- OWASP WSTG-CONF-04 każe sprawdzać kopie plików i pliki bez odnośników, a spis katalogu nazywa najbardziej oczywistym sposobem, w jaki źle skonfigurowany serwer ujawnia takie pliki [1]. Zauważa też, że logi mogą zawierać identyfikatory sesji, parametry adresów i adresy nieujawnionych stron [1].
- CWE-530 („Exposure of Backup File to an Unauthorized Control Sphere”) to kopia zapasowa zapisana w katalogu lub archiwum dostępnym dla nieuprawnionych; jest potomkiem CWE-552, plików i katalogów dostępnych dla stron zewnętrznych [2]. Wśród obserwowanych przypadków MITRE wymienia wtyczkę WordPressa tworzącą przewidywalne nazwy kopii (CVE-2024-7315) [2].
- CWE-548 („Exposure of Information Through Directory Listing”) to udostępnienie spisu wszystkich zasobów katalogu; MITRE zaleca wyłączenie automatycznych spisów katalogów [10].
Zagrożenia i skutki
Dane dostępowe do bazy. Odczytana kopia wp-config.php daje nazwę bazy, użytkownika, hasło i adres serwera bazy oraz klucze i sole [3]. Kod źródłowy pobrany z kopii pozwala też szukać podatności, których nie widać przy żądaniach do wykonywanej strony [1].
Treść dziennika. Log może ujawniać działania użytkowników, identyfikatory sesji i adresy, które nie są nigdzie podlinkowane [1]. Stała WP_DEBUG_LOG zapisuje wszystkie błędy, więc plik rośnie z każdym zapisanym błędem, dopóki ustawienie jest włączone [6].
Spis katalogu. MITRE wskazuje, że spis może dać dostęp do kodu źródłowego, ujawnić daty utworzenia plików i informacje zawarte w nazwach, przydatne przy planowaniu ataku [10]. Spis ujawnia też pliki, do których nie prowadzi żaden odnośnik, w tym kopie opisane wyżej [1].
Fałszywe trafienia. Odpowiedź 200 z własną stroną „nie znaleziono” wygląda w samym kodzie statusu jak istniejący plik [1]. O wycieku rozstrzyga treść odpowiedzi, a nie sam kod.
Przykłady
| Sytuacja | Odpowiedź serwera | Znaczenie |
|---|---|---|
GET /wp-config.php przy dopasowaniu \.php$ [4] | wynik wykonania skryptu | kod i hasła niewidoczne |
Kopia wp-config.php.bak w katalogu instalacji [2] [4] | 200 z tekstem pliku | dane bazy, klucze i sole do zmiany [3] |
Kopia emacs wp-config.php~ [1] | 200 z tekstem pliku | jak wyżej |
Plik wymiany Vim .wp-config.php.swp [5] | zależy od reguł dla nazw z kropką | zawiera zmiany z sesji edycji |
WP_DEBUG i WP_DEBUG_LOG włączone, bez własnej ścieżki [6] | 200 z wierszami błędów pod wp-content/debug.log | ścieżki, sesje, adresy [1] |
Apache z Options Indexes, katalog bez pliku indeksu [7] [8] | 200 ze spisem plików | CWE-548 [10] |
| nginx z ustawieniami domyślnymi [9] | brak spisu | autoindex off |
- [1] WSTG-CONF-04 — Review Old Backup and Unreferenced Files for Sensitive Information · OWASP Web Security Testing Guide
- [2] CWE-530: Exposure of Backup File to an Unauthorized Control Sphere · MITRE
- [3] wp-config.php — Advanced Administration Handbook · WordPress.org
- [4] Apache 2.x on Unix systems — PHP Manual · The PHP Group
- [5] recover.txt — Vim help: swap file · Vim
- [6] Debugging in WordPress — Advanced Administration Handbook · WordPress.org
- [7] Apache Core Features — dyrektywy Options i DirectoryMatch · Apache Software Foundation
- [8] httpd.conf.in — domyślna konfiguracja Apache HTTP Server · Apache Software Foundation
- [9] Module ngx_http_autoindex_module · nginx
- [10] CWE-548: Exposure of Information Through Directory Listing · MITRE
STATS
wyniki z systemu · tylko liczby zbiorczeTen parametr nie zapisuje odczytu per strona — przebieg zostawia tylko ustalenia, więc liczby sprawdzonych stron i wyników „ok” system nie ma. Pojawią się po wdrożeniu zapisu przebiegów per strona per parametr.
- Otwarte teraz
- 3stron: 2
- Nowe w ostatnim dniu
- 109.09.2026
- Otwarte od początku
- 4stron: 3
- Zamknięte
- 1od początku
- Mediana trwania
- 18 dni 19 hod wykrycia do zamknięcia
| Ustalenie | Skutek | Otwarte teraz | Łącznie | Zamknięte |
|---|---|---|---|---|
| Kopia wp-config.php.bak exposure_wpconfig_bak | PODATNA | 0 | 0 | 0 |
| Kopia wp-config.php~ exposure_wpconfig_tilde | PODATNA | 0 | 0 | 0 |
| Publiczny debug.log exposure_debug_log | PODATNA | 3 | 4 | 1 |
| Listing katalogów exposure_directory_listing | PODATNA | 0 | 0 | 0 |
| Dzień | nowe ustalenia |
|---|---|
| 23.08.2026 | 0 ustaleń |
| 24.08.2026 | 0 ustaleń |
| 25.08.2026 | 0 ustaleń |
| 26.08.2026 | 0 ustaleń |
| 27.08.2026 | 0 ustaleń |
| 28.08.2026 | 0 ustaleń |
| 29.08.2026 | 0 ustaleń |
| 30.08.2026 | 0 ustaleń |
| 31.08.2026 | 0 ustaleń |
| 01.09.2026 | 0 ustaleń |
| 02.09.2026 | 0 ustaleń |
| 03.09.2026 | 0 ustaleń |
| 04.09.2026 | 0 ustaleń |
| 05.09.2026 | 0 ustaleń |
| 06.09.2026 | 0 ustaleń |
| 07.09.2026 | 0 ustaleń |
| 08.09.2026 | 0 ustaleń |
| 09.09.2026 | 1 ustalenie |
| 10.09.2026 | 0 ustaleń |
| 11.09.2026 | 0 ustaleń |
| 12.09.2026 | 0 ustaleń |
| 13.09.2026 | 0 ustaleń |
| 14.09.2026 | 0 ustaleń |
| 15.09.2026 | 0 ustaleń |
| 16.09.2026 | 0 ustaleń |
| 17.09.2026 | 0 ustaleń |
| 18.09.2026 | 0 ustaleń |
| 19.09.2026 | 0 ustaleń |
| 20.09.2026 | 0 ustaleń |
| 21.09.2026 | 0 ustaleń |
- Przebiegów
- 33sposób exposure
- W 30 dni
- 33przebiegów
- Ostatni
- 19.09.2026start przebiegu
- Stron w przebiegach
- —33 przebiegów bez liczby stron
CARD
karta z kodu CREATO_PING, odczyt 16.09.2026| Obszar i ważność | Bezpieczeństwo · wysoka (B09) |
|---|---|
| Workflow i częstotliwość | creato_ping_security_v2 · P3 działa na LAB247cron co 24 h, T1–T3; T4 raz po anomalii · Dokładny skan. dns_integrity porównuje NS, MX, SPF i DMARC z wzorcem z poprzedniego przebiegu. |
| Sonda i helper | sposób exposure · CREATO_PING/helpers/exposure_check.py |
| Testy |
|
| Typ wyniku | 0 do 4 ustaleń, każde osobnym typem: exposure_wpconfig_bak, exposure_wpconfig_tilde, exposure_debug_log, exposure_directory_listing; do zapisu docierają najwyżej 3 (listing odpada w filtrze przebiegu) |
| Jednostka | brak — wynik jakościowy; w dowodzie ścieżka, kod HTTP i długość treści, bez samej treści pliku |
| Próg i reguła | Timeout odpowiedzi 15 s, połączenia 5 s. 403, 404, przekierowanie, błąd sieci i timeout = brak ustalenia. |
| Gdzie leżą pokrętła | CREATO_PING/helpers/exposure_check.py → PROBES, _INDEX_OF, _HREF_PARENT, _soft_200CREATO_PING/helpers/config.py → TIMEOUTS["exposure"], TIMEOUTS["security_connect"]CREATO_PING/helpers/security_runner.py → _TASK_SEVERITIESCREATO_PING/config/incident_policy.toml → [finding] exposure_wpconfig_bak, exposure_wpconfig_tilde, exposure_debug_log, exposure_directory_listing |
| Retencja odczytów | Odczytu per strona nie zapisujemy — zostaje tylko ustalenie w tabeli findings (otwarcie, zamknięcie, dowód). Replay po surowych odczytach dziś niemożliwy. |
| Znane rozbieżności |
|
| Karta przepisana z | CREATO_PING/helpers/exposure_check.py · CREATO_PING/helpers/config.py · CREATO_PING/config/incident_policy.toml · CREATO_PING/helpers/security_runner.py · CREATO_PING/helpers/clickup_writer_v2.py · CREATO_PING/workflows/_prod/creato_ping_security_v2.json · odczyt 16.09.2026 |
Kopie wp-config.php: powaga pilna, skutek PODATNA, subtask z priorytetem pilnym. debug.log: helper daje pilną (przechodzi filtr), polityka nadpisuje na wysoką — subtask wysoki, status PODATNA. Listing: helper daje normalną, więc filtr przebiegu odrzuca ustalenie przed zapisem i subtask nie powstaje. Helper nie wysyła sygnału zamknięcia.
| Ustalenie | Powaga | Pewność | Skutek | Subtask / alarm | Co zrobić |
|---|---|---|---|---|---|
| Kopia wp-config.php.bakexposure_wpconfig_bak | Pilne | Ewidentne | PODATNA | tak / tak | Usuń plik z serwera, zmień hasło do bazy. |
| Kopia wp-config.php~exposure_wpconfig_tilde | Pilne | Ewidentne | PODATNA | tak / tak | Usuń plik z serwera, zmień hasło do bazy. |
| Publiczny debug.logexposure_debug_log | Wysokie | Ewidentne | PODATNA | tak / nie | Wyłącz WP_DEBUG_LOG na produkcji i usuń plik. |
| Listing katalogówexposure_directory_listing | Wysokie | Ewidentne | PODATNA | tak / nie | Wyłącz Indexes w .htaccess lub konfiguracji serwera. |
LOOP
pętli: 2Trafności jeszcze nie liczymy: zamknięcie subtaska nie niesie dziś werdyktu (prawdziwy / fałszywy / nie dało się sprawdzić). Cztery liczby pojawią się, gdy każde zamknięcie dostanie werdykt — to warunek startu pętli 1.
Sygnał: Tarcze antybotowe hostingu, strony parkingowe i serwery catch-all odpowiadają 200 na każdą ścieżkę, więc sondy oparte na kodzie 200 dawały „wystawiony” wszędzie. Równocześnie sondy na wolnych hostingach odpowiadały po około 15 s, a limit 5 s ucinał je bez śladu. · dotyczy też: Ekspozycja .env, Ekspozycja .htaccess.bak, Dostępność xmlrpc.php, REST API: enumeracja użytkowników, Ekspozycja .git/HEAD, Dostępność readme.html, Dostępność wp-cron.php, Ekspozycja kopii zapasowych, Ekspozycja zrzutu bazy, Ekspozycja manifestów dev, Ekspozycja .DS_Store
- 1. Zbiórkaręcznieodczyt z nocnego skanu, bez zapisu per strona
- 2. Werdyktręcznieprzegląd skanera: 200 na wszystko i ciche timeouty to fałszywe wyniki
- 3. Miarabrakliczników trafności wtedy nie było
- 4. Kartabrakkarta parametru powstała 2026-09-16
- 5. Zmianazrobionestrażnik ścieżki, 15 s, logowanie błędów
- 6. Replaybrakbrak zapisanych odczytów do replayu
| Data | Zmiana | Powód | Wpływ na system | Commit · replay |
|---|---|---|---|---|
| 2026-09-05 | Przed sondami GET losowej, nieistniejącej ścieżki; odpowiedź 200 z treścią = zero sond i jedno ustalenie exposure_scan_unreliable (niska powaga, bez subtaska).helpers/exposure_check.py · config/incident_policy.toml | Odpowiedź 200 na losową ścieżkę dowodzi, że kod 200 na tym serwerze nic nie znaczy; dalsze sondowanie tarczy grozi banem IP monitoringu. | cały system Obejmuje wszystkie sondy ekspozycji naraz i wprowadza typ „nie dało się sprawdzić”; tę samą konwencję dostało wykrywanie wtyczek. Ustalenie ma niską powagę, więc filtr przebiegu je odrzuca i w produkcji nie zostawia śladu. | b0fc77cbez replayubez zapisu zatwierdzenia |
| 2026-09-05 | Limit odpowiedzi z 5 s na 15 s i połączenia z 2 s na 5 s, przeniesione do config.py; błąd sieci sondy logowany zamiast cichego pustego wyniku; do 4 sond naraz na stronę.helpers/config.py · helpers/exposure_check.py · helpers/html_fetch.py · helpers/wp_fingerprint.py | Wolne hostingi odpowiadały po około 15 s, a pusty wynik po timeoucie był nieodróżnialny od „sprawdzone, czysto”. | cały system Limit połączenia 5 s przejęło wspólne pobieranie HTML całego skanu bezpieczeństwa i wykrywanie wersji — strony z wolnym TLS przestały wypadać z całego skanu. | b0fc77cbez replayubez zapisu zatwierdzenia |
Sygnał: Brak pamięci podczas skanu: publiczny debug.log jednej ze stron był bardzo duży, a klient HTTP buforował całą odpowiedź. · dotyczy też: Sitemap.xml, Ekspozycja .env, Ekspozycja .htaccess.bak, Dostępność xmlrpc.php, REST API: enumeracja użytkowników, Ekspozycja .git/HEAD, Dostępność readme.html, Dostępność wp-cron.php, Ekspozycja kopii zapasowych, Ekspozycja zrzutu bazy, Ekspozycja manifestów dev, Ekspozycja .DS_Store
- 1. Zbiórkaręcznieodczyt z nocnego skanu, bez zapisu per strona
- 2. Werdyktręcznieawaria procesu przypisana ścieżce debug.log
- 3. Miarabrakliczników trafności wtedy nie było
- 4. Kartabrakkarta parametru powstała 2026-09-16
- 5. Zmianazrobionestrumień z limitem 64 KB
- 6. Replaybrakbrak zapisanych odczytów do replayu
| Data | Zmiana | Powód | Wpływ na system | Commit · replay |
|---|---|---|---|---|
| 2026-07-19 | Odpowiedź sondy czytana strumieniem do 64 KB; do oceny idzie pierwsze 5000 znaków.helpers/exposure_check.py · helpers/html_fetch.py · helpers/sitemap_check.py | Do rozpoznania ekspozycji wystarcza początek pliku; zmiana dotyczy sposobu czytania, nie werdyktu. | cały system Brak pamięci w helperze zatrzymywał cały proces skanu bezpieczeństwa partii stron; ten sam limit dostało sprawdzenie sitemap. | 343b699bez replayubez zapisu zatwierdzenia |