Wenn Sie ein WordPress-Entwickler sind, der HTML/CSS/JS schreibt (was 100 % der Theme-Entwickler und 99 % der Plugin-Entwickler sind), müssen Sie die Grundlagen der Front-End-Sicherheit für WordPress kennen. WordPress bietet Ihnen alle Werkzeuge, die Sie benötigen, um Ihr Theme oder Plugin sicher zu machen. Sie müssen nur wissen, wie und wann Sie jedes Werkzeug einsetzen.
Zum Beispiel ist eine große Verantwortung, die Sie als Front-End-Entwickler haben, darin, zu verhindern, dass unescaped Inhalte auf der Seite ausgegeben werden.
Sicherheit ist Ihre Verantwortung
Bevor wir ins Detail gehen, möchte ich eine Idee ausräumen, die ich (früher) verwendet habe, um eine „weniger strenge“ Sicht auf die Front-End-Sicherheit zu rechtfertigen
„Wenn ein Hacker bereits in der Lage ist, den Code/die Datenbank/den Inhalt zu ändern, was macht es für einen Unterschied, ob mein Front-End-Code sicher ist? Könnte er nicht schon größeren Schaden anrichten?“
Ja, wenn ein Hacker bereits die Kontrolle über den Code oder die Datenbank hat, ist es wahrscheinlich, dass ihm die Sicherheit der Ausgabe egal ist (er kann sie wahrscheinlich sowieso ändern).
Selbst dann **haben Sie immer noch die Verantwortung, den Front-End-Code sicher zu machen**. Einige Gründe dafür:
- Eine ordnungsgemäße Front-End-Sicherheit **verhindert auch, dass Benutzerfehler zu großen Problemen führen**. Wenn der Benutzer versehentlich ein Sonderzeichen in ein Feld eingibt, das er nicht sollte, stürzt die Seite nicht ab.
- Einige Angriffe sind begrenzt. Vielleicht hatte der Hacker nur minimale Kontrolle und konnte nur ein einzelnes Inhaltselement in der Datenbank ändern. Sie können diesen begrenzten Angriff daran hindern, viel größer zu werden.
- Sicherheit ist eine Zwiebel. Die äußerste (oft ungenießbare) Schicht ist die Front-End-Anzeige. Gute Sicherheitspraktiken machen es für einen Hacker ein kleines bisschen schwieriger, eine Website auszunutzen.
Genug mit der Motivationsrede. Lassen Sie uns darüber sprechen, wie wir unsere WordPress-Themes und -Plugins sichern können.
Wovor haben wir Angst?
Eine große Sorge für einen Front-End-Entwickler ist die Vermeidung von **Cross-Site Scripting** (kurz XSS, da „CSS“ alle möglichen Probleme verursachen würde. Wortspiele und Einzeiler sind willkommen.).
XSS-Schwachstellen ermöglichen es böswilligen Personen („Hackern“), Informationen zu stehlen. Typischerweise bedeutet dies den Diebstahl von Cookies und Sitzungsinformationen. Wenn eine böswillige Person Ihre aktive Sitzung an sich selbst senden kann (daher der Teil „Cross-Site“), könnte sie diese nutzen, um sich in Ihr Konto einzuloggen und alles zu tun, was Sie tun könnten (schlechte Nachrichten).
Was ist Escaping?
In der Informatik hat das Wort „escape“ eine besondere Bedeutung.
Ein Zeichen oder eine Zeichenkette so umwandeln, dass es buchstäblich innerhalb eines bestimmten Kontexts interpretiert wird, typischerweise um zu verhindern, dass diese Zeichen als Code interpretiert werden.
Anders ausgedrückt, im Kontext der WordPress Front-End-Entwicklung: Escaping wandelt **möglicherweise bösartigen** Inhalt in **sicheren** Inhalt um.
Die größte Gefahr hier sind im Allgemeinen <script>-Tags und andere Methoden zur Ausführung von JavaScript (z. B. onclick="javascript:"). Wenn ein <script> auf der Seite ausgegeben und ausgeführt werden kann, ist das extrem gefährlich. Escaping bedeutet, dies in <script> umzuwandeln, was sicher ist.
Warum Sie escapen müssen: Ein Beispiel
Falls Sie mit XSS nicht vertraut sind, wird ein kurzes Beispiel das Risiko verdeutlichen.
Angenommen, Ihr Theme hätte ein Feld, um einen Link für weitere Lektüre hinzuzufügen. Einen „Weiterlesen“-Link, wenn Sie so wollen. Im WordPress-Dashboard könnte es so aussehen:

In Ihrem Theme möchten Sie diesen Link am Ende des Beitrags anzeigen, so:

Also öffnen Sie single.php (die Datei, die für die Anzeige von Blogbeiträgen zuständig ist) und fügen Sie Folgendes unten hinzu:
<?php
$read_more_link = get_post_meta(
get_the_ID(),
'read_more_link',
true
);
?>
<!-- Don't do this -->
<a href="<?php echo $read_more_link; ?>">Read More</a>
Angenommen, jemand gibt bösartig diesen Text in Ihr benutzerdefiniertes Feld ein:

Wenn Sie die Seite besuchen, sehen Sie Folgendes:

Autsch! Wenn diese böse Eingabe es einem bösen Menschen erlauben würde, JavaScript auszuführen, könnten sie:
- Den Benutzer umleiten
- Die Cookies des Benutzers kapern
- Andere böse Dinge tun
Ein Escape für alles
Nachdem wir nun wissen, wie wichtig Escaping ist, schauen wir uns die von WordPress bereitgestellten Escaping-Methoden an und geben für jede Kontextinformationen.
Funktion: esc_html
Verwendet für: Ausgabe, die absolut kein HTML enthalten soll.
Was sie tut: Wandelt spezielle HTML-Zeichen (wie <, >, &) in ihre „escapte“ Entsprechung um (<, >, &).
Ein übliches Beispiel wäre die Anzeige von reinen Text-Custom-Fields in einem Theme
<?php $dog_name = get_post_meta( $post_id, 'dog_name', true ); ?>
<span class="dog-name"><?php echo esc_html( $dog_name ); ?></span>
Funktion: esc_attr
Verwendet für: Ausgabe, die im Kontext eines HTML-Attributs verwendet wird (denken Sie an „title“, „data-“ Felder, „alt“-Text).
Was sie tut: Genau das Gleiche wie esc_html. Der einzige Unterschied besteht darin, dass für jede Funktion unterschiedliche WordPress-Filter angewendet werden.
Hier wird esc_attr für ein Bild verwendet:
<img src="/images/duck.png"
alt="<?php echo esc_attr( $alt_text ); ?>"
title="<?php echo esc_attr( $title ); ?>" >
Funktion: esc_url
Verwendet für: Ausgabe, die zwangsläufig eine URL sein muss. Beispiele wären src-Attribute von Bildern und href-Werte.
Was sie tut: Ein gründlicheres, spezifischeres Escaping als die Funktionen esc_attr & esc_html, das alle Zeichen entfernt oder in ihr URL-sicheres Format umwandelt, die in URLs nicht zulässig sind.
Verwenden Sie esc_url, wenn Sie einen Link oder einen dynamischen Bildpfad ausgeben müssen:
<a href="<?php echo esc_url( $url ); ?>">Link Text</a>
<img src="<?php echo esc_url( $image_url ); ?>" >
Funktion: esc_js
Verwendet für: Ausgabe von JavaScript-Strings, hauptsächlich in Inline-Attributen wie onclick.
Was sie tut: Wandelt Sonderzeichen wie <, >, Anführungszeichen – alles, was JavaScript-Code brechen könnte.
esc_js ist wahrscheinlich die am wenigsten verwendete der esc_-Funktionen, und das aus mehreren Gründen:
- Die meiste JS wird in einer separaten Datei geladen.
- Die meisten JS werden nicht inline als Attribute geschrieben.
- Für Nicht-Inline-JS ist
json_encodeeine bessere Option.
Aber, wenn Sie jemals Inline-JS escapen müssen, hier ist, wie Sie es tun würden:
<?php $message = get_post_meta( get_the_ID(), 'onclick_message', true ); ?>
<a href="/blog/" onclick="alert('<?php echo esc_js( $message ); ?>')">...</a>
Funktion: json_encode
Verwendet für: Ausgabe einer PHP-Variable für die Verwendung in JavaScript.
Was sie tut: Wandelt eine PHP-Variable (Objekt, String, Array, was auch immer) in eine sinnvolle, escapte JavaScript-Darstellung dieser PHP-Variable um.
Besonders nützlich für <script>-Blöcke, die WP-Variablen verwenden. Ein einfaches Beispiel:
<
pre rel=”PHP”><?php $categories = get_categories(); ?>
<script type="text/javascript">
var allCategories = <?php echo json_encode( $categories ); ?>;
// Hier etwas Interessantes mit den Kategorien tun
</script>
Funktion: wp_kses
Verwendet für: Ausgabe, die etwas HTML zulassen muss, aber nicht alle Tags oder Attribute.
Was sie tut: Entfernt aus dem Inhalt alle Tags oder Attribute, die nicht mit der Liste der übergebenen Regeln übereinstimmen.
Verwenden Sie wp_kses, wenn es einen Kontext gibt, der bestimmte Tags zulässt (z. B. Inline-Formatierungstags wie <strong> und <em>), die als HTML ausgegeben werden sollen.
Ein grundlegendes Beispiel wäre die Anzeige von Kommentaren:
Was sind die _e und _x Versionen der Escaping-Funktionen (esc_attr_e, esc_attr_x)?
Dies sind **Komfortfunktionen** (um Ihnen das Leben zu erleichtern) und sie sind nützlich, wenn Sie übersetzbare Strings ausgeben: Text, der mit einer WordPress-Übersetzungsdatei geändert werden kann.
Wenn Sie ein Theme oder Plugin für eine breite Verteilung entwickeln (im Gegensatz zu einem einmaligen Kundenprojekt), möchten Sie jeden String internationalisierungsfreundlich gestalten. Das bedeutet, dass PHP-Strings, die einst unter Ihrer Kontrolle standen, von Übersetzern bearbeitet werden können – daher die Notwendigkeit des Escapings (Sie können niemandem vertrauen).
Blog
Der zweite Parameter der _e-Funktionen ist die Übersetzungdomäne. Sie wird von Übersetzern verwendet, wenn sie ihre Übersetzungen schreiben und generieren.
Die _x-Funktionen (wie esc_html_x) sind im Wesentlichen die gleichen wie ihre _e-Gegenstücke, mit einem zusätzlichen „Kontext“-Argument, um den Kontext zu erklären, in dem ein Wort oder eine Phrase verwendet wird. Nützlich für Wörter mit mehreren Bedeutungen.
Codex-Eintrag für esc_attr_e
Codex-Eintrag für esc_attr_x
Was ist mit the_title und the_content?
Wenn Sie das Standard-WordPress-Theme (zu diesem Zeitpunkt „Twenty Fifteen“ genannt) öffnen, sehen Sie Code wie diesen, der den Titel eines Beitrags ausgibt:
Sie sehen auch unescaped Aufrufe an the_content wie diese:
Sie geraten vielleicht in Panik. Warum werden diese Funktionen nicht escaped?! 2 Gründe:
1. WordPress escaped sie automatisch
Funktionen wie the_title sind Komfortfunktionen – Werkzeuge, die die Front-End-Entwicklung erleichtern. Um es Entwicklern noch einfacher zu machen, escaped WordPress bereits automatisch die Ausgabe für the_title Update: WordPress escaped the_title nicht, sei vorsichtig!.
2. Kontext: Einige Inhalte sind HTML
Im Fall von the_content wird erwartet, dass die Ausgabe unescaped HTML ist. Wenn der Benutzer einen
in seinen Inhalt einfügt
auf der Seite ausgegeben werden soll – anstelle der escaped Version.
Wenn Sie Sicherheitsbedenken haben, dass ein Benutzer Skripte zur Ausgabe von the_content hinzufügen kann, können Sie wp_kses verwenden, um unerwünschte Tags aus der endgültigen Ausgabe zu entfernen. Dies wäre auf Subdomains und Shared Hosting nützlich, und ich bin mir ziemlich sicher, dass dies auf WordPress.com verwendet wird (eine gehostete Version von WordPress, bei der Benutzer kein eigenes JavaScript hinzufügen dürfen).
Nützlicher Tipp: Wenn Sie the_title als HTML-Attribut verwenden möchten, verwenden Sie the_title_attibute, um sich einen Escape zu sparen. the_title_attribute in Aktion:
...
Escape the Things
Ich arbeite mit vielen Plugins und Themes – kommerzielle, kostenlose und individuell erstellte – und ich sehe viele unescaped Inhalte (und daraus resultierende XSS-Schwachstellen). Hoffentlich stattet Sie dieser Artikel mit den grundlegenden Werkzeugen aus, die Sie benötigen, um Ihre WordPress-Dinge sicherer zu machen.
Habe ich etwas übersehen? Lassen Sie es mich in den Kommentaren wissen!
Ich dachte immer, WordPress sollte standardmäßig alle Abfragen escapen – mit einem optionalen Parameter, um dies zu deaktivieren. Die Welt wäre ein sichererer Ort, nicht wahr?
Das macht Ruby on Rails, und ja, das wäre schön. Aber ich bin mir nicht sicher, wie das ohne das Brechen praktisch jedes jemals geschriebenen Plugins geschehen könnte!
Es ist 2015, und wir schreiben immer noch Escape-Aufrufe in der Template-Schicht, als wäre es 1999. Und das ist einer der Gründe, warum ich aufgehört habe, mit WP zu arbeiten; es ist einfach zu einfach, wirklich schrecklichen Code zu schreiben. Ich möchte keine Debatte darüber führen, ob Template-Sprachen gut oder schlecht sind, aber nach der Verwendung von etwas wie Twig (in Craft, Drupal 8 und anderen CMS), wo Variablen standardmäßig escaped werden, ist das eine Sache weniger, um die sich ein Designer/Entwickler letztendlich kümmern muss.
Beim Beispiel der benutzerdefinierten Felder ist dies ein Fall, warum WP wirklich eine ordnungsgemäße Unterstützung für benutzerdefinierte Felder integrieren muss (etwas wie ACF oder Pods kommt in den Sinn), das auch die Eingaben des Benutzers validiert (Text / HTML / Bild / Link / etc.) und diese Eingaben bereinigt, wie nötig, bevor sie überhaupt in die Datenbank gelangen.
OMG, ich glaube, ich benutze es
<a href="<?php echo $read_more_link; " read more /a
Ich hoffe, das passiert nicht auf meiner Website. Danke für die Infos, das ist sehr nützlich für Anfänger wie mich.
Ich liebe den lockeren Bezug auf Ihre Website. Ich hoffe wirklich, dass ich sie nie besuche, da sie offenbar voller Sicherheitslücken ist.
/s
Was ist mit dem Verpacken der Ausgabe in wp_strip_all_tags()?
https://codex.wordpress.org/Function_Reference/wp_strip_all_tags
Ich benutze diese Funktion immer, wenn ich jemanden auf meiner Website posten lasse, den ich nicht sehr gut kenne.
Ich habe nicht verstanden, wie man ein JS-Skript einpflanzen kann, wenn der Angreifer keinen Zugriff auf die Serverdateien hat. Wenn ich der Angreifer wäre, würde ich den gesamten Inhalt der Website und die Datenbank löschen.
Das ist großartig! Ich arbeite gerade mit Craft CMS und bin auf diese Seite gestoßen, als ich mir Twig anschaue: http://bit.ly/1BnRslK. Ich hoffe, es ist hilfreich für diejenigen, die versuchen, diese Prinzipien in Craft nachzubilden.
Vielen Dank dafür. Als selbst gelernter Designer/Entwickler, der hauptsächlich HTML, CSS, JS verwendet, scheint dies ein Bereich zu sein, über den niemand wirklich spricht (oder vielleicht weiß ich nicht, wo ich suchen soll). Habe definitiv einiges gelernt. Habe definitiv ein paar Dinge, die ich sofort beheben muss.
Leider hat fast kein Plugin diesen sauberen und sicheren Code. Aber ich hoffe, das wird sich ändern! – Wenn ich „gültigen Code“ oder „gut kodiert“ sehe – meistens sind die Plugins völlig unsicher!
Schauen Sie nur vor ein paar Wochen
http://blog.sucuri.net/2014/09/slider-revolution-plugin-critical-vulnerability-being-exploited.html
Danke für diesen großartigen Beitrag!
Was, wenn man htmlspecialchars() verwenden würde? Hat das immer noch die Sicherheitslücken?
Unter der Haube verwenden
esc_attrund ähnliche Funktionenhtmlspecialchars. Der größte Unterschied, den ich sehe, ist, dasshtmlspecialcharsmöglicherweise das Escaping von Anführungszeichen überspringt, wenn ein PHP-Flag gesetzt ist.http://php.net/htmlspecialchars
Es gibt einen Fehler:
esc_html_eechoed bereits, also machtecho esc_html_eein doppeltes Echo.In Ihrem Beispiel von
json_encode()zum Übergeben von PHP-Variablen an JS wäre der „WordPress Way“, stattdessenwp_localize_script()zu verwenden.Eine nützliche Funktion zum Escapen von Inhalten, die HTML enthalten können, ist
wp_kses_post(), die eine Abkürzung für die Funktionwp_kses()ist und gängige HTML-Tags whitelisted.Für mehr, schauen Sie sich
wp-includes/formatting.phpan.Danke für die Korrektur! Ich war zu eifrig beim Echo.
Entschuldigung, wenn ich das nicht verstehe, ich bin kein Backend-Entwickler und arbeite selten mit WordPress. Meine Frage ist, wie jemand den bösartigen Code in das benutzerdefinierte Eingabefeld einbringen könnte? Er hätte keinen Zugriff auf Ihr Dashboard, was bedeutet, dass Sie sowieso schon irgendwie gehackt wurden?
Wenn Sie ein Front-End-Dev sind, ist XSS hier weniger ein Problem, es sei denn, Ihre Besucher melden sich regelmäßig an oder haben andere Berechtigungen als nur Lesezugriff auf die Website. Denken Sie jedoch daran, dass XSS, selbst wenn es nicht destruktiv ist, lästig sein kann. Hacker müssen nicht unbedingt Anmeldedaten stehlen, um ihren Spaß zu haben, die Website nach einer Verunstaltung zu bereinigen, ist kein Spaß.
Die meisten Hackerangriffe greifen nicht direkt auf Ihr Dashboard zu, sondern nutzen Schwachstellen in Themes und Plugins aus. (Anstatt durch die Hintertür einzubrechen, bemerkt ein Dieb stattdessen ein Fenster im Keller, das leicht zu öffnen ist.)
WP ist mit Hooks und Filtern sehr erweiterbar, aber in dieser Macht, wenn etwas nicht gut geschrieben ist, kann es Sie Sicherheitsrisiken aussetzen. Selbst wenn Ihr eigener Code kugelsicher ist, sind andere Plugins im Ökosystem möglicherweise nicht so und da müssen Sie vorsichtig sein.
Viele Exploits stammen nicht aus dem betreffenden Plugin, sondern aus der Ausnutzung von Schwachstellen anderer Plugins. (Dieses Slider-Plugin ist ein Beispiel für einen sehr fiesen Bug.)
Mark Jaquith hatte einen WordCamp-Vortrag zu diesem Thema, der eine gute weiterführende Lektüre darstellt.