Dostępność wp-cron.php
ważność średniamierzonysposób exposure
Czy wp-cron.php jest dostępny z zewnątrz. Może być nadużyty do przeciążenia serwera.
WIKI
artykuł z 16.09.2026 · źródeł 7Dostępność wp-cron.php to parametr monitoringu stron internetowych, który sprawdza, czy plik wp-cron.php w katalogu głównym WordPressa odpowiada na żądania z zewnątrz. Pomiar kończy się jednym z trzech wyników: plik odpowiada, dostęp jest zablokowany albo nie udało się uzyskać odpowiedzi. Nagłówek pliku opisuje go jako pseudodemona crona, który uruchamia zaplanowane zadania WordPressa [3].
Jak działa
WP-Cron przy każdym wczytaniu strony sprawdza listę zaplanowanych zadań i uruchamia te, na które przyszła pora [1]. W przeciwieństwie do systemowego crona nie działa stale: zadanie zaplanowane na 14:00 wykona się dopiero przy pierwszym wczytaniu strony, np. o 17:00 [1].
Uruchomienie odbywa się przez HTTP. Funkcja spawn_cron zakłada blokadę i wysyła do wp-cron.php na tej samej stronie żądanie pętli zwrotnej (ang. loopback) z parametrem doing_wp_cron, z limitem czasu 0,01 s i bez czekania na odpowiedź [4]. Od wersji 6.9 jest to wywoływane na akcji shutdown, bo wcześniejsze wywołanie wydłużało czas do pierwszego bajtu strony [4]. Sam wp-cron.php najpierw wczytuje środowisko WordPressa przez wp-load.php, potem sprawdza, czy są zadania gotowe do uruchomienia i czy blokada należy do tego wywołania, i dopiero wtedy wykonuje zadania [3].
Stała DISABLE_WP_CRON w wp-config.php wyłącza WP-Cron [5]: wizyty przestają wywoływać wp-cron.php [4]. Podręcznik zaleca wtedy harmonogram systemu, np. wpis crontab z poleceniem wget --delete-after http://YOUR_SITE_URL/wp-cron.php, uruchamiany raz na dobę albo co 15 minut [2]. Nagłówek wp-cron.php zaznacza, że ta stała i bezpośrednie wywołanie pliku wzajemnie się wykluczają, a wywołanie bezpośrednie działa bez niej [3]. Stała nie zamyka więc pliku, tylko przenosi wywołanie z wizyt na zewnętrzny harmonogram.
Standardy i specyfikacje
- Plugin Handbook: Cron opisuje model wywołania przy wczytaniu strony [1], a rozdział o harmonogramie systemu — wyłączenie tego modelu i wywoływanie
wp-cron.phpprzez HTTP [2]. - wp-config.php opisuje
ALTERNATE_WP_CRON, tryb z przekierowaniem przeglądarki, stosowany zwykle wtedy, gdy zaplanowane wpisy nie publikują się na czas, orazWP_CRON_LOCK_TIMEOUT: proces crona nie uruchomi się częściej niż raz na podaną liczbę sekund [5]. - CVE-2023-22622: WordPress do wersji 6.1.1 uzależnia wykonanie
wp-cron.php, a z nim aktualizacji bezpieczeństwa, od nieprzewidywalnych wizyt, a przewodniki instalacji i bezpieczeństwa o tym nie wspominają. NVD ocenia wpis na 5,3 w CVSS 3.1 [7].
Zagrożenia i skutki
Obciążenie żądaniami. W raporcie z 2023 roku w programie ujawniania podatności Departamentu Obrony USA na HackerOne badacz opisał wp-cron.php jako cel odmowy usługi: po około tysiącu żądań wysłanych skryptem strona zwracała kod 502. Raport zamknięto jako rozwiązany [6]. Kod pliku pokazuje, skąd koszt: każde żądanie wczytuje całe środowisko WordPressa, zanim sprawdzi listę zadań i blokadę [3]. Blokada ogranicza powtórne wykonanie zadań, a nie liczbę żądań [3] [5]. Zalecane w raporcie DISABLE_WP_CRON z cronem systemowym [6] nie odcina pliku od żądań z zewnątrz [3].
Opóźnione zadania. Na stronie z małym ruchem zadania wykonują się z opóźnieniem [1], co CVE-2023-22622 wiąże z opóźnieniem aktualizacji bezpieczeństwa [7]. Zablokowanie wp-cron.php na serwerze bez innego harmonogramu daje ten sam skutek, bo pętla zwrotna i polecenie wget wywołują ten sam adres [2] [4].
Publiczny plik to norma. Mechanizm wymaga, żeby wp-cron.php odpowiadał na żądania HTTP: wywołuje go sam WordPress [4] albo zewnętrzny harmonogram [2]. Odpowiedź 200 jest domyślnym stanem instalacji, a nie błędem konfiguracji.
Przykłady
| Konfiguracja | Kto wywołuje wp-cron.php | Odpowiedź na GET /wp-cron.php |
|---|---|---|
| Domyślna [1] [4] | WordPress przy wizycie, pętlą zwrotną | 200, pusta treść [3] |
DISABLE_WP_CRON i crontab z wget [2] | harmonogram systemu przez HTTP | 200, plik nadal publiczny [3] |
ALTERNATE_WP_CRON [5] | odwiedzający po przekierowaniu, plik dołączany w tym samym żądaniu [4] | 200 |
| Plik zablokowany, brak harmonogramu | pętla zwrotna nie dociera do pliku [4] | 403, zadania czekają |
| Seria żądań wysłanych skryptem [6] | skrypt obciążający | 502 przy przeciążeniu serwera |
- [1] Cron — Plugin Handbook · WordPress Developer Resources
- [2] Hooking WP-Cron Into the System Task Scheduler — Plugin Handbook · WordPress Developer Resources
- [3] wp-cron.php (wordpress-develop, trunk) · WordPress Core
- [4] wp-includes/cron.php (wordpress-develop, trunk) · WordPress Core
- [5] wp-config.php — Advanced Administration Handbook · WordPress.org
- [6] Report #1888723 — WordPress application vulnerable to DoS attack via wp-cron.php · HackerOne / U.S. Dept Of Defense
- [7] CVE-2023-22622 · NIST (National Vulnerability Database)
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
- 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 · średnia (B17) |
|---|---|
| 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 albo 1 ustalenie exposure_wpcron (powaga niska w helperze, normalna w polityce) — dziś odrzucane przed zapisem |
| Jednostka | brak — wynik jakościowy |
| Próg i reguła | Timeout odpowiedzi 15 s, połączenia 5 s. Reguła: kod 200 = exposure_wpcron. |
| Gdzie leżą pokrętła | CREATO_PING/helpers/exposure_check.py → PROBES (/wp-cron.php, reguła 200)CREATO_PING/helpers/config.py → TIMEOUTS["exposure"], TIMEOUTS["security_connect"]CREATO_PING/helpers/security_runner.py → _TASK_SEVERITIESCREATO_PING/config/incident_policy.toml → [finding] exposure_wpcron |
| Retencja odczytów | Nic: helper nadaje powagę poniżej wysokiej, filtr przebiegu odrzuca ustalenie przed zapisem, a produkcja idzie z --no-stats. Nie ma ani odczytu per strona, ani ustalenia, ani licznika — statystyki i replay niemożliwe. |
| Znane rozbieżności |
|
| Karta przepisana z | CREATO_PING/helpers/exposure_check.py · CREATO_PING/helpers/security_runner.py · CREATO_PING/config/incident_policy.toml · CREATO_PING/workflows/_prod/creato_ping_security_v2.json · odczyt 16.09.2026 |
Brak skutku w produkcji: helper nadaje powagę niską, a filtr przebiegu przepuszcza do zapisu tylko pilną i wysoką, więc ustalenie odpada, zanim przeczyta je polityka incydentów. Przebieg idzie z --no-stats, więc nie zostaje nawet licznik. Nie powstaje subtask, zmiana statusu strony ani ustalenie w bazie.
| Ustalenie | Powaga | Pewność | Skutek | Subtask / alarm | Co zrobić |
|---|---|---|---|---|---|
| Dostępny wp-cron.phpexposure_wpcron | Normalne | Ewidentne | bez wpływu | nie / nie | Ustaw DISABLE_WP_CRON i cron systemowy. |
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 plików wrażliwych, Ekspozycja .htaccess.bak, Dostępność xmlrpc.php, REST API: enumeracja użytkowników, Ekspozycja .git/HEAD, Dostępność readme.html, 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 plików wrażliwych, Ekspozycja .env, Ekspozycja .htaccess.bak, Dostępność xmlrpc.php, REST API: enumeracja użytkowników, Ekspozycja .git/HEAD, Dostępność readme.html, 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 |