Forum: PC-Programmierung [PHP] Injection verhindern


von Niklas S. (niklas_s)


Lesenswert?

Ich habe eine PHP-Datei, der ich 'datei' übergebe.

Also index.php?datei=test.txt

In der PHP-Datei steht zur Zeit

if(!empty($_GET['datei']))
{
  unlink('unterverzeichnis/'.$_GET['datei']);
  echo 'unterverzeichnis/'.$_GET['datei'].' gelöscht.';
}

Das könnte man so manipulieren, daß mein gesamter Serverdatenbestand 
gelöscht wird.

Wie kann ich bestimmen, daß nur Dateien im Verzeichnis 
'unterverzeichnis' gelöscht werden können?

: Verschoben durch User
von Peter II (Gast)


Lesenswert?

du musst prüfen das im Dateinamen keine "/" enthalten ist. Also kein 
Zeichen mit dem mit den Path ändern kann.

von Patrick-Oliver S. (patrick-oliver)


Lesenswert?

Hallo,

per Mustervergleich kannst du das Format der übergebenen Zeichenkette 
prüfen.
Schaue dir hierzu bitte http://de3.php.net/preg_match an.
Per stat (http://de3.php.net/manual/de/function.stat.php) kann man sich 
noch Eigenschaften der zu löschenden Datei anschauen, um ggf. nur 
Dateien zu löschen, dir einem bestimmten Benutzer gehören.
Per file_exists (http://de3.php.net/file_exists) kann dann noch geprüft 
werden, ob die angeforderte Datei überhaupt existiert.

Grundsätzlich würde ich keiner Benutzereingabe trauen und den 
vollständigen Pfad der zu löschenden Datei von Hand zusammen bauen.

Gruß,
Patrick-Oliver

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Wenn es nur ein bestimmtest Verzeichnis betrifft:
1) dem PHP Prozess nur Schreibrechte  in diesem Verzeichnis einräumen
2) Alle Pfadangaben vorher entfernen: 
http://php.net/manual/de/function.basename.php
1
if(!empty($_GET['datei'])) {
2
  $file = basename($_GET['datei']);
3
  unlink('unterverzeichnis/'.$file);
4
  echo 'unterverzeichnis/'.$file.' gelöscht.';
5
}

von Chris (Gast)


Lesenswert?

Ich würde auch auf Leerzeichen, Backlash sowie ".." prüfen und die 
ausschließen.

von Ben _. (burning_silicon)


Lesenswert?

Aufpassen, daß man die blockierten Zeichen nicht per Multibyte-Code oder 
ähnlichen Zeugs codieren kann, so daß sie die Kontrollen unterlaufen.

Ich würd grundsätzlich alles rausschmeißen was keine Buchstaben/Ziffern 
sind bzw. irgendwo vermerken welche Dateien überhaupt gelöscht werden 
dürfen. Dann kann auch keiner mit "kill.php?datei=*.*" rumspielen.

von Peter II (Gast)


Lesenswert?

Das sicherste ist, den Dateiname überhaupt nicht zu verwenden. Meist 
werde ja noch Daten in der Datenbank ablegt. Dann kann man jeder Datei 
eine ID geben und dann wird sie unter diesem namen gespeichert. Welcher 
name dann in der Datenbank steht ist egal.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Peter II schrieb:
> Meist werde ja noch Daten in der Datenbank ablegt
Dann sollte man sich aber gegen SQL Injection schützen ;)

von Oliver R. (sourcebox)


Lesenswert?

Den gesamten Server wirst du wohl auf diese Weise nicht löschen können, 
da PHP nicht die entsprechenden Zugriffsrechte haben dürfte. Nichts 
desto trotz ist es natürlich sinnvoll derartige Zugriffe nicht 
zuzulassen.

Falls du trotzdem auf derartige Weise vorgehen möchtest, empfiehlt es 
sich, über die Funktion realpath() (siehe 
http://de2.php.net/manual/de/function.realpath.php) den resultierenden 
Dateinamen zu ermitteln und dann zu schauen, ob sich dieser innerhalb 
eines bestimmten Verzeichnisses befindet. Mit realpath() umgehst du die 
Möglichkeit, dass man sich per Directory Traversal (../../ etc.) 
durchhangeln kann.

von Robert R. (auza)


Lesenswert?

Auch eine Einschränkung der Dateiendungen wäre denkbar, wenn Du z.B. nur 
*.txt Dateien hast. Einfach die Dateiendung im Script hinzufügen und den 
Dateinammen per Regex auf erlaubte Zeichen prüfen:
1
$Dateiname = "FEHLER";
2
if ((preg_match('/^[a-zA-Z0-9-_]{0,16}$/', $_GET['datei']))) { 
3
   $Dateiname = $_GET['datei'].".txt";
4
}
5
6
if ($Dateiname != "FEHLER") {
7
   # HIER WIE VON Läubi BESCHRIEBEN DIE DATEI LÖSCHEN
8
} else { 
9
   # HIER EINTRAGE, WAS PASSIERT, WENN DIE DATEI NICHT DEM FILTER ENTSPRICHT
10
}

Im Beispiel dürft der Dateiname aus bis zu 16 Zeichen bestehen und alle 
Zeichen von a-z, A-Z, 0-9 und noch Bindestriche und Unterstriche 
enthalten.
Sonderzeichen wie äöüß sind hier ausgenommen.

Der Code ist nicht getestet, sondern nur eben hingeschrieben. Es sollte 
aber hervorgehen, wie es funktionieren kann.

Du könntest auch noch mit Prüfsummen arbeiten, denn Du wirst ja sicher 
vorher irgendwo auswählen können, welche Datei gelöscht werden soll. 
Dann erzeugst Du einen Hash mit dem Dateinamen und einem "geheimen" 
Schlüssel.
1
$Hash = md5($Dateiname."GeheimerString");
Dass kannst Du dann vom Script vor dem löschen prüfen.

Am besten ist jedoch, so wenig Informationen wie möglich nach "draußen" 
zu geben. Eine Datenbank die die Dateien referenziert ist nach wie vor 
die beste Lösung. Dort aber auch nicht die ID direkt an das Script 
übergeben, sondern einen Hashwert. :)

von Christian D. (christian_d) Flattr this


Lesenswert?

Chris schrieb:
> Ich würde auch auf Leerzeichen, Backlash sowie ".." prüfen und die
> ausschließen.

und ich würde dringend empfehlen sowas nur per whitelist und nicht 
blacklist zu machen sonst findet man immer ein Hintertürchen!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.