Die serverseitig interpretierte Skriptsprache PHP ist laut dem Tiobe Index auf Platz 5 der beliebtesten Programmiersprachen weltweit (Stand: Oktober 2013). Die einfache Syntax von PHP halten die Sprache seit 18 Jahren auf Erfolgskurs. Die Popularität und der rege Einsatz von PHP führen jedoch dazu, dass böswillige Menschen versuchen, Sicherheitslücken in PHP-Anwendungen auszunutzen.
Um keine Angriffspunkte in der eigenen PHP-Anwendung zu bieten, sollte man den direkten Zugriff auf superglobale Arrays (engl. Superglobals) vermeiden.
Erklärung:
Superglobals sind vordefinierte Variablen, die in allen Gültigkeitsbereichen (sog. Scopes) eines PHP-Skripts verfügbar sind. Zu den Superglobalen gehören unter anderem die häufig eingesetzten Variablen: $_SERVER, $_GET und $_POST.
Für PHP-Anfänger wird das Auslesen eines GET-Parameters oftmals so vorgestellt:
<?php $text = $_GET['text']; echo $text; ?> |
Liefert man dem PHP-Skript keinen GET-Parameter, so kommt es zum Hinweis: Undefined index: text
. Um dieses Problem zu vermeiden, kann bereits vor dem Zugriff auf den GET-Parameter text
geprüft werden, ob dieser Parameter überhaupt existiert:
<?php if (isset($_GET['text'])) { $text = $_GET['text']; echo $text; } ?> |
Es besteht aber weiterhin das Problem, dass alle Eingaben des GET-Parameters interpretiert werden. Ruft man das Script beispielsweise mit ?text=<b>HTML</b>
auf, so wird das HTML-Tag <b>
interpretiert und der Text „HTML“ fett auf die eigene Webseite geschrieben.
Um die Interpretation von allen möglichen Parameter-Werten zu verhindern, wird empfohlen, nicht direkt auf die Superglobalen zuzugreifen sondern die in PHP 5.2 eingeführte Funktion filter_input zu verwenden. Dadurch erspart man sich gleichzeitig die Prüfung auf die Existenz des GET-Parameters:
1 2 3 4 | <?php $text = filter_input(INPUT_GET, 'text', FILTER_SANITIZE_FULL_SPECIAL_CHARS); echo $text; ?> |
Die Funktion „filter_input“ akzeptiert verschiedene Filterarten zum Säubern von Eingaben (siehe Sanitize Filters). Der Filter „FILTER_SANITIZE_FULL_SPECIAL_CHARS“ sorgt in unserem Beispiel dafür, dass anstelle eines fettgeschriebenem „HTML“ nur noch ein „<b>HTML</b>“ angezeigt wird. Die Umwandlung der Sonderzeichen entspricht dem Verhalten der Funktion htmlspecialchars.
Möchte man, dass HTML-Tags aus dem Parameterwert vollständig entfernt werden, so kann man einen anderen Filter verwenden:
1 2 3 4 | <?php $text = filter_input(INPUT_GET, 'text', FILTER_SANITIZE_STRING); echo $text; ?> |
Übrig bleibt jetzt nur noch die Eingabe „HTML“. Dadurch, dass jetzt HTML-Tags aus den Parameterwerten entfernt werden, kann niemand mehr absichtlich oder versehentlich HTML-Code an das PHP-Skript senden, um beispielsweise das Layout der Seite zu verändern.
Um diese kleine Übung abzuschließen, empfehle ich noch das Entfernen des schließenden PHP-Tags. NetBeans 7.4 warnt sogar bei der Verwendung des schließenden Trennzeichens:
Fertiges Code-Beispiel:
1 2 3 4 | <?php $text = filter_input(INPUT_GET, 'text', FILTER_SANITIZE_STRING); echo $text; |
Hi,ich habe eine Frage zu Deinem Text:
Um diese kleine Übung abzuschließen, empfehle ich noch das Entfernen des schließenden PHP-Tags. NetBeans 7.4 warnt sogar bei der Verwendung des schließenden Trennzeichens:
Warum sollte man das PHP Script nicht mehr schließen ?, welche Vorteile hätte das ?
lg gomez
Für diesen Fall ändert das abschliessende Tag nichts.
Es verhindert aber die u.U. zu frühe Übertragung von Content an den Client. Alles nach dem Tag ist Content – und sei es nur eine Leerstelle oder Zeilenumbruch.
Beispiel: Erstelle ein Script mit einer Klasse, welche irgendwas machen soll und füge nach dem Abschlusstag eine Leerzeile ein. Erstelle ein aufrufbares Script welche die Klasse einbindet. Versuche nach der Einbindung die HTTP Header zu ändern – z.B. um ein Download zu realisiern. Sofern Output-Caching nicht aktiviert ist, wird PHP beim Aufruf sich beschweren, das die Header nicht mehr geändert werden können, da bereits Content (Die Leerzeile) übertragen wurde.
Vielen Dank für die Erklärung! Ich sollte diesen Fakt im Artikel aufnehmen.
Ich finde es komisch, dass netbeans trotzdem eine warning anzeigt, wenn man z.B. isset benutzt. Dabei wird genau das im Kommentar zur Fehlermeldung (conditions with is_*()) vorgeschlagen. Außerdem funktionieren Filter bei Cookies nicht.