Słowniczek

Czym są nonce w WordPressie? Tokeny bezpieczeństwa wyjaśnione

5 sierpnia 2026

Nonce w WordPressie to token bezpieczeństwa dołączany do formularzy, linków i żądań AJAX, dzięki któremu WordPress może sprawdzić, że żądanie zostało świadomie wywołane przez konkretnego zalogowanego użytkownika. Nazwa pochodzi z kryptografii i oznacza number used once, czyli liczbę użytą raz, ale tutaj jest lekko myląca: nonce w WordPressie nie jest liczbą, nie jest używany tylko raz i technicznie stanowi skrót powiązany z użytkownikiem, sesją i jedną konkretną akcją. Pozostaje ważny do 24 godzin. Głównym zagrożeniem, przed którym broni nonce, jest cross-site request forgery (CSRF), czyli atak, w którym złośliwa strona po cichu wysyła żądanie z Twoją zalogowaną sesją, na przykład po to, żeby usunąć wpis albo zmienić ustawienie. Nonce działa i właśnie dlatego najczęstszy błąd bezpieczeństwa leży po drugiej stronie: nonce dowodzi intencji, a nie uprawnień. Kod wtyczki, który sprawdza nonce, ale zapomina o kontroli uprawnień funkcją current_user_can(), to jedno z najczęstszych źródeł publikowanych podatności WordPressa.

Czym jest nonce i dlaczego nazwa wprowadza w błąd?

W kryptografii nonce to wartość używana dokładnie raz i nigdy więcej, i to właśnie czyni ją przydatną wobec ataków typu replay. WordPress pożyczył nazwę, ale nie ścisłą definicję. Nonce w WordPressie to krótki skrót generowany z czterech składników: akcji, do której należy, identyfikatora i tokenu sesji bieżącego użytkownika, aktualnego okna czasowego oraz tajnych kluczy z pliku wp-config.php. Taka konstrukcja ma trzy praktyczne konsekwencje:

  • Nonce jest osobisty. Token wygenerowany dla jednego użytkownika nie przejdzie weryfikacji u żadnego innego, więc nie da się go współdzielić ani wykraść z publicznej strony.
  • Nonce dotyczy konkretnej akcji. Token utworzony dla akcji delete-post_42 jest bezwartościowy dla delete-post_43 i dla każdej innej operacji. Dlatego zaszycie na sztywno ogólnej nazwy akcji osłabia cały mechanizm.
  • Nonce da się użyć wielokrotnie w czasie jego życia. Ten sam token przechodzi weryfikację dowolnie wiele razy przez maksymalnie 24 godziny. WordPress opisuje to wprost, więc sam nonce nie chroni przed powtórzeniem żądania, które atakujący już przechwycił.

Oficjalna dokumentacja dla deweloperów WordPressa jest w tej sprawie przyjemnie szczera i opisuje nonce jako jedną warstwę obrony, a nie kompletny system bezpieczeństwa.

Przed jakimi atakami chroni nonce? CSRF w praktyce

Atakiem, dla którego nonce w ogóle istnieje, jest cross-site request forgery. Scenariusz wygląda tak: w jednej karcie przeglądarki jesteś zalogowany do panelu WordPressa. W drugiej otwierasz zupełnie niezwiązaną stronę, którą kontroluje atakujący. Ta strona zawiera ukryty formularz albo znacznik obrazka wskazujący na Twoją witrynę, na przykład żądanie dezaktywacji wtyczki albo utworzenia użytkownika. Ponieważ przeglądarka automatycznie wysyła Twoje ciasteczka WordPressa z każdym żądaniem do Twojej domeny, żądanie dociera w pełni uwierzytelnione, a WordPress ochoczo by je wykonał. Nic nie kliknąłeś, niczego nie zobaczyłeś, a Twoja witryna właśnie zyskała nowego administratora.

Nonce przerywa ten atak na ostatnim kroku. Złośliwa strona potrafi sfałszować żądanie, ale nie zna aktualnego nonce dla Twojego użytkownika i tej akcji, bo token pojawia się wyłącznie w stronach, które WordPress renderuje dla Ciebie. Sfałszowane żądanie przychodzi bez ważnego nonce, weryfikacja się nie udaje, a WordPress zatrzymuje się na słynnym białym ekranie z pytaniem, czy na pewno chcesz to zrobić.

Jak długo ważny jest nonce? System taktów

WordPress dzieli czas na takty po dwanaście godzin. Przy weryfikacji akceptuje tokeny z taktu bieżącego i poprzedniego, i stąd bierze się maksymalny czas życia wynoszący 24 godziny. Funkcje weryfikujące mówią nawet, w której połowie jesteś: zwracają 1, jeśli nonce powstał w ciągu ostatnich dwunastu godzin, 2, jeśli ma od dwunastu do 24 godzin, i false, jeśli jest nieważny albo wygasł.

Czas życia można zmienić filtrem nonce_life, z czego korzystają niektóre konfiguracje nastawione na bezpieczeństwo, żeby skrócić to okno:

// Skrócenie czasu życia nonce do 4 godzin
add_filter( 'nonce_life', function () {
	return 4 * HOUR_IN_SECONDS;
} );

Krótszy czas życia zawęża okno na atak typu replay, ale sprawia też, że strony w pamięci podręcznej z osadzonymi nonce wygasają szybciej, a to realny problem na witrynach z agresywnym cache'owaniem stron. Jeśli zapisana strona poda nonce starszy niż 24 godziny, każdy odwiedzający dostanie token, który nigdy nie przejdzie weryfikacji. To klasyczna przyczyna tego, że funkcje AJAX na mocno cache'owanych witrynach WordPress tajemniczo przestają działać u części odwiedzających.

Jak utworzyć nonce w WordPressie?

WordPress dostarcza trzy funkcje pomocnicze do generowania nonce, po jednej dla każdego miejsca, w którym token zwykle mieszka:

// 1. W formularzu: dodaje ukryte pole oraz pole referer
wp_nonce_field( 'save_settings_action', 'my_plugin_nonce' );

// 2. W adresie URL: dokleja ?_wpnonce=... do linku
$url = wp_nonce_url( admin_url( 'admin.php?page=my-plugin&delete=42' ), 'delete-item_42' );

// 3. Surowy token, na przykład do przekazania do JavaScriptu
$nonce = wp_create_nonce( 'my_ajax_action' );

Pierwszy argument to zawsze akcja i właśnie tu staranność się opłaca. Nazwa akcji taka jak delete-item_42, zawierająca identyfikator obiektu, daje token działający wyłącznie dla dokładnie tego elementu. Leniwa, ogólna akcja w rodzaju my_nonce, współdzielona przez całą wtyczkę, oznacza, że jeden wyciekły albo przewidywalny token otwiera każdą operację, jaką ta wtyczka oferuje.

Jak zweryfikować nonce: wp_verify_nonce, check_admin_referer i check_ajax_referer

Weryfikacja ma jedną funkcję niskopoziomową i dwie wygodne nakładki, które w prawdziwym kodzie spotkasz znacznie częściej:

// Niski poziom: zwraca 1, 2 albo false, nigdy nie przerywa wykonania
if ( ! wp_verify_nonce( $_POST['my_plugin_nonce'], 'save_settings_action' ) ) {
	return; // stop, nieprawidłowe żądanie
}

// Ekrany administracyjne: weryfikuje i przy błędzie kończy stroną błędu
check_admin_referer( 'save_settings_action', 'my_plugin_nonce' );

// Obsługa AJAX: ta sama idea dla żądań do admin-ajax.php
check_ajax_referer( 'my_ajax_action', 'security' );

Nakładki przerywają wykonanie przy niepowodzeniu, czego zwykle chcesz na początku funkcji obsługującej. Niskopoziomowa wp_verify_nonce() daje Ci zamiast tego wartość zwrotną, więc w kontekście API możesz odpowiedzieć porządnym błędem w formacie JSON. Który wariant byś nie wybrał, weryfikacja musi stać przed wykonaniem akcji, a nie po nim, co brzmi oczywiście, a i tak wraca w changelogach wtyczek jako powtarzalny błąd.

Nonce w REST API i w żądaniach AJAX

REST API WordPressa korzysta z tego samego mechanizmu ze stałą nazwą akcji. Dla każdego żądania opartego na uwierzytelnianiu ciasteczkami WordPress oczekuje nonce utworzonego dla akcji wp_rest i przekazanego w nagłówku żądania X-WP-Nonce. Skrypty rejestrowane w standardowy sposób dostają to automatycznie: wp_localize_script() albo nowszy pakiet wp.apiFetch przekazują token dalej, więc każde zalogowane żądanie REST niesie go bez udziału dewelopera.

// Przekazanie nonce dla REST do Twojego JavaScriptu
wp_localize_script( 'my-app', 'myAppData', array(
	'restUrl' => esc_url_raw( rest_url( 'my-plugin/v1/' ) ),
	'nonce'   => wp_create_nonce( 'wp_rest' ),
) );

// W JavaScripcie: wyślij go jako nagłówek
fetch( myAppData.restUrl + 'items', {
	method: 'POST',
	headers: { 'X-WP-Nonce': myAppData.nonce, 'Content-Type': 'application/json' },
	body: JSON.stringify( { title: 'Nowy element' } ),
} );

Bez tego nagłówka REST API traktuje żądanie jako nieuwierzytelnione, nawet jeśli przeglądarka wysłała prawidłowe ciasteczka logowania. To działanie celowe: dokładnie ta sama ochrona przed CSRF, opisana wyżej, zastosowana do API.

Dlaczego nonce nie jest sprawdzeniem uprawnień?

To najważniejsza rzecz, jaką trzeba zrozumieć o nonce, i zarazem ta część, która regularnie idzie źle w ekosystemie wtyczek. Udana weryfikacja nonce dowodzi dwóch rzeczy: żądanie pochodzi ze strony wygenerowanej przez WordPress i należy do użytkownika, któremu token wydano. Nie dowodzi, że ten użytkownik ma prawo zrobić to, o co żądanie prosi. Subskrybent może mieć całkowicie poprawny nonce, bo WordPress bez oporów wydaje je każdemu zalogowanemu użytkownikowi, a część tokenów działa nawet dla odwiedzających, którzy w ogóle nie są zalogowani.

Poprawny kod obsługi zadaje więc zawsze dwa osobne pytania:

// Intencja: czy to prawdziwe żądanie od tego użytkownika?
check_admin_referer( 'save_settings_action', 'my_plugin_nonce' );

// Uprawnienia: czy ten użytkownik ma prawo to zrobić?
if ( ! current_user_can( 'manage_options' ) ) {
	wp_die( 'Niewystarczające uprawnienia.' );
}

Bazy podatności pękają od przykładów tego, co się dzieje, gdy drugie pytanie zostaje pominięte. Błędna kontrola dostępu i CSRF konsekwentnie plasują się wśród najczęstszych kategorii w CVE dotyczących wtyczek WordPress, a spora część tych wpisów sprowadza się do funkcji obsługującej, która sprawdziła nonce albo nic, zamiast sprawdzić uprawnienie. Jeśli czytasz biuletyn wtyczki mówiący, że dowolny uwierzytelniony użytkownik mógł zmienić ustawienia albo że zabrakło autoryzacji, zwykle stoi za tym ten właśnie schemat.

Częste błędy z nonce w motywach i wtyczkach

  • Sprawdzenie nonce zamiast sprawdzenia uprawnień. Klasyk opisany wyżej. Potrzebne są oba, bo odpowiadają na różne pytania.
  • Jeden ogólny nonce do wszystkiego. Pojedyncza nazwa akcji w całej wtyczce zamienia wąski token w klucz uniwersalny.
  • Nonce na stronach z pamięci podręcznej. Cache całych stron podaje tokeny po upływie ich 24-godzinnego życia, po cichu psując formularze i AJAX u części odwiedzających. Pomaga cache'owanie fragmentów albo pobieranie nonce osobnym żądaniem.
  • Weryfikacja po wykonaniu akcji. Sprawdzenie musi być pierwszą rzeczą, jaką robi funkcja obsługująca.
  • Traktowanie nonce jako dowodu tożsamości dla niezalogowanych. Nonce dla odwiedzających bez sesji są z konstrukcji słabsze, bo część skrótu odpowiadająca użytkownikowi pozostaje pusta.
  • Wyciekanie nonce w adresach URL. Tokeny doklejone do linków lądują w logach serwera, historii przeglądarki i nagłówku Referer. Dla akcji niszczących lepszym domem są żądania POST z wp_nonce_field().

Jak InspectWP pomaga dostrzec konsekwencje?

Z zewnątrz nie zobaczysz, czy wtyczka poprawnie weryfikuje swoje nonce, ale zobaczysz konsekwencje, gdy staną się publiczne. InspectWP wykrywa wtyczki i motywy analizowanej witryny WordPress wraz z ich wersjami i zestawia je ze znanymi danymi o podatnościach, a błędy typu CSRF i brakującej autoryzacji, dokładnie takie jak opisane w tym artykule, stanowią sporą część tych wpisów. Jeśli raport oznaczy zainstalowaną wtyczkę z opublikowaną podatnością, rozwiązanie jest niemal zawsze to samo i przyjemnie proste: zaktualizuj. Przy zaplanowanych raportach automatycznych ta pętla wykrywania, nauki i aktualizacji działa nieprzerwanie, a nie wtedy, gdy komuś akurat przyjdzie to do głowy.

Sprawdź teraz swoją stronę WordPress

InspectWP analizuje Twoją stronę WordPress pod kątem bezpieczeństwa, problemów SEO, zgodności z RODO i wydajności — za darmo.

Przeanalizuj stronę za darmo