Ekspozycja .htaccess.bak
ważność średniamierzonysposób exposure
Kopia .htaccess wystawiona publicznie. Ujawnia reguły WAF, ścieżki wewnętrzne i lokalizację .htpasswd — mapę zabezpieczeń serwera.
Do 2026-09-16 katalog obiecywał tę ścieżkę przy plikach wrażliwych, ale żadna sonda jej nie próbowała.
WIKI
artykuł z 16.09.2026 · źródeł 10Ekspozycja .htaccess.bak to parametr monitoringu stron internetowych, który sprawdza, czy pod adresem /.htaccess.bak serwer WWW oddaje treść kopii pliku konfiguracyjnego .htaccess, zamiast odmówić dostępu albo zgłosić brak pliku. Pomiar kończy się jednym z trzech wyników: kopia dostępna, niedostępna albo nie udało się uzyskać odpowiedzi. Pliki .htaccess to rozproszone pliki konfiguracyjne serwera Apache: umieszczone w katalogu dokumentów zmieniają konfigurację tego katalogu i wszystkich jego podkatalogów [1].
Jak działa
Nazwę pliku konfiguracyjnego wyznacza dyrektywa AccessFileName, domyślnie .htaccess [2]. O tym, które dyrektywy z pliku serwer uwzględni, decydują AllowOverride i AllowOverrideList [1]. Dokumentacja Apache zaleca umieszczanie konfiguracji w pliku głównym, a .htaccess przewiduje dla sytuacji, w których twórcy treści muszą zmieniać konfigurację bez uprawnień administratora, typowych dla hostingu z panelem [1]. WordPress używa .htaccess do sterowania tym, jak Apache podaje pliki z katalogu głównego, zwłaszcza do przyjaznych odnośników; podstawowy blok zaczyna się od # BEGIN WordPress i zawiera dyrektywy RewriteEngine i RewriteRule [8].
Kopia z dodatkowym rozszerzeniem nie jest dla serwera plikiem konfiguracyjnym, tylko zwykłym plikiem w katalogu dokumentów. OWASP opisuje, że ręczne kopie typu file.bak lub file.old są obsługiwane inaczej niż oryginał i zwykle podawane jako tekst [9].
Domyślny plik konfiguracyjny Apache zawiera jednak blok <Files ".ht*"> z dyrektywą Require all denied, opisany jako ochrona plików .htaccess i .htpasswd przed odczytem przez klientów [3]. W sekcji <Files> gwiazdka oznacza dowolny ciąg znaków [2], więc wzorzec obejmuje także .htaccess.bak. Debian stosuje w tym miejscu wyrażenie regularne <FilesMatch "^\.ht"> z tym samym opisem [4]. Wyrażenie nie ma kotwicy końca, więc również pasuje do kopii. Apache z konfiguracją domyślną odmawia zatem dostępu do .htaccess.bak, a wyciek wymaga innego serwera albo zmienionej konfiguracji.
Nginx. Nginx nie ma plików konfiguracyjnych na poziomie katalogu, takich jak .htaccess; całą konfigurację ustawia administrator na poziomie serwera [6]. Poradnik WordPressa dla nginx zaleca osobny blok location ~ /\. z deny all, który blokuje pliki ukryte, m.in. .htaccess, .htpasswd i .DS_Store [6]. Strona przeniesiona z Apache bez takiego bloku zostawia kopię w katalogu, którego żadna reguła nie chroni.
Zbyt wąska reguła. Przykład ochrony plików wrażliwych w dokumentacji WordPressa używa wzorca ^(wp-config\.php|\.htaccess|\.htpasswd|debug\.log)$ [8]. Kotwica końca sprawia, że wzorzec nie obejmuje .htaccess.bak. Kopia pozostaje chroniona tylko wtedy, gdy w konfiguracji głównej działa ogólna reguła dla .ht* [3].
Inna nazwa kopii. Plik skopiowany jako htaccess.bak albo htaccess.txt, bez kropki na początku, nie pasuje do wzorca .ht* [2] [3].
Standardy i specyfikacje
- Apache HTTP Server, samouczek
.htaccesswymienia dwa powody, by woleć plik główny: wydajność i bezpieczeństwo [1]. - Apache Core Features definiuje
AccessFileName,AllowOverridei składnię wzorców w<Files>[2]. - OWASP WSTG-CONF-04 zalicza kopie i pliki bez odnośników pozostawione w katalogach serwera do źródeł wycieku informacji i zauważa, że stare kopie mogą zawierać błędy poprawione w nowszych wersjach [9].
- CWE-530 („Exposure of Backup File to an Unauthorized Control Sphere”) to kopia zapasowa zapisana w katalogu lub archiwum dostępnym dla nieuprawnionych; MITRE opisuje kopie przemianowane np. na rozszerzenie
.~bk[10].
Zagrożenia i skutki
Ścieżka do pliku haseł. Plik .htaccess może włączać uwierzytelnianie; przykład w dokumentacji Apache zawiera AuthType Basic i ścieżkę AuthUserFile do pliku haseł [1]. Dokumentacja WordPressa podaje taki blok do ochrony wp-login.php, z pełną ścieżką bezwzględną do .htpasswd [8]. Moduł mod_authn_file wymaga, by plik haseł leżał poza drzewem dokumentów, bo inaczej klient może go pobrać [5]. Kopia pokazuje, gdzie ten plik leży.
Zapora aplikacji i ścieżki serwera. Wordfence ładuje swoją zaporę przed WordPressem przez dyrektywę php_value auto_prepend_file w .htaccess, z bezwzględną ścieżką do pliku wordfence-waf.php [7]. Kopia ujawnia więc obecność zapory, położenie jej pliku i układ katalogów na dysku.
Wyjątki dostępu. Dokumentacja WordPressa pokazuje ograniczanie dostępu do wybranych adresów IP dyrektywami Require ip w bloku <RequireAny> [8]. Odczytana kopia wskazuje, z których adresów zabezpieczenie jest pomijane.
Nieaktualne reguły. Kopia sprzed zmiany pokazuje stan konfiguracji, który mógł zostać poprawiony. OWASP zwraca uwagę, że stara wersja pliku może zawierać błędy usunięte w nowej [9].
Przykłady
| Sytuacja | Odpowiedź na GET /.htaccess.bak | Znaczenie |
|---|---|---|
Apache z domyślnym blokiem <Files ".ht*"> [3] | 403 | kopia chroniona tą samą regułą co .htaccess |
Apache w Debianie z <FilesMatch "^\.ht"> [4] | 403 | wyrażenie obejmuje kopię |
Tylko reguła z kotwicą końca dla \.htaccess [8] | 200 z dyrektywami | reguła nie obejmuje kopii |
| nginx bez bloku dla plików ukrytych [6] | 200 z dyrektywami | nginx nie traktuje pliku jako konfiguracji |
nginx z location ~ /\. i deny all [6] | 403 | plik istnieje, ale nie jest podawany |
Kopia nazwana htaccess.bak, bez kropki [2] | zależy od serwera | poza wzorcem .ht* |
Kopia z AuthUserFile i ścieżką w katalogu dokumentów [5] | 200 z dyrektywami | plik haseł do pobrania pod znanym adresem |
- [1] Apache HTTP Server Tutorial: .htaccess files · Apache Software Foundation
- [2] Apache Core Features — AccessFileName, AllowOverride, Files · Apache Software Foundation
- [3] httpd.conf.in — domyślna konfiguracja Apache HTTP Server · Apache Software Foundation
- [4] apache2.conf.in — konfiguracja pakietu apache2 w Debianie · Debian Apache Maintainers
- [5] Apache Module mod_authn_file · Apache Software Foundation
- [6] Nginx — Advanced Administration Handbook · WordPress.org
- [7] Enable WordFence — OpenLiteSpeed Documentation · OpenLiteSpeed
- [8] Apache HTTPD / .htaccess — Advanced Administration Handbook · WordPress.org
- [9] WSTG-CONF-04 — Review Old Backup and Unreferenced Files for Sensitive Information · OWASP Web Security Testing Guide
- [10] CWE-530: Exposure of Backup File to an Unauthorized Control Sphere · 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.
Ten parametr nie otworzył jeszcze żadnego ustalenia w bazie LAB247. Pusto nie znaczy „czysto” — znaczy, że nic nie przekroczyło reguły.
- Przebiegów
- 33sposób exposure
- W 30 dni
- 0przebiegów
- Ostatni
- 19.09.2026start przebiegu
- Stron w przebiegach
- —33 przebiegów bez liczby stron
CARD
karta z kodu CREATO_PING, odczyt 22.09.2026Jak ten parametr trafia do ClickUpa: wynik sondy to linia w subtasku 2. Pomiar, a usterka, którą otwiera — linia w subtasku 1. Podsumowanie (z identyfikatorem CWE i kategorią OWASP), skąd liczy się wskaźnik zagrożenia i status strony. Projekcja z bazy skanera odświeża oba subtaski co godzinę. Do 22.09 każde ustalenie dostawało własny subtask i status ze starego słownika (PODATNA, WARNING…) — te słowa zostały jeszcze w części opisów pomiaru niżej jako język wewnętrzny sond.
| Obszar i ważność | Bezpieczeństwo · średnia (B22) |
|---|---|
| Workflow i częstotliwość | creato_ping_security_v2 · P3 działa na LAB247Skaner 2.0, rytm „p3” / „bezpieczenstwo”: premium co 6 h, reszta co 24 h (tier 1–3), co 9 dni (tier 4) · 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 albo 1 ustalenie exposure_htaccess_bak |
| Jednostka | brak — wynik jakościowy; w dowodzie ścieżka, kod HTTP i długość treści. Pliki sekretów (.env, kopie wp-config, debug.log, zrzut bazy, archiwum, phpinfo) mają dowód „tylko skrót”: długość i skrót treści, nigdy fragment. |
| Próg i reguła | Timeout odpowiedzi 15 s, połączenia 5 s. Reguła: 200 + początek nie jest HTML-em + marker dyrektywy. |
| Gdzie leżą pokrętła | CREATO_PING/helpers/exposure_check.py → PROBES (reguła htaccess_text), _HTACCESS_MARKERS, _HTML_MARKERS, _text_file_matchesCREATO_PING/helpers/config.py → TIMEOUTS["exposure"], TIMEOUTS["security_connect"]CREATO_PING/helpers/security_runner.py → do_writera (bramka gate z polityki; sito powagi zniknęło 18.09)CREATO_PING/config/incident_policy.toml → [finding] exposure_htaccess_bak |
| Retencja odczytów | Surowy pomiar jako NIEZMIENNY wiersz tabeli `odczyty` w bazie skanera (wejście, wyjście, dowody, sha karty sondy i helpera, commit kodu) — trigger odrzuca każdą zmianę. Okno retencji z kohorty: 90 dni premium, 30 dni reszta; poza oknem zostają odczyty z werdyktem problemu, akcją albo etykietą, bo replay reguł ich potrzebuje (`skaner/retencja.py`). Do LAB247 ten kanał nie idzie (do bazy serwisu jadą dziś tylko sprawdzenia dostępności), więc poza odczytem zostaje werdykt w tabeli `werdykty` i sprawa w tabeli `sprawy`. |
| 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/skaner/adapter_clickup.py · CREATO_PING/skaner/sprawy.py · CREATO_PING/skaner/usterki.toml · CREATO_PING/skaner/ocena.py · odczyt 22.09.2026 |
exposure_htaccess_bak: bramka polityki otwarta (gate=true) → sprawa w skanerze → Kopia .htaccess do pobrania — waga 3 → ocena 5–6 (żółty), status strony „sredni”, dopóki sprawa jest otwarta. Kolejne przebiegi odświeżają opis i datę; helper nie wysyła sygnału zamknięcia.
| Kod | Finding | Severity | Pewność | Skutek | Finding / alarm | Waga → ocena | Co zrobić |
|---|---|---|---|---|---|---|---|
| B22.01 | Kopia .htaccess.bakexposure_htaccess_bak | Wysoka | Ewidentne | otwarta podatność | tak / nie | waga 3 → ocena 5–6 (żółty) | Usuń plik z serwera. |
| Kod i klucz | B22.01 · exposure_htaccess_bak · w tabeli typów |
|---|---|
| Co znaczy | Kopia .htaccess ujawnia reguły WAF, ścieżki i lokalizację .htpasswd. |
| Kiedy powstaje | GET /.htaccess.bak: status == 200, początek treści nie jest HTML-em (ta sama reguła co zrzut SQL), a pierwsze 5000 znaków (lower) zawiera któryś marker: 'rewriteengine', 'rewriterule', '<ifmodule', 'order allow,deny', 'require all denied', 'authuserfile', 'php_value', 'errordocument'.Markery :170-173, ocena :195-196, :250-264. |
| Severity · pewność | Wysoka · Ewidentne |
| Skutek dla strony | otwarta podatność · zakłada Finding · alarm nie |
| Waga → ocena | waga 3 → ocena 5–6 (żółty) |
| Klasyfikacja | CWE: CWE-530 (Exposure of Backup File to an Unauthorized Control Sphere)OWASP Top 10:2025: A01:2025 Broken Access ControlOWASP ASVS 5.0.0: 13.4.7OCSF 1.9.0: Vulnerability Finding (class_uid 2002) |
| Rekord OCSF | finding_info.analytic.uid = "B22.01" · analytic.name = "exposure_htaccess_bak" · finding_info.types = ["B22 Ekspozycja .htaccess.bak"] |
| Co zrobić | Usuń plik z serwera. |
| Wersje typu |
|
LOOP
pętli: 3Trafnoś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, Kopie wp-config.php, 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, Kopie wp-config.php, Ekspozycja .env, 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 |
Sygnał: Przegląd kodu nowych sond przed wdrożeniem: reguła odrzucała plik, gdy HTML pojawił się gdziekolwiek w pierwszych 5000 znaków, a prawdziwy zrzut bazy WordPressa ma znaczniki HTML w treści wpisów — pilny wyciek zostałby przeoczony. · dotyczy też: Ekspozycja zrzutu bazy
- 1. Zbiórkabrakreguła poprawiona przed pierwszym przebiegiem
- 2. Werdyktręcznieprzegląd kodu: zrzut WordPressa zawiera HTML w treści wpisów
- 3. Miarabrakliczników trafności wtedy nie było
- 4. Kartabrakkarta parametru powstała 2026-09-16
- 5. Zmianazrobionerozstrzyga początek pliku
- 6. Replaybrakpo wdrożeniu suchy przebieg na żywo, bez zapisanych odczytów
| Data | Zmiana | Powód | Wpływ na system | Commit · replay |
|---|---|---|---|---|
| 2026-09-16 | Plik uznany za stronę HTML tylko wtedy, gdy zaczyna się od <html, <!doctype, <head albo <body; dotyczy zrzutów .sql i kopii .htaccess.bak.helpers/exposure_check.py | Strona błędu zaczyna się od HTML-a, a zrzut bazy od komentarza albo CREATE; szukanie HTML-a w całej treści dawało fałszywy negatyw na ustaleniu pilnym. | tylko ten parametr | 193591fbez replayubez zapisu zatwierdzenia |