Advertisement
  1. Code
  2. Plugins

Benutzerdefinierte Datenbanktabellen: Sicherheit geht vor

Scroll to top
Read Time: 11 min
This post is part of a series called Custom Database Tables.
Custom Database Tables: Creating the Table
Custom Database Tables: Creating an API

German (Deutsch) translation by Wei Zhang (you can also view the original English article)

Dies ist Teil zwei einer Serie über benutzerdefinierte Datenbanktabellen in WordPress. Im ersten Teil haben wir die Gründe dafür und dagegen mit benutzerdefinierten Tabellen besprochen. Wir haben uns einige Details angesehen, die berücksichtigt werden müssten - Spaltenbenennung, Spaltentypen - sowie das Erstellen der Tabelle. Bevor wir fortfahren, müssen wir uns mit dem sicheren Umgang mit diesem neuen Tisch beschäftigen. In einem früheren Artikel ging es um die allgemeine Desinfektion und Validierung. In diesem Lernprogramm werden wir uns dies im Zusammenhang mit Datenbanken genauer ansehen.

Die Sicherheit bei der Interaktion mit einer Datenbanktabelle ist von größter Bedeutung. Deshalb behandeln wir sie früh in der Serie. Wenn dies nicht korrekt geschieht, können Sie Ihre Tabelle über die SQL-Injection für die Bearbeitung offen lassen. Es könnte einem Hacker ermöglichen, Informationen zu extrahieren, Inhalte zu ersetzen oder sogar das Verhalten Ihrer Website zu ändern - und der Schaden, den sie anrichten könnten, ist nicht auf Ihre benutzerdefinierte Tabelle beschränkt.

Nehmen wir an, wir möchten, dass Administratoren Datensätze aus unserem Aktivitätsprotokoll löschen. Ein häufiger Fehler, den ich gesehen habe, ist folgender:

Also, was ist hier los? Jede Menge: Sie haben keine geprüften Berechtigungen, sodass jeder ein Aktivitätsprotokoll löschen kann. Sie haben auch keine Nonces geprüft, sodass ein Administratorbenutzer selbst bei Berechtigungsprüfungen dazu gebracht werden kann, ein Protokoll zu löschen. Dies wurde alles in diesem Tutorial behandelt. Ihr dritter Fehler besteht jedoch aus den ersten beiden: Die Funktion unsafe_delete_log() verwendet den übergebenen Wert in einem SQL-Befehl, ohne ihn vorher zu umgehen. Dadurch bleibt es weit offen für Manipulationen.

Nehmen wir an, die beabsichtigte Verwendung ist

Was ist, wenn ein Angreifer besucht (oder einen Admin in einen Besuch getrieben hat):www.unsafe-site.com?action=delete-activity-log&log_id=1;%20DROP%20TABLE%20wp_posts.Die log_id enthält einen SQL-Befehl, der anschließend in $sql eingefügt wird und wie folgt ausgeführt wird:

Das Ergebnis: Die gesamte wp_posts-Tabelle wird gelöscht. Ich habe Code wie diesen in Foren gesehen - und das Ergebnis ist, dass jeder, der seine Website besucht, jede Tabelle in seiner Datenbank aktualisieren oder löschen kann.

Wenn die ersten beiden Fehler korrigiert wurden, ist es für diese Art von Angriff zwar schwieriger, aber nicht unmöglich, und schützt nicht vor einem „Angreifer“, der zum Löschen von Aktivitätsprotokollen berechtigt ist. Es ist äußerst wichtig, Ihre Site vor SQL-Injektionen zu schützen. Es ist auch unglaublich einfach: WordPress bietet die Methode prepare. In diesem speziellen Beispiel:

Der SQL-Befehl würde jetzt als ausführen


Datenbankabfragen bereinigen

Die meisten Bereinigungen können ausschließlich mit$wpdb global durchgeführt werden, insbesondere mit der Methode prepare. Es bietet auch Methoden zum sicheren Einfügen und Aktualisieren von Daten in Tabellen. Diese funktionieren normalerweise, indem sie eine unbekannte Eingabe ersetzen oder eine Eingabe einem Formatplatzhalter zuordnen. Dieses Format teilt WordPress mit, welche Daten zu erwarten sind:

  • %sbezeichnet eine Zeichenfolge
  • %d bezeichnet eine ganze Zahl
  • %f bezeichnet einen Schwimmer

Wir betrachten zunächst drei Methoden, die Abfragen nicht nur bereinigen, sondern auch für Sie erstellen.

Daten einfügen

WordPress bietet die Methode $wpdb->insert(). Es ist ein Wrapper zum Einfügen von Daten in die Datenbank und übernimmt die Bereinigung. Es sind drei Parameter erforderlich:

  • Tabellenname - der Name der Tabelle
  • Daten - Array von Daten, die als Spalten-> Wert-Paare eingefügt werden sollen
  • Formate - Array von Formaten für den entsprechenden Wert im Datenarray (z. B.%s,%d,%f)

Beachten Sie, dass die Schlüssel der Daten Spalten sein sollten: Wenn es einen Schlüssel gibt, der nicht mit einer Spalte übereinstimmt, wird möglicherweise ein Fehler ausgegeben.

In den folgenden Beispielen haben wir die Daten explizit festgelegt - aber im Allgemeinen wären diese Daten von Benutzereingaben stammen - es könnte also alles sein. Wie in diesem Artikel besprochen, sollten die Daten zuerst validiert worden sein, um Fehler an den Benutzer zurückzugeben. Die Daten müssen jedoch noch bereinigt werden, bevor sie in unsere Tabelle eingefügt werden. Wir werden uns im nächsten Artikel dieser Serie mit der Validierung befassen.

Daten aktualisieren

Zur Aktualisierung der Daten in der Datenbank haben wir $wpdb->update() Diese Methode akzeptiert fünf Argumente:

  • Tabellenname - der Name der Tabelle
  • Daten - Array von Daten, die als Spalten-> Wertpaare aktualisiert werden sollen
  • Where - Array von Daten, die als Spalten-> Wertepaare übereinstimmen sollen
  • Datenformat - Array von Formaten für die entsprechenden Datenwerte
  • Where Format - Array von Formaten für die entsprechenden "Where" -Werte

Dadurch werden alle Zeilen, die mit dem where-Array übereinstimmen, mit Werten aus dem Datenarray aktualisiert. Wie bei $wpdb->insert() müssen die Schlüssel des Datenarrays wieder mit einer Spalte übereinstimmen. Bei einem Fehler wird false zurückgegeben oder die Anzahl der aktualisierten Zeilen.

Im folgenden Beispiel aktualisieren wir alle Datensätze mit der Protokoll-ID '14' (dies sollte höchstens ein Datensatz sein, da dies unser Primärschlüssel ist). Es aktualisiert die Benutzer-ID auf 2 und die Aktivität auf "bearbeitet".

Löschen

Seit 3.4 bietet WordPress außerdem die $wpdb->delete () - Methode zum einfachen (und sicheren) Löschen von Zeilen. Diese Methode benötigt drei Parameter:

  • Tabellenname - der Name der Tabelle
  • Where - Array von Daten, die als Spalten-> Wertepaare übereinstimmen sollen
  • Formate - Array von Formaten für den entsprechenden Werttyp (z. B.%s,%d,%f)

Wenn Sie möchten, dass Ihr Code mit WordPress vor 3.4 kompatibel ist, müssen Sie die entsprechende Methode $wpdb->prepare verwenden, um die entsprechende SQL-Anweisung zu bereinigen. Ein Beispiel dafür wurde oben gegeben. Die $wpdb->delete -Methode gibt die Anzahl der gelöschten Zeilen zurück, oder false, um festzustellen, ob der Löschvorgang erfolgreich war.

esc_sql

Im Hinblick auf die obigen Methoden und die allgemeinere $wpdb->prepare() -Methode, die als nächstes beschrieben wird, ist diese Funktion etwas redundant. Es wird als nützlicher Wrapper für die $wpdb->escape() -Methode zur Verfügung gestellt, die selbst als addslashes bezeichnet wird. Da es normalerweise angemessener und ratsamer ist, die obigen drei Methoden oder $wpdb->prepare() zu verwenden, werden Sie wahrscheinlich feststellen, dass Sie esc_sql() selten benötigen.

Als einfaches Beispiel:

Allgemeine Anfragen

Für allgemeine SQL-Befehle, bei denen (dh Zeilen nicht eingefügt, entfernt oder aktualisiert werden), muss die Methode $wpdb->prepare() verwendet werden. Es akzeptiert eine variable Anzahl von Argumenten. Die erste ist die SQL-Abfrage, die wir ausführen möchten, wobei alle "unbekannten" Daten durch ihren entsprechenden Platzhalter ersetzt werden Diese Werte werden als zusätzliche Argumente in der Reihenfolge übergeben, in der sie angezeigt werden.

Zum Beispiel anstelle von:

wir haben

Die prepare-Methode macht zwei Dinge.

  1. Es wendet mysql_real_escape_string() (oder addSlashes()) auf die Werte an, die eingefügt werden. Insbesondere wird verhindert, dass Werte mit Anführungszeichen aus der Abfrage springen.
  2. Es wendet vsprintf() an, wenn die Werte der Abfrage hinzugefügt werden, um sicherzustellen, dass sie entsprechend formatiert sind (Ganzzahlen sind also Ganzzahlen, Floats sind Floats usw.). Deshalb hat unser Beispiel zu Beginn des Artikels alles außer der '1' gestrichen.

Kompliziertere Abfragen

Sie sollten feststellen, dass $wpdb->prepare, die Methoden Insert, Update und Delete alles sind, was Sie wirklich brauchen. Manchmal gibt es jedoch Umstände, unter denen ein „manueller“ Ansatz gewünscht wird - manchmal nur aus Sicht der Lesbarkeit. Angenommen, wir haben ein unbekanntes Array von Aktivitäten, für das wir alle Protokolle benötigen. Wir * könnten * die Platzhalter von%s dynamisch zur SQL-Abfrage hinzufügen, aber ein direkterer Ansatz scheint einfacher zu sein:

Die Idee ist, esc_sql und sanitize_title_for_query auf jedes Element im Array anzuwenden. Der erste fügt Schrägstriche hinzu, um den Begriffen zu entgehen - ähnlich wie $wpdb->prepare(). Die zweite Anwendung wendet einfach sanitize_title_with_dashes() an - das Verhalten kann jedoch durch Filter vollständig geändert werden. Die eigentliche SQL-Anweisung wird gebildet, indem das jetzt bereinigte Array in eine durch Kommas getrennte Zeichenfolge implodiert wird, die dem IN(...) - Teil der Abfrage hinzugefügt wird.

Wenn erwartet wird, dass das Array Ganzzahlen enthält, reicht es aus, intval() oder absint() zu verwenden, um jedes Element im Array zu bereinigen.

Whitelisting

In anderen Fällen kann Whitelisting angebracht sein. Die unbekannte Eingabe kann beispielsweise ein Array von Spalten sein, die in der Abfrage zurückgegeben werden sollen. Da wir wissen, was die Spalten der Datenbank sind, können wir sie einfach auf die weiße Liste setzen - alle Felder entfernen, die wir nicht kennen. Um unseren Code jedoch benutzerfreundlich zu gestalten, sollten wir die Groß- und Kleinschreibung nicht beachten. Dazu konvertieren wir alles, was wir erhalten, in Kleinbuchstaben - da in Teil 1 speziell Spaltennamen in Kleinbuchstaben verwendet wurden.

Whitelisting ist auch praktisch, wenn der ORDER BY-Teil der Abfrage festgelegt wird (wenn dies durch Benutzereingaben festgelegt wird): Daten können nur als DESC oder ASC bestellt werden.

LIKE Queries

SQL-Anweisungen LIKE unterstützen die Verwendung von Platzhaltern wie% (null oder mehr Zeichen) und _ (genau ein Zeichen), wenn der Abfrage Werte zugeordnet werden. Zum Beispiel würde der Wert foobar mit einer der Abfragen übereinstimmen:

Diese Sonderzeichen können jedoch tatsächlich in dem gesuchten Begriff vorhanden sein. Um zu verhindern, dass sie als Platzhalter interpretiert werden, müssen wir ihnen entgehen. Hierfür bietet WordPress die Funktion like_escape(). Beachten Sie, dass dies die SQL-Injection nicht verhindert - sondern nur die Zeichen% und _ entgeht: Sie müssen dennoch esc_sql() oder $wpdb->prepare() verwenden.

Query Wrapper-Funktionen

In den Beispielen, die wir uns angesehen haben, haben wir zwei andere Methoden von $wpdb verwendet:

  • $wpdb->query($sql) - Hiermit werden alle an sie gerichteten Abfragen ausgeführt und die Anzahl der betroffenen Zeilen zurückgegeben.
  • $wpdb->get_results($sql,$output) - Hiermit wird die Abfrage ausgeführt und die entsprechende Ergebnismenge (d. h. die übereinstimmenden Zeilen) zurückgegeben. $output legt das Format der zurückgegebenen Ergebnisse fest:
    • ARRAY_A - numerisches Array von Zeilen, wobei jede Zeile ein assoziatives Array ist und nach Spalten sortiert wird.
    • ARRAY_N - numerisches Array von Zeilen, wobei jede Zeile ein numerisches Array ist.
    • OBJECT - numerisches Array von Zeilen, wobei jede Zeile ein Zeilenobjekt ist. Standard.
    • OBJECT_K - assoziatives Array von Zeilen (eingegeben durch den Wert der ersten Spalte), wobei jede Zeile ein assoziatives Array ist.

Es gibt andere, die wir auch nicht erwähnt haben:

  • $wpdb->get_row($sql,$ouput,$row) - Dies führt die Abfrage aus und gibt eine Zeile zurück. $row legt fest, welche Zeile zurückgegeben werden soll. Standardmäßig ist dies 0, die erste übereinstimmende Zeile. $output legt das Format der Zeile fest:
    • ARRAY_A - Zeile ist ein column=>value-Paar.
    • ARRAY_N - Zeile ist ein numerisches Array von Werten.
    • OBJECT - Die Zeile wird als Objekt zurückgegeben. Standard.
  • $wpdb->get_col($sql,$column) - Dies führt die Abfrage aus und gibt ein numerisches Array mit Werten aus der angegebenen Spalte zurück. $column gibt an, welche Spalte als Ganzzahl zurückgegeben werden soll. Standardmäßig ist dies 0, die erste Spalte.
  • $wpdb->get_var($sql, $column, $row) - Dies führt die Abfrage aus und gibt einen bestimmten Wert zurück. $row und $column sind wie oben angegeben und geben an, welchen Wert zurückgegeben werden soll. Zum Beispiel,

Es ist wichtig zu wissen, dass diese Methoden nur Wrapper sind, um eine SQL-Abfrage auszuführen und das Ergebnis zu formatieren. Sie bereinigen die Abfrage nicht. Sie sollten sie also nicht alleine verwenden, wenn die Abfrage "unbekannte" Daten enthält.


Zusammenfassung

Wir haben in diesem Tutorial eine Menge behandelt - und die Datenbereinigung ist ein wichtiges Thema. Im nächsten Artikel werden wir es auf unser Plug-In anwenden. Wir werden einen Satz von Wrapper-Funktionen entwickeln (ähnlich Funktionen wie wp_insert_post(), wp_delete_post() usw.), die eine Abstraktionsebene zwischen unserem Plug-In und der Datenbank hinzufügen.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.