Sicheres Programmieren mit PHP (2)
Überprüfung von Variablenwerten
Vertrauen Sie keinen Werten, die über Browsereingaben, den URL oder Cookies in das PHP-Skript gelangen!
Alle externen Parameter, selbst wenn sie aus versteckten Feldern
<input type="hidden" ... /> oder Auswahlmenüs kommen, müssen einer
Plausibilitätsprüfung unterworfen werden,
bevor sie im Programm verwendet werden.
Das betrifft alle Werte der Felder
_GET, _POST, _COOKIE, sowie
_REQUEST.
Dazu bietet PHP eine Vielzahl von Möglichkeiten.
# Wert aus Formular-Eingabefeld "zahl" muss numerisch sein:
$zahl = (is_numeric($_REQUEST['zahl']) ? $_REQUEST['zahl'] : 0);
Weitere Beispiele finden Sie in:
http://www.php-faq.de/q/q-security-variablen.html
Vermeiden Sie beim Zugriff auf Dateien Variablen, insbesondere dann,
wenn sie aus Bestandteilen des URLs oder Cookies bestehen.
Betrachten Sie das folgende schlechte Beispiel:
# datei ist Bestandteil des URLs
include($_REQUEST['datei']);
Unerwünschte Effekte treten ein, wenn der URL so aussieht:
.../script.php?datei=/etc/passwd
Wie kann man es besser machen?
Wenn eine Variable nur einen Dateinamen im gleichen Verzeichnis wie das
PHP-Skript enthalten darf (aber keinen Pfadnamen), dann reicht
häufig die Püfung auf
/ im Dateinamen:
if (isset($_REQUEST['datei']) && !ereg('/', $_REQUEST['datei'])) {
# datei ist gesetzt und enthält kein /
include($_REQUEST['datei']);
} else {
# Fehler ...
}
Wenn Variablen nur Werte aus einer vorgegebenen Menge annehmen dürfen (z.B.
aus einem
<select> Menü), sollte dies abgeprüft werden:
# nur diese drei Werte sind möglich:
$seiten = array('index.html' => 1, 'kontakt.html' => 1,
'lehre.html' => 1);
if (isset($_REQUEST['datei']) && isset($seiten[$_REQUEST['datei']])) {
# datei ist gesetzt und erlaubt
include($_REQUEST['datei']);
} else {
# Fehler ...
}
Gründlich prüfen sollten Sie unbedingt auch die Parameter für Funktionen
zum Starten von externen Programmen, wie
system(), exec(), passthru(), popen() und den
`Backtick` Operator.
Zum Maskieren von Shell-Metazeichen (z.B. Stern oder Semikolon, die mglw.
unerwünschte Effekte haben können) eignet sich die Funktion
escapeshellarg().
if (isset($_REQUEST['datei']) && !ereg('/', $_REQUEST['datei'])) {
# datei ist gesetzt und enthält kein /
# evtl. Shell-Metazeichen maskieren:
$datei = escapeshellarg($_REQUEST['datei']);
system("/bin/ls -l $datei");
} else {
# Fehler ...
}
Weitere Hinweise:
http://www.php-faq.de/ch/ch-security.html