Ein Nonce in WordPress ist ein Sicherheitstoken, das an Formulare, Links und AJAX-Anfragen gehängt wird, damit WordPress prüfen kann, ob die Anfrage absichtlich von einem bestimmten eingeloggten Benutzer ausgelöst wurde. Der Name stammt aus der Kryptografie und steht für number used once, was hier allerdings leicht in die Irre führt: Ein WordPress-Nonce ist keine Zahl, wird nicht nur einmal verwendet und ist technisch ein Hash, der an den Benutzer, die Session und genau eine Aktion gebunden ist. Gültig bleibt es bis zu 24 Stunden. Die Bedrohung, gegen die Nonces verteidigen, heißt Cross-Site Request Forgery (CSRF): ein Angriff, bei dem eine bösartige Seite still eine Anfrage mit Ihrer eingeloggten Session absetzt, etwa um einen Beitrag zu löschen oder eine Einstellung zu ändern. Nonces funktionieren, und genau deshalb liegt der häufigste Sicherheitsfehler auf der anderen Seite: Ein Nonce belegt Absicht, nicht Berechtigung. Plugin-Code, der ein Nonce prüft, aber die Rechteprüfung mit current_user_can() vergisst, ist eine der häufigsten Quellen veröffentlichter WordPress-Schwachstellen.
Was ist ein Nonce? Der Name führt etwas in die Irre
In der Kryptografie ist ein Nonce ein Wert, der genau einmal und nie wieder verwendet wird, und genau das macht ihn gegen Replay-Angriffe nützlich. WordPress hat den Namen übernommen, die strenge Definition aber nicht. Ein WordPress-Nonce ist ein kurzer Hash aus vier Zutaten: der Aktion, zu der es gehört, der ID und dem Session-Token des aktuellen Benutzers, dem aktuellen Zeitfenster und den geheimen Schlüsseln aus Ihrer wp-config.php. Diese Konstruktion hat drei praktische Konsequenzen:
- Ein Nonce ist persönlich. Ein Token, das für einen Benutzer erzeugt wurde, scheitert bei jedem anderen Benutzer an der Prüfung. Es lässt sich also nicht teilen oder von einer öffentlichen Seite stehlen.
- Ein Nonce gehört zu genau einer Aktion. Ein Token für die Aktion delete-post_42 ist für delete-post_43 oder irgendeinen anderen Vorgang wertlos. Deshalb schwächt ein fest verdrahteter, allgemeiner Aktionsname den ganzen Mechanismus.
- Ein Nonce ist innerhalb seiner Lebensdauer wiederverwendbar. Dasselbe Token besteht die Prüfung beliebig oft, bis zu 24 Stunden lang. WordPress dokumentiert das ausdrücklich, ein Nonce allein schützt also nicht davor, dass ein Angreifer eine bereits abgefangene Anfrage erneut abspielt.
Die offizielle WordPress-Entwicklerdokumentation geht damit erfreulich offen um und beschreibt Nonces als eine Verteidigungsschicht, nicht als vollständiges Sicherheitssystem.
Welche Angriffe verhindern WordPress-Nonces? CSRF erklärt
Der Angriff, für den es Nonces gibt, heißt Cross-Site Request Forgery. Das Szenario: Sie sind in einem Browser-Tab in Ihrem WordPress-Adminbereich eingeloggt. In einem anderen Tab öffnen Sie eine völlig unabhängige Seite, die ein Angreifer kontrolliert. Diese Seite enthält ein verstecktes Formular oder ein Image-Tag, das auf Ihre Website zeigt, zum Beispiel eine Anfrage, ein Plugin zu deaktivieren oder einen Benutzer anzulegen. Weil Ihr Browser Ihre WordPress-Cookies automatisch bei jeder Anfrage an Ihre Domain mitschickt, kommt die Anfrage vollständig authentifiziert an, und WordPress würde sie bereitwillig ausführen. Sie haben nichts geklickt, nichts gesehen, und Ihre Website hat gerade einen neuen Administrator bekommen.
Nonces brechen diesen Angriff im letzten Schritt. Die bösartige Seite kann die Anfrage fälschen, aber sie kann das aktuelle Nonce für Ihren Benutzer und diese Aktion nicht kennen, denn das Token taucht nur in Seiten auf, die WordPress für Sie ausliefert. Die gefälschte Anfrage kommt ohne gültiges Nonce an, die Prüfung scheitert, und WordPress stoppt mit der berühmten weißen Seite und der Frage: Möchten Sie das wirklich tun?
Wie lange ist ein WordPress-Nonce gültig? Das Tick-System
WordPress teilt die Zeit in Ticks von zwölf Stunden. Bei der Prüfung eines Nonce akzeptiert WordPress Token aus dem aktuellen und dem vorherigen Tick, und daher kommt die maximale Lebensdauer von 24 Stunden. Die Prüffunktionen verraten sogar, in welcher Hälfte Sie sich befinden: Sie geben 1 zurück, wenn das Nonce in den letzten zwölf Stunden erzeugt wurde, 2, wenn es zwischen zwölf und 24 Stunden alt ist, und false, wenn es ungültig oder abgelaufen ist.
Die Lebensdauer lässt sich über den Filter nonce_life ändern, was manche sicherheitsbewussten Setups nutzen, um das Zeitfenster zu verkürzen:
// Nonce-Lebensdauer auf 4 Stunden verkürzen
add_filter( 'nonce_life', function () {
return 4 * HOUR_IN_SECONDS;
} );Kürzere Lebensdauern schrumpfen das Replay-Fenster, lassen aber auch gecachte Seiten mit eingebetteten Nonces schneller ablaufen, und das ist auf Websites mit aggressivem Page-Caching ein echtes Problem. Liefert eine gecachte Seite ein Nonce aus, das älter als 24 Stunden ist, bekommt jeder Besucher ein Token, das die Prüfung nie bestehen kann. Das ist der klassische Grund, warum AJAX-Funktionen auf stark gecachten WordPress-Websites für manche Besucher rätselhaft scheitern.
Wie man in WordPress ein Nonce erzeugt
WordPress bringt drei Hilfsfunktionen zum Erzeugen von Nonces mit, eine für jeden Ort, an dem ein Token typischerweise landet:
// 1. Im Formular: ergänzt ein verstecktes Eingabefeld plus Referer-Feld
wp_nonce_field( 'save_settings_action', 'my_plugin_nonce' );
// 2. In einer URL: hängt ?_wpnonce=... an einen Link
$url = wp_nonce_url( admin_url( 'admin.php?page=my-plugin&delete=42' ), 'delete-item_42' );
// 3. Reines Token, z. B. zur Übergabe an JavaScript
$nonce = wp_create_nonce( 'my_ajax_action' );Das erste Argument ist immer die Aktion, und hier zahlt sich Sorgfalt aus. Ein Aktionsname wie delete-item_42, der die Objekt-ID enthält, ergibt ein Token, das ausschließlich für genau dieses Element funktioniert. Eine bequeme Allzweck-Aktion wie my_nonce, die ein ganzes Plugin durchzieht, bedeutet dagegen: Ein einziges abgeflossenes Token öffnet jeden Vorgang, den das Plugin anbietet.
Nonce prüfen: wp_verify_nonce, check_admin_referer und check_ajax_referer
Für die Prüfung gibt es eine Low-Level-Funktion und zwei bequeme Wrapper, denen Sie in echtem Code weit häufiger begegnen:
// Low Level: gibt 1, 2 oder false zurück, bricht nie ab
if ( ! wp_verify_nonce( $_POST['my_plugin_nonce'], 'save_settings_action' ) ) {
return; // Stopp, ungültige Anfrage
}
// Adminbereich: prüft und bricht bei Fehlschlag mit Fehlerseite ab
check_admin_referer( 'save_settings_action', 'my_plugin_nonce' );
// AJAX-Handler: dieselbe Idee für Anfragen an admin-ajax.php
check_ajax_referer( 'my_ajax_action', 'security' );Die Wrapper beenden die Ausführung bei einem Fehlschlag, und genau das will man am Anfang eines Handlers meistens. Die Low-Level-Variante wp_verify_nonce() liefert stattdessen den Rückgabewert, sodass Sie in einem API-Kontext mit einem sauberen JSON-Fehler antworten können. Welche Variante Sie auch wählen: Die Prüfung muss vor der Aktion stehen, nicht danach. Das klingt selbstverständlich und ist trotzdem ein wiederkehrender Bugfix in Plugin-Changelogs.
Nonces in der REST API und in AJAX-Anfragen
Die WordPress REST API nutzt denselben Mechanismus mit einem festen Aktionsnamen. Für jede Anfrage, die sich auf Cookie-Authentifizierung stützt, erwartet WordPress ein Nonce für die Aktion wp_rest, geliefert im Request-Header X-WP-Nonce. Skripte, die auf dem Standardweg registriert werden, bekommen das automatisch: wp_localize_script() oder das neuere wp.apiFetch-Bundle reichen das Token durch, und jede eingeloggte REST-Anfrage trägt es mit, ohne dass die Entwicklerin darüber nachdenken muss.
// Ein REST-Nonce an das eigene JavaScript übergeben
wp_localize_script( 'my-app', 'myAppData', array(
'restUrl' => esc_url_raw( rest_url( 'my-plugin/v1/' ) ),
'nonce' => wp_create_nonce( 'wp_rest' ),
) );
// In JavaScript: als Header mitschicken
fetch( myAppData.restUrl + 'items', {
method: 'POST',
headers: { 'X-WP-Nonce': myAppData.nonce, 'Content-Type': 'application/json' },
body: JSON.stringify( { title: 'Neues Element' } ),
} );Ohne den Header behandelt die REST API die Anfrage als nicht authentifiziert, selbst wenn der Browser gültige Login-Cookies mitgeschickt hat. Das ist Absicht: Es ist exakt der oben beschriebene CSRF-Schutz, angewendet auf die API.
Warum ein Nonce keine Rechteprüfung ist
Das ist der mit Abstand wichtigste Punkt an Nonces, und es ist der Teil, der im Plugin-Ökosystem regelmäßig schiefgeht. Eine erfolgreiche Nonce-Prüfung belegt zwei Dinge: Die Anfrage stammt von einer Seite, die WordPress erzeugt hat, und sie gehört zu dem Benutzer, für den sie ausgestellt wurde. Sie belegt nicht, dass dieser Benutzer tun darf, worum die Anfrage bittet. Ein Abonnent kann ein vollkommen gültiges Nonce besitzen, denn WordPress stellt jedem eingeloggten Benutzer bereitwillig Nonces aus, und manche Token funktionieren sogar für Besucher, die überhaupt nicht eingeloggt sind.
Korrekter Handler-Code stellt deshalb immer zwei getrennte Fragen:
// Absicht: ist das eine echte Anfrage dieses Benutzers?
check_admin_referer( 'save_settings_action', 'my_plugin_nonce' );
// Berechtigung: darf dieser Benutzer das überhaupt?
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( 'Unzureichende Berechtigungen.' );
}Schwachstellen-Datenbanken sind voll davon, was passiert, wenn die zweite Frage ausfällt. Fehlerhafte Zugriffskontrolle und CSRF gehören durchgehend zu den häufigsten Kategorien bei CVEs für WordPress-Plugins, und ein großer Teil dieser Einträge läuft auf einen Handler hinaus, der ein Nonce geprüft hat, oder gar nichts, statt einer Berechtigung. Wenn Sie eine Plugin-Meldung lesen, in der steht, jeder authentifizierte Benutzer habe Einstellungen ändern können, oder es fehle die Autorisierung, steckt üblicherweise genau dieses Muster dahinter.
Häufige Nonce-Fehler in Themes und Plugins
- Nonce-Prüfung statt Rechteprüfung. Der Klassiker, oben beschrieben. Beide Prüfungen werden gebraucht, sie beantworten unterschiedliche Fragen.
- Ein allgemeines Nonce für alles. Ein einziger Aktionsname quer durch ein ganzes Plugin macht aus einem eng begrenzten Token einen Generalschlüssel.
- Nonces in gecachten Seiten. Full-Page-Caches liefern Token über ihre Lebensdauer von 24 Stunden hinaus aus und zerlegen still Formulare und AJAX für einen Teil der Besucher. Fragment-Caching oder das separate Nachladen des Nonce löst das.
- Prüfen nach dem Handeln. Die Prüfung muss das Erste sein, was der Handler tut.
- Einem Nonce als Identitätsnachweis für Ausgeloggte vertrauen. Nonces für Besucher ohne Session sind konstruktionsbedingt schwächer, weil der Benutzeranteil des Hash leer bleibt.
- Nonces über URLs preisgeben. An Links angehängte Token landen in Serverlogs, im Browserverlauf und im Referer-Header. Für zerstörerische Aktionen sind POST-Anfragen mit wp_nonce_field() die bessere Heimat.
Wie InspectWP Ihnen hilft, die Folgen zu erkennen
Von außen lässt sich nicht sehen, ob ein Plugin seine Nonces korrekt prüft, aber die Folgen werden sichtbar, sobald sie öffentlich sind. InspectWP erkennt die Plugins und Themes einer analysierten WordPress-Website samt Versionen und gleicht sie mit bekannten Schwachstellendaten ab, und CSRF-Lücken sowie fehlende Autorisierung genau der hier beschriebenen Art machen einen großen Teil dieser Einträge aus. Wenn ein Bericht ein installiertes Plugin mit einer veröffentlichten Schwachstelle markiert, ist die Lösung fast immer dieselbe und angenehm einfach: aktualisieren. Mit geplanten automatischen Berichten läuft diese Schleife aus Erkennen, Verstehen und Aktualisieren dauerhaft, statt immer dann, wenn jemand zufällig daran denkt.