Seien Sie wachsam: PHP- und WordPress-Funktionen, die Ihre Website unsicher machen können
Veröffentlicht: 2022-03-10Die Sicherheit einer WordPress-Website (oder einer anderen) ist ein vielschichtiges Problem. Der wichtigste Schritt, den jeder unternehmen kann, um sicherzustellen, dass eine Website sicher ist, besteht darin, daran zu denken, dass kein einzelner Prozess oder keine einzelne Methode ausreicht, um sicherzustellen, dass nichts Schlimmes passiert. Aber es gibt Dinge, die Sie tun können, um zu helfen. Eine davon besteht darin, im Code, den Sie schreiben, und im Code anderer, die Sie bereitstellen, auf Funktionen zu achten, die negative Folgen haben können. In diesem Artikel behandeln wir genau diese: Funktionen, die ein WordPress-Entwickler vor der Verwendung klar überlegen sollte.
WordPress selbst bietet eine beträchtliche Bibliothek von Funktionen, von denen einige gefährlich sein können. Darüber hinaus gibt es viele PHP-Funktionen, die ein WordPress (PHP)-Entwickler mit einer gewissen Häufigkeit verwendet, die bei Verwendung gefährlich sein kann.
Alle diese Funktionen haben legitime und sichere Verwendungszwecke, aber sie sind auch Funktionen, die es leicht machen können, dass Ihr Code für schlechte Zwecke missbraucht wird. Wir behandeln die Dinge, die am wahrscheinlichsten die Ursache einer Sicherheitslücke sind, und warum Sie darauf achten müssen. Wir werden zuerst PHP-Funktionen in Ihrem Code herunterfahren, die Angreifer für Böses verwenden können, und dann über WordPress-spezifische PHP-Funktionen sprechen, die ebenfalls Kopfschmerzen verursachen können.
PHP-Funktionen, auf die Sie achten sollten
Wie gesagt, PHP enthält viele einfach zu bedienende Funktionen. Einige dieser Funktionen sind berüchtigt für die Leichtigkeit, mit der Menschen damit schlechte Dinge anstellen können. Alle diese Funktionen haben eine angemessene Verwendung, aber seien Sie vorsichtig, wie Sie sie verwenden und wie anderer Code, den Sie in ein Projekt ziehen, funktioniert.
Wir gehen davon aus, dass Sie bereits magische Anführungszeichen haben und Globals registrieren, wenn Ihre PHP-Version sie unterstützt. Sie waren in PHP 5 und höher standardmäßig deaktiviert, konnten aber für Versionen unter 5.4 aktiviert werden. Nur wenige Hosts erlaubten es, aber ich denke nicht, dass ein PHP-Sicherheitsartikel wirklich vollständig ist, ohne sie einzubeziehen.
Oder eine Erwähnung, dass PHP 5.6 die letzte 5.x-Version ist, die noch immer Sicherheitsunterstützung bietet. Du solltest zumindest dabei sein. Und Sie sollten einen Plan haben, auf PHP 7 umzusteigen, bevor der Support für 5.6 Ende 2018 endet.
Danach müssen Sie sich nur noch mit einigen riskanten Funktionen befassen. Beginnen mit…
extract
ist eine schlechte Nachricht, insbesondere bei $_POST
oder ähnlichem
Glücklicherweise ist die Verwendung der extract
von PHP weitgehend in Ungnade gefallen. Der Kern seiner Verwendung bestand darin, dass Sie es auf einem Array von Daten ausführen konnten und seine Schlüssel-Wert-Paare zu lebenden Variablen in Ihrem Code wurden. Damit
$arr = array( 'red' => 5 ); extract($arr); echo $red; // 5
würde funktionieren. Das ist cool, aber es ist auch wirklich gefährlich, wenn Sie $_GET
, $_POST
usw. extrahieren. In diesen Fällen erstellen Sie das register_globals
-Problem im Wesentlichen selbst neu: Ein externer Angreifer kann Ihre Variablenwerte einfach ändern, indem er eine Abfragezeichenfolge hinzufügt oder Formularfeld. Die beste Lösung ist einfach: Verwenden Sie kein extract
.
Wenn Sie das zu extrahierende Array selbst erstellen, ist die Verwendung von extract
kein spezielles Sicherheitsproblem, und in einigen Fällen kann es nützlich sein. Aber alle Verwendungen davon haben das Problem, zukünftige Leser zu verwirren. Das Erstellen eines Arrays und das Aufrufen von extract
ist verwirrender, als nur Ihre Variablen zu deklarieren. Ich ermutige Sie daher, stattdessen manuelle Deklarationen vorzunehmen, es sei denn, dies ist völlig unmöglich.
Wenn Sie bei Benutzereingaben extract
müssen, sollten Sie immer das Flag EXTR_SKIP
verwenden. Dies hat immer noch das Problem der Verwirrung, beseitigt jedoch die Möglichkeit, dass Ihre voreingestellten Werte von einem böswilligen Außenstehenden über eine einfache Abfragezeichenfolge oder eine Änderung des Webformulars geändert werden können. (Weil es bereits eingestellte Werte „überspringt“.)
„ eval
ist böse“, weil willkürlicher Code beängstigend ist
eval
in PHP und fast jeder anderen Sprache, die es enthält, steht immer ganz oben auf Listen wie dieser. Und das aus gutem Grund. Die offizielle Dokumentation von PHP auf PHP.net sagt es ziemlich offen:
ACHTUNG : Das Sprachkonstrukt eval() ist sehr gefährlich, da es die Ausführung von beliebigem PHP-Code erlaubt. Von seiner Verwendung wird daher abgeraten. Wenn Sie sorgfältig überprüft haben, dass es keine andere Möglichkeit gibt, als dieses Konstrukt zu verwenden, achten Sie besonders darauf, keine vom Benutzer bereitgestellten Daten daran zu übergeben, ohne es vorher ordnungsgemäß zu validieren.
eval
lässt jeden beliebigen String in Ihrem Programm laufen, als wäre es PHP-Code. Das bedeutet, dass es für die „Meta-Programmierung“ nützlich ist, bei der Sie ein Programm erstellen, das selbst ein Programm erstellen kann. Es ist auch sehr gefährlich, denn wenn Sie jemals zulassen, dass beliebige Quellen (wie ein Textfeld auf einer Webseite) sofort an Ihren eval
-String-Evaluator übergeben werden, haben Sie es einem böswilligen Angreifer plötzlich trivial leicht gemacht, so ziemlich alles zu tun, was PHP kann auf Ihrem Server tun. Dazu gehören natürlich das Herstellen einer Verbindung zur Datenbank, das Löschen von Dateien und so ziemlich alles andere, was jemand tun kann, wenn er sich per SSH in eine Maschine einloggt. Das ist schlecht.
Wenn Sie eval
in Ihrem Programm verwenden müssen, sollten Sie sich alle Mühe geben, um sicherzustellen, dass Sie nicht zulassen, dass willkürliche Benutzereingaben hineingereicht werden. Und wenn Sie beliebigen Benutzern Zugriff auf die Eingaben für eval
gewähren müssen , beschränken Sie ihre Möglichkeiten über eine schwarze Liste von Befehlen, die Sie nicht ausführen lassen, oder (besser, aber weitaus schwieriger zu implementieren) eine weiße Liste, die nur die Befehle enthält, die Sie ausführen für sicher halten. Besser noch, lassen Sie nur eine kleine Anzahl spezifischer Parameteränderungen zu, z. B. nur validierte Ganzzahlen.
Aber denken Sie immer an diese Zeile von Rasmus Lerdorf, dem Gründer von PHP:
"Wenn `eval()` die Antwort ist, stellen Sie mit ziemlicher Sicherheit die falsche Frage."
Variationen über eval
Neben dem wohlbekannten eval
gibt es eine Vielzahl anderer Möglichkeiten, wie PHP in der Vergangenheit Strings als Code ausgewertet hat. Die beiden, die für WordPress-Entwickler am relevantesten sind, sind preg_replace
mit dem Modifikator /e
und create_function
. Jedes funktioniert ein wenig anders, und preg_replace
nach PHP 5.5.0 funktioniert überhaupt nicht. (PHP 5.5 und niedriger erhalten keine offiziellen Sicherheitsupdates mehr und sollten daher am besten nicht verwendet werden.)
/e
-Modifikatoren in Regex sind auch „böse“
Wenn Sie PHP 5.4.x oder niedriger verwenden, sollten Sie nach PHP- preg_replace
-Aufrufen Ausschau halten, die mit einem e enden. Das kann so aussehen:
$html = preg_replace( '( (.*?) )e', '" " . strtoupper("$2") . " "', $html );) // or $html = preg_replace( '~ (.*?) ~e', '" " . strtoupper("$2") . " "', $html );)
$html = preg_replace( '( (.*?) )e', '" " . strtoupper("$2") . " "', $html );) // or $html = preg_replace( '~ (.*?) ~e', '" " . strtoupper("$2") . " "', $html );)
$html = preg_replace( '( (.*?) )e', '" " . strtoupper("$2") . " "', $html );) // or $html = preg_replace( '~ (.*?) ~e', '" " . strtoupper("$2") . " "', $html );)
$html = preg_replace( '( (.*?) )e', '" " . strtoupper("$2") . " "', $html );) // or $html = preg_replace( '~ (.*?) ~e', '" " . strtoupper("$2") . " "', $html );)
$html = preg_replace( '( (.*?) )e', '" " . strtoupper("$2") . " "', $html );) // or $html = preg_replace( '~ (.*?) ~e', '" " . strtoupper("$2") . " "', $html );)
$html = preg_replace( '( (.*?) )e', '" " . strtoupper("$2") . " "', $html );) // or $html = preg_replace( '~ (.*?) ~e', '" " . strtoupper("$2") . " "', $html );)
$html = preg_replace( '( (.*?) )e', '" " . strtoupper("$2") . " "', $html );) // or $html = preg_replace( '~ (.*?) ~e', '" " . strtoupper("$2") . " "', $html );)
$html = preg_replace( '( (.*?) )e', '" " . strtoupper("$2") . " "', $html );) // or $html = preg_replace( '~ (.*?) ~e', '" " . strtoupper("$2") . " "', $html );)
$html = preg_replace( '( (.*?) )e', '" " . strtoupper("$2") . " "', $html );) // or $html = preg_replace( '~ (.*?) ~e', '" " . strtoupper("$2") . " "', $html );)
PHP bietet verschiedene Möglichkeiten, Ihren regulären Ausdruck „einzuzäunen“, aber das Wichtigste, wonach Sie Ausschau halten sollten, ist „e“ als letztes Zeichen für das erste Argument von preg_replace
. Wenn es da ist, übergeben Sie tatsächlich das gesamte gefundene Segment als Argument an Ihr Inline-PHP und eval
es dann aus. Dies hat genau die gleichen Probleme wie eval
, wenn Sie Benutzereingaben in Ihre Funktion einfließen lassen. Der Beispielcode kann ersetzt werden, indem stattdessen preg_replace_callback
verwendet wird. Der Vorteil davon ist, dass Sie Ihre Funktion ausgeschrieben haben, sodass es für einen Angreifer schwieriger ist, das zu ändern, was ausgewertet wird. Also würdest du das obige schreiben als:
// uppercase headings $html = preg_replace_callback( '( (.*?) )', function ($m) { return " " . strtoupper($m[2]) . " "; }, $html );
// uppercase headings $html = preg_replace_callback( '( (.*?) )', function ($m) { return " " . strtoupper($m[2]) . " "; }, $html );
// uppercase headings $html = preg_replace_callback( '( (.*?) )', function ($m) { return " " . strtoupper($m[2]) . " "; }, $html );
// uppercase headings $html = preg_replace_callback( '( (.*?) )', function ($m) { return " " . strtoupper($m[2]) . " "; }, $html );
// uppercase headings $html = preg_replace_callback( '( (.*?) )', function ($m) { return " " . strtoupper($m[2]) . " "; }, $html );
Es ist auch schlecht, Benutzereingaben create_function
s zuzulassen …
PHP hat auch die Funktion create_function
. Dies ist jetzt in PHP 7.2 veraltet, aber es war eval
sehr ähnlich und hatte die gleichen grundlegenden Nachteile: Es ermöglicht, dass ein String (das zweite Argument) in ausführbares PHP umgewandelt wird. Und es hatte die gleichen Risiken: Es ist zu einfach für Sie, einem schlauen Cracker versehentlich die Möglichkeit zu geben, irgendetwas auf Ihrem Server zu tun, wenn Sie nicht aufpassen.
Dieser ist jedoch, wenn Sie mit PHP über 5.3 arbeiten, noch einfacher zu beheben als preg_replace
. Sie können einfach Ihre eigene anonyme Funktion erstellen, ohne Zeichenfolgen als Vermittler zu verwenden. Dies ist sowohl sicherer als auch lesbarer, zumindest in meinen Augen.
assert
ist auch eval
-Like
assert
ist keine Funktion, die viele PHP-Entwickler in WordPress oder außerhalb davon verwenden. Seine Absicht besteht darin, sehr einfache Behauptungen über Vorbedingungen für Ihren Code zu erstellen. Aber es unterstützt auch eine Operation vom Typ eval
. Aus diesem Grund sollten Sie davor genauso vorsichtig sein wie vor eval
. Stringbasierte Behauptungen (der Kern warum das schlecht ist) sind in PHP 7.2 ebenfalls veraltet, was bedeutet, dass sie in Zukunft weniger besorgniserregend sein sollten.
Das Einbinden von Variablendateien ist eine Möglichkeit, möglicherweise eine unkontrollierte PHP-Ausführung zuzulassen
Wir haben ziemlich gut untersucht, warum eval
schlecht ist, aber etwas wie include
oder require($filename'.php')
kann ähnlich schlechte Nachrichten sein, insbesondere wenn $filename
auf einen vom Benutzer kontrollierbaren Wert gesetzt wird. Der Grund unterscheidet sich geringfügig von eval
. Variable Dateinamen werden häufig für Dinge wie einfaches URL-zu-Datei-Routing in Nicht-WordPress-PHP-Apps verwendet. Aber Sie können sie auch in WordPress sehen.

Der Kern des Problems besteht darin, dass Sie beim include_once
require_once
include
require
Skript dazu bringen, die eingeschlossene Datei auszuführen. Es ist mehr oder weniger eine konzeptionelle eval
dieser Datei, obwohl wir selten so darüber nachdenken.
Wenn Sie alle Dateien geschrieben haben, die Ihre Variablen include
könnten, und darüber nachgedacht haben, was passieren würde, wenn dies der Fall ist, ist alles in Ordnung. Aber es ist eine schlechte Nachricht, wenn Sie nicht darüber nachgedacht haben, was das Einbinden von password.php
oder wp-config.php
include
Es ist auch eine schlechte Nachricht, wenn jemand eine schädliche Datei hinzufügen und dann Ihr include
ausführen könnte (obwohl Sie an diesem Punkt wahrscheinlich größere Probleme haben).
Die Lösung dafür ist jedoch nicht allzu schwierig: Hardcode enthält, wenn Sie können. Wenn dies nicht möglich ist, führen Sie entweder eine Whitelist (besser) oder eine Blacklist mit Dateien, die aufgenommen werden können. Wenn die Dateien in der Whitelist sind (das heißt: Sie haben geprüft, was sie beim Hinzufügen tut), wissen Sie, dass Sie sicher sind. Wenn es sich nicht auf Ihrer Whitelist befindet, wird es nicht in Ihr Skript aufgenommen. Mit dieser einfachen Optimierung sind Sie ziemlich sicher. Eine Whitelist würde in etwa so aussehen:
$white_list = ['db.php', filter.php', 'condense.php'] If (in_array($white_list, $file_to_include)) { include($file_to_include); }
Übergeben Sie niemals Benutzereingaben an shell_exec
und Varianten
Dies ist eine große Sache. shell_exec
, system
, exec
und Backticks in PHP ermöglichen es dem Code, den Sie ausführen, mit der zugrunde liegenden (normalerweise Unix-) Shell zu kommunizieren. Dies ähnelt dem, was eval
gefährlich macht, aber verdoppelt. Verdoppelt, denn wenn Sie Benutzereingaben hier unvorsichtig durchlassen, ist der Angreifer nicht einmal an die Beschränkungen von PHP gebunden.
Die Möglichkeit, Shell-Befehle von PHP aus auszuführen, kann als Entwickler sehr nützlich sein. Aber wenn Sie jemals die Eingabe eines Benutzers dort zulassen, kann er heimlich viele gefährliche Kräfte erlangen. Ich würde also so weit gehen zu sagen, dass Benutzereingaben niemals an Funktionen vom Typ shell_exec
übergeben werden sollten.
Der beste Weg, den ich mir vorstellen könnte, um mit dieser Art von Situation umzugehen, wenn Sie versucht wären, sie zu implementieren, wäre, den Benutzern Zugriff auf eine kleine Menge bekanntermaßen sicherer vordefinierter Shell-Befehle zu gewähren. Das könnte man absichern. Aber selbst dann würde ich Sie warnen, sehr vorsichtig zu sein.
Achten Sie unserialize
; Es führt Code automatisch aus
Die Kernaktion, serialize
für ein lebendes PHP-Objekt aufzurufen, diese Daten irgendwo zu speichern und diesen gespeicherten Wert später zu unserialize
, um dieses Objekt wieder zum Leben zu erwecken, ist cool. Es ist auch ziemlich häufig, aber es kann riskant sein. Warum riskant? Wenn die Eingabe für diesen unserialize
nicht vollständig sicher ist (z. B. als Cookie und nicht in Ihrer Datenbank gespeichert wird), kann ein Angreifer den internen Zustand Ihres Objekts so ändern, dass der unserialize
etwas Schlechtes bewirkt.
Dieser Exploit ist eher esoterisch und wird weniger wahrscheinlich bemerkt als ein eval
-Problem. Wenn Sie jedoch ein Cookie als Speichermechanismus für serialisierte Daten verwenden, verwenden Sie serialize
nicht für diese Daten. Verwenden Sie so etwas wie json_encode
und json_decode
. Mit diesen beiden wird PHP niemals automatisch Code ausführen.
Die zentrale Schwachstelle besteht darin, dass PHP, wenn es einen String in eine Klasse __wakeup
unserialize
für diese Klasse aufruft. Wenn nicht validierte Benutzereingaben deserialisiert werden dürfen, könnte etwas wie ein Datenbankaufruf oder eine unserialized
in der __wakeup
Methode möglicherweise auf einen gefährlichen oder unerwünschten Ort verweisen.
unserialize
unterscheidet sich von den eval
-Schwachstellen, da es die Verwendung magischer Methoden für Objekte erfordert. Anstatt eigenen Code zu erstellen, ist der Angreifer gezwungen, Ihre bereits geschriebenen Methoden für ein Objekt zu missbrauchen. Sowohl die magischen Methoden __destruct
als auch __toString
für Objekte sind ebenfalls riskant, wie diese OWASP-Wiki-Seite erklärt.
Im Allgemeinen ist es in Ordnung, wenn Sie die Methoden __wakeup
, __destruct
oder __toString
in Ihren Klassen nicht verwenden. Aber da Sie später vielleicht sehen, wie jemand sie zu einer Klasse hinzufügt, ist es eine gute Idee, niemals einen Benutzer in die Nähe Ihrer Aufrufe zu lassen, um alle öffentlichen Daten für diese Art von Verwendung zu serialize
und zu unserialize
und weiterzugeben, obwohl etwas wie JSON ( json_encode
und json_decode
) vorhanden ist ist niemals eine automatische Codeausführung.
Das Abrufen von URLs mit file_get_contents
ist riskant
Eine gängige Praxis beim schnellen Schreiben von PHP-Code, der eine externe URL aufrufen muss, besteht darin, nach file_get_contents
zu greifen. Es ist schnell, es ist einfach, aber es ist nicht supersicher.
Das Problem mit file_get_contents
ist subtil, aber es kommt häufig vor, dass Hosts PHP manchmal so konfigurieren, dass Sie nicht einmal auf externe URLs zugreifen können. Dies soll Sie schützen.
Das Problem hierbei ist, dass file_get_contents
entfernte Seiten für Sie abruft. Dabei wird jedoch nicht die Integrität der HTTPS-Protokollverbindung überprüft. Das bedeutet, dass Ihr Skript möglicherweise Opfer eines Man-in-the-Middle-Angriffs werden könnte, der es einem Angreifer ermöglichen würde, so ziemlich alles, was er will, in Ihr Ergebnis der Seite file_get_contents
.
Dies ist ein eher esoterischer Angriff. Aber um mich davor zu schützen, wenn ich modernes (Composer-basiertes) PHP schreibe, verwende ich fast immer Guzzle, um die sicherere cURL-API zu umschließen. In WordPress ist es sogar noch einfacher: Verwenden wp_remote_get
. Es funktioniert viel konsistenter als file_get_contents
und überprüft standardmäßig SSL-Verbindungen. (Sie können das ausschalten, aber, ähm, vielleicht nicht ...) Besser noch, aber etwas lästiger, darüber zu sprechen, sind wp_safe_remote_get
usw. Diese funktionieren identisch mit den Funktionen ohne safe_
in ihrem Namen, aber sie werden es schaffen Stellen Sie sicher, dass unterwegs keine unsicheren Um- und Weiterleitungen passieren.
Vertrauen Sie der URL-Validierung von filter_var
nicht blind
Das ist also ein wenig obskur, also Requisiten an Chris Weigman, der es in diesem WordCamp-Vortrag erklärt hat. Im Allgemeinen ist filter_var
von PHP eine großartige Möglichkeit, Daten entweder zu validieren oder zu bereinigen. (Obwohl, lassen Sie sich nicht verwirren, was Sie versuchen zu tun …)
Das Problem hier ist ziemlich spezifisch: Wenn Sie versuchen, es zu verwenden, um sicherzustellen, dass eine URL sicher ist, validiert filter_var
das Protokoll nicht. Das ist nicht oft ein Problem, aber wenn Sie Benutzereingaben zur Validierung an diese Methode übergeben und FILTER_VALIDATE_URL
verwenden, wird etwas wie javascript://comment%0aalert(1)
durchkommen. Das heißt, dies kann ein sehr guter Vektor für einen einfachen XSS-Angriff an einer Stelle sein, die Sie nicht erwartet haben.
Für die Validierung einer URL hat die esc_url
-Funktion von WordPress einen ähnlichen Einfluss, lässt aber nur erlaubte Protokolle durch. javascript
ist nicht in der Standardliste, also würde es Sie schützen. Im Gegensatz zu filter_var
gibt es jedoch eine leere Zeichenfolge (nicht falsch) für ein unzulässiges Protokoll zurück, das an es übergeben wird.
WordPress-spezifische Funktionen, die Sie im Auge behalten sollten
Zusätzlich zu den potenziell anfälligen Kern-PHP-Funktionen gibt es einige WordPress-spezifische Funktionen, die ein bisschen schwierig sein können. Einige davon sind den oben aufgeführten gefährlichen Funktionen sehr ähnlich, andere etwas anders.
WordPress wird mit maybe_unserialize
Dies ist wahrscheinlich offensichtlich, wenn Sie das Obige lesen. In WordPress gibt es eine Funktion namens maybe_unserialize
, die, wie Sie sich vorstellen können, das, was ihr übergeben wird, bei Bedarf deserialisiert.
Es gibt keine neue Schwachstelle, die dadurch eingeführt wird, das Problem ist einfach, dass genau wie die Core unserialize
diese dazu führen kann, dass ein verwundbares Objekt ausgenutzt wird, wenn es deserialisiert wird.
is_admin
antwortet nicht, wenn ein Benutzer ein Administrator ist!
Dieser ist ziemlich einfach, aber der Name der Funktion ist mehrdeutig, und daher neigt er dazu, die Leute zu verwirren oder zu übersehen, wenn Sie es eilig haben. Sie sollten immer überprüfen, ob ein Benutzer, der versucht, eine Aktion in WordPress auszuführen, über die erforderlichen Rechte und Privilegien verfügt, um diese Aktion auszuführen. Dazu sollten Sie die Funktion current_user_can
verwenden.
Aber Sie könnten fälschlicherweise denken, dass is_admin
Ihnen sagen wird, ob der aktuelle Benutzer ein Konto auf Administratorebene ist und daher in der Lage sein sollte, eine Option festzulegen, die Ihr Plugin verwendet. Das ist ein Fehler. Was is_admin
in WordPress tut, sagt Ihnen stattdessen, ob die aktuelle Seitenlast auf der Verwaltungsseite der Website liegt (im Gegensatz zur Vorderseite). Jeder Benutzer, der auf eine Verwaltungsseite (wie das „Dashboard“) zugreifen kann, kann diese Prüfung also potenziell bestehen. Solange Sie sich daran erinnern, dass es bei is_admin
um den Seitentyp geht, nicht um den aktuellen Benutzer, ist alles in Ordnung.
add_query_arg()
bereinigt URLs nicht
Dies ist nicht so üblich, aber es gab vor einigen Jahren eine große Welle von Updates im WordPress-Ökosystem, weil die öffentliche Dokumentation zu diesen Funktionen nicht korrekt war. Das Kernproblem besteht darin, dass die Funktion add_query_arg
(und ihre Umkehrung remove_query_arg
) die Site-URL nicht automatisch bereinigt, wenn eine URL nicht an sie übergeben wurde, und die Leute dachten, dass dies der Fall wäre. Viele Plugins wurden vom Codex in die Irre geführt und nutzten diesen daher unsicher.
Die Kernsache, die sie anders machen mussten: das Ergebnis eines Aufrufs dieser Funktion bereinigen, bevor sie verwendet wird. Wenn Sie das tun, sind Sie wirklich sicher vor den XSS-Angriffen, für die Sie sie hielten. Das sieht also ungefähr so aus:
echo esc_url( add_query_arg( 'foo', 'bar' ) );
$wpdb->query()
ist offen für SQL-Injection-Angriffe
Wenn Sie sich mit SQL-Injection auskennen, mag dies albern erscheinen, ja sogar überflüssig, es aufzulisten. Denn die Sache ist die, dass Sie auf irgendeine Weise auf eine Datenbank zugreifen (z. B. mit mysqli
oder PDO-Datenbanktreibern), um Datenbankabfragen zu erstellen, die SQL-Injection-Angriffe ermöglichen.
Der Grund, warum ich ausdrücklich $wpdb->query
, ist, dass einige andere Methoden (wie insert
, delete
, etc.) auf $wpdb
Injektionsangriffe für Sie erledigen. Wenn Sie außerdem daran gewöhnt sind, grundlegende WordPress-Datenbankabfragen mit WP_Query
oder ähnlichem durchzuführen, müssen Sie die SQL-Injection nicht in Betracht ziehen. Aus diesem Grund rufe ich es an: Um sicherzustellen, dass Sie verstehen, dass ein Injektionsangriff auf die Datenbank möglich ist, wenn Sie zum ersten Mal versuchen, $wpdb
zu verwenden, um Ihre eigene Abfrage zu erstellen.
Was ist zu tun? Verwenden Sie $wpdb->prepare()
und dann $wpdb->query()
. Sie sollten auch sicherstellen, dass Sie sich vorbereiten, bevor Sie andere „Getting“-Methoden von $wpdb
wie get_row()
und get_var()
. Sonst könnten Sie von Bobby Tables erwischt werden.
esc_sql
Sie auch nicht vor SQL-Injection
Für die meisten WordPress-Entwickler würde ich sagen, dass esc_sql
keine Bedeutung hat, aber es sollte. Wie wir gerade erwähnt haben, sollten Sie wpdb->prepare()
verwenden, bevor Sie eine Datenbankabfrage durchführen. Das wird dich schützen. Aber es ist verlockend und verständlich, dass ein Entwickler stattdessen nach esc_sql
. Und sie könnten erwarten, dass es sicher wäre.
Das Problem ist, dass esc_sql
keinen so robusten Schutz gegen SQL-Injection bietet. Es ist wirklich eine verherrlichte Version der add_slashes
-Funktion von PHP, von deren Verwendung Sie jahrelang abgeraten haben, um Ihre Datenbank zu schützen.
Es gibt noch mehr zu tun, aber das ist ein großer Anfang
Sicherheit ist viel mehr, als nur nach Funktionen in Ihrem Code Ausschau zu halten, die Angreifer missbrauchen können. Wir haben zum Beispiel nicht ausführlich über die Notwendigkeit diskutiert, alle Daten, die Sie von Benutzern erhalten, zu validieren und zu bereinigen und zu entkommen, bevor Sie sie auf einer Webseite veröffentlichen (obwohl ich kürzlich einen Artikel zu diesem Thema veröffentlicht habe, „Protecting Your WordPress Website gegen einen Cross-Site-Scripting-Angriff“). Sie können und sollten dies jedoch als Teil einer umfassenderen Sicherheitsstrategie nutzen.
Es ist eine großartige Idee, diese Liste leicht zu missbrauchender Funktionen bei der letzten Inspektion an Ihrer Seite zu haben, bevor Sie ein neues Plugin in WordPress bereitstellen. Aber Sie sollten auch sicherstellen, dass Sie der Sicherheit Ihres Hostings vertrauen, sicherstellen, dass Ihre Benutzer gute Passwörter haben und vieles mehr.
Das Wichtigste, was Sie bei der Sicherheit beachten sollten, ist, dass Ihr schwächstes Glied dasjenige ist, auf das es ankommt. Gute Praktiken in einem Bereich verstärken mögliche Schwachstellen woanders, aber sie können ihn nie vollständig korrigieren. Aber seien Sie wachsam bei diesen Funktionen, und Sie werden bei den meisten einen Vorsprung haben.