Was man bei Eingabe-Prüfung falsch machen kann (u.a. SQL-Injection)

Ein kurzer Ausflug in die PHP-Programmierung brachte mich heute auf einen Fehler, der mir hoffentlich früher auch nicht unentdeckt blieb. Aufgabe war es, die Einträge des Gästebuchs eines Kunden auf verschiedene Seiten auszugeben -- je nach Anzahl der Einträge pro Seite. Der englische Fachausdruck dafür ist Pagination.

Die Seitenzahl (bzw. das daraus errechnete Offset) wird über eine GET-Variable 'page' übergeben. Funktionierte alles wunderbar und schlußendlich wollte ich noch eine zusätzliche Prüfung auf schadhaften Code (SQL-Injection etc.) einbauen. Dieser Code soll prüfen, ob sich in $_GET['page'] auch wirklich nur Ziffern finden.

<?php
if(isset($_GET['page']) && !preg_match("/[0-9]+/", $_GET['page']))
    die("Die Seitenzahl darf nur aus Ziffern bestehen.");
?>

Das funktioniert prinzipiell auch wie es sollte, bis ich einige Real-Life-Tests durchführte. Zwar stirbt das Script bei Werten wie '?page=ABC' wie gewünscht ab, sobald sich aber irgendwo eine Ziffer befindet -- '?page=AB123' -- nicht.

Der Fehler liegt im Detail, der richtige Ausdruck lautet nicht "/[0-9]+/" sondern "/^[0-9]+$/". Das Dach- und Dollar-Symbol stellt sicher, dass sich von Anfang bis Ende auch wirklich nur Ziffern befinden dürfen.

So funktioniert alles wie es sein soll und es gilt wieder einmal: Traue keiner Variable, die du nicht selbst definierst. Darüber hinaus dürfen die Funktionen addslashes, is_numeric respektive is_int und mysql_escape_string nicht unerwähnt bleiben.



↑ to the elevators

© 2001—2012 Martin Mahner. This is an I ♥ Django Project.

Admin | Generated: Tue, 7 Feb 2012 10:27:27 +0100