HOWTO · PHP

Eingaben in PHP säubern

Im heutigen Beitrag erfahren Sie, wie Sie die Eingabedaten in PHP bereinigen, bevor Sie sie an die Datenbank übergeben.

Auf dieser Seite

Es gibt keinen universellen Schritt, der jeden nicht vertrauenswürdigen Wert sicher macht. Entscheiden Sie, wofür der Wert steht, prüfen Sie ihn anhand dieser Anforderung, normalisieren Sie ihn nur dann, wenn die Anwendung dafür eine klare Regel vorgibt, kodieren Sie ihn für den Kontext, in dem er angezeigt wird, und verwenden Sie beim Übermitteln an eine Datenbank parametrisierte Abfragen. Diese Maßnahmen lösen unterschiedliche Probleme: Bei der Validierung wird ein Wert angenommen oder abgelehnt, bei der Bereinigung wird er verändert, und die Ausgabekodierung stellt Zeichen in einem bestimmten Kontext sicher dar. Keine dieser Maßnahmen allein garantiert die Datenintegrität oder schützt jede Verwendung eines Werts.

Was die Bereinigung von PHP-Eingaben leisten kann und was nicht

Die Verarbeitung von Eingaben beginnt mit den Anforderungen an das jeweilige Feld. Für ein Alter, eine E-Mail-Adresse, einen Anzeigenamen und einen Suchbegriff gelten unterschiedliche zulässige Formate. Bei der Validierung wird geprüft, ob ein Wert diese Anforderungen erfüllt; bei der Normalisierung wird er gezielt und nach einer dokumentierten Regel umgewandelt, etwa indem umgebende Leerzeichen entfernt werden. Eine bereinigende Funktion kann Zeichen entfernen oder verändern. Dadurch kann sich die Eingabe unbemerkt ändern, und das Ergebnis ist nicht automatisch für jede weitere Verwendung geeignet.

Bewahren Sie den ursprünglichen Wert getrennt von normalisierten oder kodierten Darstellungen auf, wenn die Anwendung ihn weiterhin benötigt. Entfernen Sie keine Zeichen allein deshalb, weil sie ungewöhnlich wirken: Namen und andere legitime Texte können Satzzeichen oder Nicht-ASCII-Zeichen enthalten. Wählen Sie die passende Verarbeitung auch am jeweiligen Verwendungsort. Für HTML-Ausgaben ist HTML-Kodierung erforderlich, für SQL-Werte sind es Abfrageparameter. Diese Schutzmaßnahmen sind nicht austauschbar.

HTML kodieren, wenn Sie Benutzereingaben anzeigen

Kodieren Sie Text, wenn Sie ihn in einen HTML-Textknoten oder ein in Anführungszeichen gesetztes Attribut einfügen. Bei gewöhnlichen HTML-Ausgaben wandelt htmlspecialchars() Zeichen mit besonderer Bedeutung in HTML um, darunter kaufmännische Und-Zeichen und spitze Klammern sowie mit den passenden Flags auch Anführungszeichen. htmlentities() kodiert außerdem Zeichen, für die benannte HTML-Entitäten existieren. Keine der beiden Funktionen ist ein allgemeiner HTML-Sanitizer: Die Kodierung eines Werts für einen Textknoten macht ihn nicht sicher für JavaScript, CSS, eine URL oder rohes HTML-Markup. Verwenden Sie die Kodierung und Regeln, die zum konkreten Ausgabekontext passen.

Dieses eigenständige Beispiel kodiert einen Namen für einen HTML-Textknoten:

Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.

<?php
$name = 'Ada & Sam';
echo htmlspecialchars($name, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'), PHP_EOL;
Ada &amp; Sam

Das unveränderte Beispiel gibt Ada & Sam aus; dieser Name und die Ausgabe bleiben auf Englisch. Die bereitgestellten Laufzeitnachweise bestätigen die Ausgabe. Es handelt sich um eine Zeichenkette für einen HTML-Textkontext, nicht um einen Wert, der für SQL oder JavaScript wiederverwendet werden sollte.

Eingaben mit filter_var() validieren und normalisieren

filter_var() führt eine ausgewählte Validierungs- oder Filteroperation aus; die Funktion ist kein HTML-Sanitizer. Beispielsweise gibt filter_var($email, FILTER_VALIDATE_EMAIL) die akzeptierte E-Mail-Adresse zurück oder false, wenn sie dem Filter nicht entspricht. Mit filter_var($count, FILTER_VALIDATE_INT) lässt sich eine Ganzzahl validieren. Bei Bedarf kann die Anwendung dafür Optionen festlegen, etwa einen bestimmten Wertebereich. Prüfen Sie den Rückgabewert ausdrücklich, denn false bedeutet, dass die Validierung fehlgeschlagen ist.

Filter zur Bereinigung können Eingaben verändern, statt deren Gültigkeit nachzuweisen. FILTER_SANITIZE_EMAIL entfernt beispielsweise Zeichen, die dieser Filter nicht zulässt. Damit wird weder bestätigt, dass die resultierende Adresse einer bestimmten Person gehört, noch dass sie E-Mails empfangen kann. Wenn die Anwendung Eingaben normalisieren soll, legen Sie eine Regel dafür fest und validieren Sie anschließend das Ergebnis. Verlassen Sie sich nicht auf FILTER_SANITIZE_STRING als allgemeine Lösung: Das Entfernen von Markup sorgt weder für eine zum Ausgabekontext passende Kodierung noch macht es beliebige Inhalte sicher.

Vorbereitete Anweisungen für SQL verwenden

Verwenden Sie parametrisierte Abfragen, damit die SQL-Syntax von den übermittelten Werten getrennt bleibt. Bereiten Sie mit PDO eine Abfrage mit einem Platzhalter vor und übergeben Sie den Wert beim Ausführen separat. Ein mögliches Muster ist $statement = $pdo->prepare('SELECT id, email FROM Users WHERE lastname = :lastname');, gefolgt von $statement->execute(['lastname' => $lastname]);. Dies ist ein beispielhafter Ausschnitt: $pdo muss bereits mit der vorgesehenen Datenbank verbunden sein. Der Datenbankdienst und das Schema sind nicht Teil dieses Beispiels.

PDO bereinigt keine beliebigen Eingaben. Bei Werten in der Abfrage schützt die Parameterbindung vor SQL-Injection; sie prüft jedoch nicht, ob ein Wert für die Anwendung sinnvoll ist. Validieren Sie Werte anhand der Regeln für das jeweilige Feld. Verwenden Sie für Bezeichner wie Tabellen- oder Spaltennamen eine separate Strategie zum Erstellen der Abfrage, da sich solche Bezeichner im Allgemeinen nicht als Wertparameter übergeben lassen. Auch MySQLi unterstützt vorbereitete Anweisungen; verwenden Sie bei dieser Schnittstelle deren API zur Parameterbindung.

Profilfelder entsprechend ihrem erwarteten Typ verarbeiten

Wenden Sie für jedes Profilfeld eine eigene Regel an. Validieren Sie eine E-Mail-Adresse und bestätigen Sie bei Bedarf die Inhaberschaft über einen Anwendungsablauf. Entfernen Sie Leerzeichen am Anfang und Ende eines Anzeigenamens nur, wenn dies der vorgesehenen Richtlinie entspricht. Prüfen Sie eine Postleitzahl anhand der relevanten Region, statt ein weltweit einheitliches Format vorauszusetzen. Parsen Sie numerische Felder und prüfen Sie den zulässigen Wertebereich, bevor Sie sie verwenden. Lassen Sie legitime Satzzeichen und Unicode-Zeichen zu, sofern das jeweilige Feld sie erlaubt.

Wenn Sie gespeicherte Profilwerte auf einer Seite anzeigen, kodieren Sie sie zum Ausgabezeitpunkt passend zum konkreten HTML-Kontext – auch dann, wenn sie bei der Übermittlung validiert wurden. Verwenden Sie bei Profilabfragen vorbereitete Anweisungen. Wenn Validierung, Normalisierung, Datenbank-Parameterbindung und Ausgabekodierung getrennte Entscheidungen bleiben, lässt sich die Verarbeitung leichter nachvollziehen und keine einzelne Umwandlung wird fälschlich als universeller Schutz verstanden.