Dateisystem - Sicherheit
Inhaltsverzeichnis
PHP ist von den in den meisten Serversystemen implementierten
Sicherheitseinstellungen hinsichtlich der Berechtigungen auf Datei-
und Verzeichnisebene abhängig. Dies verleiht Ihnen Kontrolle darüber,
welche Dateien in dem Dateisystem gelesen werden dürfen. Vorsicht ist
bei weltweit lesbaren Dateien geboten um sicherzustellen, dass diese
sicher von allen Usern mit Zugriff auf dieses Dateisystem (nur) gelesen
werden können.
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 User zum Ausdruck
bringt, dass gerne eine Datei in seinem Heimatverzeichnis löschen
möchte. Dies geht von einer Situation aus, in der ein PHP Web-Interface
regelmäßig zum Dateimanagement verwendet wird, und der Apache User
ist auch berechtigt, 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!";
?>
Da der Benutzer- und Dateiname über ein Benutzerformular bereitgestellt
werden kann jeder jemand anderes Benutzer- und Dateinamen übertragen und
so Dateien ohne über die entsprechnde Erlaubnis zu verfügen.
In diesem Fall empfiehlt es sich, eine andere
Form der Authentifizierung zu verwenden. Stellen Sie sich vor was
passieren würde, wenn die übertragenen Variablen "../etc/" und
"passwd" beinhalten würden. Der Code würde dann effektiv lesen:
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 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!";?>
Es gibt zwei wichtige Kriterien die Sie beachten sollten, um diese
Dinge zu vermeiden:
-
Erteilen Sie dem PHP Web-user (Binärdatei) nur eingeschränkte Rechte.
-
Prüfen Sie alle übertragenen Variablen.
Hier ist ein verbessertes Skript:
Beispiel #3 Etwas sicherere Prüfung des Dateinamens
<?php
// löscht eine Datei von der Festplatte, auf die
// der PHP user 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);
?>
Auch dies nicht völlig makellos. Wenn Ihr Authentifizierungssystem
Benutzern erlauben sollte, deren eigene Logins zu kreieren, und ein
Benutzer wählt den Login "../etc", ist das System wieder aufgedeckt.
Aus diesem Grund ziehen Sie es vielleicht vor, einen besseren Check
zu schreiben:
Beispiel #4 Sicherere Dateinamensprüfung
<?php
$username = $_SERVER['REMOTE_USER']; // Nutzung des 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 mit der
Sie sich befassen sollten, inklusive Einträge für Geräte (/dev/ oder
com1), Konfigurationsdateien (/etc/ Dateien und die .ini Dateien), gut
bekannte Verzeichnisse (/home/, My Documents), etc. Aus diesem Grund
ist es gewöhnlich einfacher eine Vorgangsweise einzuführen, bei der
außer den von Ihnen explizit erlaubten Dingen alles verboten ist.