- die drei Grundregeln sicherer WordPress-Entwicklung kennen
- Eingaben validieren und bereinigen
- Ausgaben kontextgerecht maskieren
- Nonces und Rechteprüfungen gegen gefälschte Anfragen einsetzen
Die meisten Sicherheitslücken in WordPress entstehen nicht im Core, sondern in Plugins und Themes – und fast immer durch dieselben wenigen Fehler: Eingaben werden ungeprüft verarbeitet, Ausgaben nicht maskiert, Aktionen ohne Rechteprüfung ausgeführt. Die gute Nachricht: WordPress bringt für all das fertige Funktionen mit, und wer ein paar feste Regeln befolgt, schließt die häufigsten Angriffswege zuverlässig. Diese Lektion zeigt diese Regeln und die passenden Funktionen. Sie ist die wichtigste des Moduls, denn jede spätere Lektion über Plugins und Schnittstellen baut darauf auf.
1. Die Grundregel
Die Regel der WordPress-Sicherheitsrichtlinien lautet: Eingaben früh prüfen und bereinigen, Ausgaben spät maskieren. Jede Eingabe gilt als unsicher – aus Formularen, Adressen, Cookies, der REST API und sogar aus der eigenen Datenbank, denn dort können Daten eines Angreifers liegen. Und jede Ausgabe wird unmittelbar vor dem Ausgeben maskiert, mit der Funktion, die zum Kontext passt.
2. Ausgaben maskieren
Die häufigste Lücke ist Cross-Site Scripting: Eine Eingabe wird ungefiltert ausgegeben und enthält Schadcode, der dann im Browser anderer Besucher läuft. Probieren Sie es aus:
1<?php echo '<p>' . $bewertung . '</p>'; // gefährlich!HTML, das der Browser erhält
<p><script>alert('gehackt')</script></p>| Kontext | Funktion | Beispiel |
|---|---|---|
| Text in HTML | esc_html() | <h2><?= esc_html( $titel ) ?></h2> |
| HTML-Attribut | esc_attr() | <input value="<?= esc_attr( $name ) ?>"> |
| Adresse (URL) | esc_url() | <a href="<?= esc_url( $link ) ?>"> |
| Erlaubtes HTML | wp_kses_post() | Inhalt mit Absätzen und Links |
| JavaScript-Daten | wp_json_encode() | Werte an Skripte übergeben |
3. Eingaben prüfen und bereinigen
Bevor Daten gespeichert oder verarbeitet werden, werden sie geprüft und bereinigt. Zahlen werden mit absint() oder (int) in ganze Zahlen umgewandelt, Texte mit sanitize_text_field() von Tags und Steuerzeichen befreit, E-Mail-Adressen mit is_email() geprüft und mit sanitize_email() bereinigt. Wo nur bestimmte Werte erlaubt sind – etwa ein Niveau „einsteiger“, „fortgeschritten“ oder „alle“ –, ist eine Liste erlaubter Werte der sicherste Weg: Alles andere wird abgelehnt. Für Datenbankabfragen gilt zusätzlich: Niemals Eingaben direkt in SQL einsetzen, sondern $wpdb->prepare() mit Platzhaltern nutzen.
1<?php2$kurs_id = absint( $_POST['kurs_id'] ?? 0 );3$name = sanitize_text_field( wp_unslash( $_POST['name'] ?? '' ) );4$email = sanitize_email( wp_unslash( $_POST['email'] ?? '' ) );5$niveau = in_array( $_POST['niveau'] ?? '', [ 'einsteiger', 'fortgeschritten', 'alle' ], true )6 ? $_POST['niveau'] : 'alle';78if ( ! $kurs_id || ! is_email( $email ) ) {9 wp_die( 'Bitte Kurs und gültige E-Mail angeben.' );10}1112global $wpdb;13$plaetze = $wpdb->get_var( $wpdb->prepare(14 "SELECT plaetze FROM {$wpdb->prefix}studio_kurse WHERE id = %d", $kurs_id15) );4. Nonces und Rechte
Zwei weitere Angriffe zielen nicht auf die Daten, sondern auf die Aktion. Bei einer Cross-Site Request Forgery bringt ein Angreifer einen angemeldeten Benutzer dazu, unbemerkt eine Aktion auszuführen – etwa über einen präparierten Link, der eine Einstellung ändert. Dagegen helfen Nonces: einmalige, zeitlich begrenzte Prüfwerte, die WordPress in Formulare und Links einbaut und beim Absenden prüft. Die zweite Frage lautet: Darf dieser Benutzer das überhaupt? Das prüft current_user_can() mit einem passenden Recht, etwa edit_posts oder manage_options. Klicken Sie sich durch eine sichere Formularverarbeitung:
5. Lücke oder sicher?
Beurteilen Sie typische Codezeilen:
echo '<a href="' . esc_url( $link ) . '">' . esc_html( $titel ) . '</a>';
$wpdb->query( "DELETE FROM tabelle WHERE id = " . $_GET['id'] );
update_option( 'studio_preis', sanitize_text_field( $_POST['preis'] ) ); ohne Rechte- und Nonce-Prüfung
if ( ! current_user_can( 'manage_options' ) ) { wp_die( 'Keine Berechtigung' ); }
<input value="<?php echo esc_attr( $name ); ?>">
6. Werkzeuge, die helfen
Niemand muss diese Regeln allein im Kopf behalten. Der offizielle WordPress Coding Standard für PHP_CodeSniffer erkennt fehlende Maskierung, ungeprüfte Eingaben und fehlende Nonces automatisch und lässt sich in jeden Editor und jede Pipeline einbinden. Das Plugin Plugin Check prüft Plugins vor der Veröffentlichung auf typische Probleme. Und KI-Assistenten beim Programmieren kennen die WordPress-Sicherheitsfunktionen gut – ihre Vorschläge sollten dennoch gegen diese Regeln geprüft werden, denn auch sie vergessen gelegentlich eine Maskierung. Modul 4 zeigt, wie diese Werkzeuge in den Entwicklungsablauf eingebunden werden.
7. Ein Beispiel
Ein Fahrradladen ließ ein kleines Plugin für Werkstattanfragen programmieren. Bei einer Sicherheitsprüfung fielen drei Probleme auf: Der Name der Kunden wurde im Backend ohne Maskierung angezeigt, die Löschfunktion für Anfragen prüfte weder Nonce noch Rechte, und eine Suche setzte den Suchbegriff direkt in eine SQL-Abfrage ein. Alle drei Lücken ließen sich in einer Stunde schließen: esc_html bei der Ausgabe, check_admin_referer und current_user_can vor dem Löschen, $wpdb->prepare für die Suche. Seitdem läuft der WordPress Coding Standard bei jeder Änderung automatisch mit und meldet solche Fehler, bevor sie online gehen.
8. Häufige Fragen
Reicht es nicht, Eingaben beim Speichern zu bereinigen? Nein. Bereinigen beim Speichern ist wichtig, aber Daten können auch auf anderen Wegen in die Datenbank gelangen – über Importe, andere Plugins oder Angriffe. Deshalb wird zusätzlich bei jeder Ausgabe maskiert. Beide Schritte ergänzen sich.
Was ist mit Daten aus der REST API? Für sie gelten dieselben Regeln. Die REST API bietet zusätzlich eigene Mechanismen: Für jeden Parameter lassen sich Typ, Validierung und Bereinigung festlegen, und jeder Endpunkt bekommt eine Berechtigungsprüfung. Modul 6 zeigt die Einzelheiten.
Wie gehe ich mit HTML um, das Redakteure eingeben dürfen? Mit wp_kses_post() wird nur das HTML erlaubt, das auch im Editor zulässig ist, etwa Absätze, Links und Hervorhebungen, während Skripte entfernt werden. Für eigene, engere Regeln gibt es wp_kses() mit einer Liste erlaubter Tags und Attribute.
9. Übung zum Selbermachen
Bauen Sie in WordPress Playground ein kleines Formular in ein Must-use-Plugin ein, das auf einer eigenen Adminseite eine Einstellung „Begrüßungstext“ speichert. Fügen Sie mit wp_nonce_field einen Prüfwert hinzu, prüfen Sie beim Speichern mit check_admin_referer und current_user_can( 'manage_options' ), bereinigen Sie die Eingabe mit sanitize_text_field und speichern Sie sie mit update_option. Geben Sie den Text anschließend im Frontend mit esc_html aus. Versuchen Sie danach bewusst, im Formular <script> einzugeben, und prüfen Sie, dass es als harmloser Text erscheint. Wer so einmal den ganzen Weg von der Eingabe bis zur Ausgabe sicher umgesetzt hat, wendet die Regeln künftig fast automatisch an – und ist bestens für die Plugin-Entwicklung in Modul 4 vorbereitet.
- [1]WordPress.org (2026): Plugin Handbook – Security: Sanitizing, Validating, Escaping, Nonces, Checking User Capabilities.
- [2]WordPress.org (2026): WordPress Coding Standards for PHP_CodeSniffer. github.com/WordPress/WordPress-Coding-Standards.
- [3]OWASP Foundation (2021): OWASP Top 10 – A03 Injection. owasp.org.
- [4]WordPress.org (2026): Plugin Check (PCP). wordpress.org/plugins/plugin-check.
Stand: September 2026, WordPress 7.1, PHP 8.3. Kursmaterial der Klarwerk Akademie. WordPress entwickelt sich schnell – maßgeblich ist die aktuelle Dokumentation auf developer.wordpress.org.