DISABLE_WP_CRON = true nie zabezpiecza punktu końcowego wp-cron.php; zatrzymuje jedynie proces WordPressa przed wysyłaniem własnego żądania loopback. Plik pozostaje dostępny z sieci, więc każdy może go wywołać i wymusić pełny proces bootstrap WordPressa.

Ten ukryty punkt wejścia może marnować zasoby CPU, pamięć oraz procesy PHP (workers), szczególnie na obciążonych stronach. Jeśli myślałeś, że zamknąłeś te drzwi, to jeszcze tego nie zrobiłeś.

Dlaczego to ustawienie jest często błędnie rozumiane

Gdy WordPress wykonuje zaplanowane zadanie, najpierw próbuje wysłać szybkie żądanie HTTP do własnego pliku wp-cron.php. Ustawienie DISABLE_WP_CRON na true instruuje rdzeń (core) systemu, aby pominął to wewnętrzne żądanie. Rdzeń nie zmienia konfiguracji serwera WWW ani nie dodaje warstwy uwierzytelniania do wp-cron.php. Skrypt pozostaje publicznym adresem URL, który zwraca status 200, nawet jeśli proces PHP zostanie przerwany wcześniej.

Atakujący, który odkryje ten adres URL, może wysyłać do niego wielokrotne zapytania, zmuszając WordPressa do każdorazowego ładowania wszystkich wtyczek, motywów i bazy danych. Na hostingu współdzielonym lub na stronie z ograniczoną liczbą procesów PHP, ten pojedynczy punkt końcowy może stać się wektorem ataku typu denial-of-service (DoS).

Co tak naprawdę należy zrobić

Aby przenieść zaplanowane zadania do harmonogramu na poziomie systemu (cron, systemd-timer itp.) i zamknąć publiczny dostęp, wykonaj poniższe pięć kroków.

1. Wyłącz wewnętrzny loopback

Dodaj linię

define( 'DISABLE_WP_CRON', true );

do pliku wp-config.php. Powstrzyma to WordPressa przed próbami wysyłania własnych żądań HTTP, ale nie zatrzyma wywołań zewnętrznych.

2. Zablokuj wp-cron.php na poziomie serwera WWW

W Nginx, na przykład, wstaw blok location, który zwraca 403 Forbidden:

location = /wp-cron.php {
    return 403;
}

Serwer odrzuci teraz żądanie, zanim PHP w ogóle zostanie uruchomione, co eliminuje koszt procesu bootstrap.

3. Dodaj mu-plugin jako zabezpieczenie

Utwórz wtyczkę typu must-use (umieszczoną w wp-content/mu-plugins), która loguje każde żądanie docierające do wp-cron.php i kończy działanie błędem 403. Pozwoli to przechwycić żądania, które w jakiś sposób ominą regułę serwera – na przykład poprzez inny hostname lub regułę na brzegu sieci CDN (edge rule).

4. Wyłącz asynchroniczne wywołania Action Scheduler

Wiele wtyczek korzysta z biblioteki Action Scheduler, która może generować własne żądania loopback. Podepnij się pod hook action_scheduler_queue_runner i przerwij działanie dla żądań spoza CLI, zapobiegając próbom otwierania własnych „drzwi” przez bibliotekę.

5. Odepnij runner kolejki od hooka WP-Cron

Usuń domyślny runner kolejki Action Scheduler, który jest podpięty do hooka wp cron. Dzięki temu kolejka będzie uruchamiana tylko wtedy, gdy jawnie wywołasz ją z linii komend.

Uruchamianie zadań we właściwy sposób

Po zabezpieczeniu publicznego punktu końcowego użyj harmonogramu systemowego, aby wywoływać WordPressa raz na minutę (lub z inną częstotliwością, jakiej potrzebujesz) za pomocą WP-CLI:

wp cron event run --due-now

Ta pojedyncza komenda przetwarza zdarzenia cron rdzenia oraz kolejkę Action Scheduler w kontrolowanym środowisku, korzystając z tego samego procesu PHP, którego użyłbyś do dowolnego innego zadania CLI.

Korzyści, które możesz zmierzyć

  • Bezpieczeństwo – Żaden nieautoryzowany użytkownik nie może uruchomić ciężkich zadań w tle.
  • Wydajność – Procesy PHP pozostają dostępne dla rzeczywistych odwiedzających; znikają nagłe skoki zużycia pamięci spowodowane przypadkowymi uderzeniami w cron.
  • Niezawodność – Planowanie staje się proaktywne; dokładnie wiesz, kiedy zadanie zostanie wykonane, ponieważ jest ono sterowane przez systemowy cron, a nie przez ładowanie strony przez odwiedzającego.

Na co zwrócić uwagę po wprowadzeniu zmian

Nie polegaj na kodzie statusu HTTP pliku wp-cron.php; może on nadal zwracać 200, nawet jeśli zostanie zablokowany przez PHP. Zamiast tego:

  • Monitoruj rozmiar kolejki Action Scheduler. Rosnąca kolejka często sygnalizuje pominięte uruchomienia.
  • Sprawdzaj logi serwera pod kątem wpisów „403” pochodzących z bloku location dla wp-cron.php.
  • Obserwuj liczbę procesów PHP-FPM lub FastCGI podczas szczytowego natężenia ruchu, aby potwierdzić spadek obciążenia.

Uwaga ostrzegawcza

Niektórzy administratorzy pozostawiają DISABLE_WP_CRON ustawione na false, ponieważ polegają na tym, że strony o niskim natężeniu ruchu naturalnie wyzwalają crona. Powyższa metoda całkowicie eliminuje tę zależność, ale dodaje krok konserwacyjny: musisz upewnić się, że harmonogram systemowy działa niezawodnie. Jeśli demon cron serwera ulegnie awarii, zaplanowane zadania zostaną wstrzymane. Połącz tę konfigurację z monitorowaniem usługi systemowego crona, aby uniknąć tej pułapki.

Podsumowując: ustawienie DISABLE_WP_CRON na true jedynie powstrzymuje WordPressa przed wysyłaniem żądań do samego siebie; nie zamyka ono publicznego punktu końcowego wp-cron.php. Zablokuj plik na poziomie serwera WWW, dodaj rozwiązanie zapasowe w postaci mu-plugin i przekieruj wszystkie zaplanowane zadania przez harmonogram systemowy za pomocą WP-CLI. Dzięki temu zabezpieczysz stronę, zmniejszysz zbędną pracę procesów PHP i zyskasz precyzyjną kontrolę nad czasem wykonywania zadań w tle.