PHP ist hinsichtlich der Berechtigungen auf Datei- und Verzeichnisebene von den in den meisten Serversystemen implementierten Sicherheitseinstellungen abhängig. Dies verleiht Ihnen Kontrolle darüber, welche Dateien im Dateisystem gelesen werden dürfen. Es sollte sichergestellt werden, dass alle öffentlich zugänglichen Dateien von allen Benutzern, die Zugang zu diesem Dateisystem haben, gelesen werden können, ohne die Sicherheit zu gefährden.
Da PHP entwickelt wurde, um Zugriffe auf das Dateisystem auf Benutzebene zu erlauben, ist es natürlich auch möglich, ein PHP-Skript zu schreiben, dass Ihnen erlaubt, Systemdateien wie /etc/passwd zu lesen, Ethernetverbindungen zu modifizieren, enorme Druckaufträge zu senden etc. Dies hat offensichtliche Implikationen, indem Sie sicherstellen müssen, dass alle von Ihnen zu lesenden bzw. zu schreibenden Dateien auch die richtigen sind.
Stellen Sie sich folgendes Skript vor, in dem ein Benutzer zum Ausdruck bringt, dass er eine Datei in seinem Heimatverzeichnis löschen möchte. Es wird davon ausgegangen, dass ein PHP-Webinterface regelmäßig für das Dateimanagement verwendet wird und dass der Apache-Benutzer berechtigt ist, in seinem Heimatverzeichnis Dateien zu löschen.
Beispiel #1 Schlechte Variablenprüfung führt zu....
<?php
// Löschen einer Datei aus dem Heimatverzeichnis des Users
$username = $_POST['user_submitted_name'];
$userfile = $_POST['user_submitted_filename'];
$homedir = "/home/$username";
unlink("$homedir/$userfile");
echo "Die Datei wurde gelöscht!";
?>
"../etc/"
und "passwd"
beinhalten würden.
Der Code würde dann folgendermaßen aussehen:
Beispiel #2 ... Ein Angriff auf das Dateisystem
<?php
// Löscht eine Datei irgendwo auf der Festplatte, wo der Benutzer
// die nötigen Rechte besitzt. Wenn PHP root-Zugriff hat:
$username = $_POST['user_submitted_name']; // "../etc"
$userfile = $_POST['user_submitted_filename']; // "passwd"
$homedir = "/home/$username"; // "/home/../etc"
unlink("$homedir/$userfile"); // "/home/../etc/passwd"
echo "Die Datei wurde gelöscht!";?>
?>
Beispiel #3 Etwas sicherere Prüfung des Dateinamens
<?php
// Löscht eine Datei von der Festplatte, auf die
// der PHP-Benutzer Zugriff hat.
$username = $_SERVER['REMOTE_USER']; // using an authentication mechanism
$userfile = basename($_POST['user_submitted_filename']);
$homedir = "/home/$username";
$filepath = "$homedir/$userfile";
if (file_exists($filepath) && unlink($filepath)) {
$logstring = "$filepath gelöscht\n";
} else {
$logstring = "$filepath konnte nicht gelöscht\n";
}
$fp = fopen("/home/logging/filedelete.log", "a");
fwrite($fp, $logstring);
fclose($fp);
echo htmlentities($logstring, ENT_QUOTES);
?>
"../etc/"
, ist das System
erneut angreifbar. Aus diesem Grund sollten Sie eventuell eine speziellere
Überprüfung durchführen
Beispiel #4 Sicherere Dateinamensprüfung
<?php
$username = $_SERVER['REMOTE_USER']; // Nutzung eines Authentifikationsmechanismus
$userfile = $_POST['user_submitted_filename'];
$homedir = "/home/$username";
$filepath = "$homedir/$userfile";
if (!ctype_alnum($username) || !preg_match('/^(?:[a-z0-9_-]|\.(?!\.))+$/iD', $userfile)) {
die("Ungültiger Benutzer- oder Dateiname");
}
// etc.
?>
Abhängig vom Betriebssystem gibt es eine große Anzahl Dateien, auf die Sie
achten sollten, inklusive Einträge für Geräte (/dev/
oder com1), Konfigurationsdateien (die Dateien in
/etc/ und die .ini
-Dateien),
allgemein bekannte Verzeichnisse (/home/,
My Documents) etc. Aus diesem Grund ist es für
gewöhnlich einfacher, eine Richtlinie zu erstellen, in der alles verboten
ist, was Sie nicht ausdrücklich erlauben.