cyberscout: Dateiupload

Hallo nocheinmal
Ich beschäftige mich seit heute mittag mit Dateiupload. Die FTP-Lösung hat leider nach wie vor nicht funktioniert (trotz wahsaga`s Hilfe) und somit bin ich auf die Funktion move_uploaded_file() gekommen. (upload geht über ein Formular)

Der komplette Befehl, den ich verwende:

$uploaddir = "/";
$uploadfile = $uploaddir . $_FILES['pfad_grafik']['name'];

move_uploaded_file($_FILES['pfad_grafik']['tmp_name'], $uploadfile);

Dazu einige Fragen:

  • von wo aus geht der Pfad, der in diesem Beispiel als $uploaddir angegeben wurde? Von /tmp, oder / oder vom Speicherort der php-Datei?
  • Wenn ich diese Zeile online ausführen lasse erhalte ich immer folgende Fehlermeldungen:

Warning: move_uploaded_file(../public_html/Beispiel.jpg): failed to open stream: Permission denied in /home/cscout/public_html/benutzerverwaltung/bilder.php on line 140

Warning: move_uploaded_file(): Unable to move '/tmp/phpAAboG7' to '../public_html/Beispiel.jpg' in /home/cscout/public_html/benutzerverwaltung/bilder.php on line 140

Nun vermute ich, dass der aktuelle Benutzer keine Schreibrechte hat. Wie kann ich diese setzen, muss ich da so oder so auf FTP zurückgreifen?

  • Was gibt es sonst für Möglichkeiten, Bilder upzuloaden?

Vielen Dank für eure Hilfe.

Gruss
cyberscout

  1. Halihallo cyberscout

    • von wo aus geht der Pfad, der in diesem Beispiel als $uploaddir angegeben wurde? Von /tmp, oder / oder vom Speicherort der php-Datei?

    http://ch2.php.net/manual/de/function.move-uploaded-file.php
    "Ist die Datei gültig, wird sie zum in destination bezeichneten
    Dateinamen verschoben."
    Es wird von "nichts ausgegangen". Es ist eben einfach ein Dateiname,
    wie z.B. './upload.txt' (wo das Script liegt) oder '/upload.txt' (FS-
    Root).

    • Wenn ich diese Zeile online ausführen lasse erhalte ich immer folgende Fehlermeldungen:

    Benötigt werden Leserechte im entsprechenden tmp-Ordner und
    Schreibrechte im Zielordner. Zudem musst du alle Verzeichnisse
    öffnen dürfen (Ausführungsberechtigung).
    Bei Safe Mode muss zusätzlich die selbe UID vorliegen, s. Doku.

    Nun vermute ich, dass der aktuelle Benutzer keine Schreibrechte hat. Wie kann ich diese setzen, muss ich da so oder so auf FTP zurückgreifen?

    Du musst nicht zwingend auf FTP zurückgreifen, solltest dir aber mal
    alles zu Safe Mode http://ch2.php.net/manual/de/features.safe-mode.php
    durchlesen und die vorhandene PHP-Konfiguration und Verzeichnis/Datei
    Permissions ansehen.

    • Was gibt es sonst für Möglichkeiten, Bilder upzuloaden?

    Was gefällt dir an http://ch2.php.net/manual/de/features.file-upload.php
    nicht?

    Viele Grüsse

    Philipp

  2. Moin,

    $uploaddir = "/";
    $uploadfile = $uploaddir . $_FILES['pfad_grafik']['name'];

    move_uploaded_file($_FILES['pfad_grafik']['tmp_name'], $uploadfile);

    Falls das jemand im Archiv lesen sollte: Auf gar keinen Fall nachmachen. Das ist eine Sicherheitslücke wie sie im Lehrbuch steht. Nie, nie, nie solltet ihr sowas in ein Skript schreiben welches ihr tatsächlich im Internet zugreifbar macht. Auch nichts was so ähnlich aussieht, solange ihr nicht genau wisst was es tut.

    Der Grund ist folgender: $_FILES[...]['name'] enthält einen Wert der vom Browser des Benutzers kommt und daher immer als böse und feindlich zu betrachten ist. Da kann der Client reinschreiben was er will, also zum Beispiel auch Sachen die einen "/" enthalten.

    In diesem Fall wird das ganze noch offensichtlich schlimmer gemacht dadurch dass du einen "/" davorschreibst, man braucht also nur noch "etc/passwd" in den Namen zu schreiben und der Code würde dann versuchen die hochgeladene Datei nach /etc/passwd zu tun. (Dass das nicht funktionieren wird tut erstmal nichts zu Sache, es gibt noch viele andere Möglichkeiten auf diese Weise das System zu übernehmen.)

    ACHTUNG und jetzt das wichtige: Wenn $uploaddir statt dessen auf "/was/weiss/ich/wo" gesetzt worden wäre, wäre das kein Stückchen besser (auch wenn das vielleicht nicht offensichtlich ist), denn der Name könnte ja auch "/../../../../../../etc/passwd" lauten, was am Ende wieder auf das gleiche hinausläuft.

    Deswegen bei allen Sachen bei denen eine Eingabe vom User in einen Dateinamen involviert ist, immer Vorkehrungen dagegen treffen. Manche Leute prüfen ob ein "/" (bzw. \ unter Windows) oder ".." im String vorkommt und lehnen ihn dann ab. Das ist im Prinzip ok, meiner Meinung nach aber zu unschön (und hat ein paar Schwächen). Stattdessen schlage ich vor basename() zu verwenden um sicherzugehen, dass der Name wirklich nur ein Dateiname ist und keine Pfadelemente enthält. Und natürlich muß man ein Verzeichnis voranstellen.

    Der obige Code sieht also besser so aus:

    $uploaddir = "/irgendwo/wo/es/schön/ist/";
    $uploadfile = $uploaddir . basename($_FILES['pfad_grafik']['name']);

    move_uploaded_file($_FILES['pfad_grafik']['tmp_name'], $uploadfile);

    Hier fehlen selbstverständlich noch andere wichtige Elemente; man sollte zum Beispiel den Dateityp und die Endung prüfen ob sie wirklich akzeptabel ist (und bitte, bitte, akzeptiert keine PHP- oder ähnliche Dateien) und bestimmt auch auf die Größe schauen.

    --
    Henryk Plötz
    Grüße aus Berlin
    ~~~~~~~~ Un-CDs, nein danke! http://www.heise.de/ct/cd-register/ ~~~~~~~~
    ~~ Help Microsoft fight software piracy: Give Linux to a friend today! ~~
    1. Hallo

      @Henryk
      Vielen Dank für die Hinweise zur Sicherheit, dann werde ich in meinem Script basename() anwenden.

      Das Prüfen von Dateiendungen und Typ kommt schon noch, aber zuerst sollte die Grundfunktion laufen.

      Überigens: Help Microsoft fight software piracy: Give Linux to a friend today!: Coole Signiatur!

      @Philipp
      Vielen Dank für deine Antwort. Dumme Frage: Wie ändere ich die Schreibrechte? Es geht um ein Forum, bei dem jeder Benutzer in seiner Benutzerverwaltung Grafiken hochladen kann, und diese dann seinen Beiträgen hinzufügen. Also müsste jeder auf dieses Verzeichnis Zugriffsrechte haben.

      Diese Lösung ist schon gut, ich dachte nur, wenn es eine einfachere gäbe müsste ich mich nicht mit den Problemen rumschlagen.

      Gruss
      cyberscout

      1. Hallo nochmal
        Mein Problem hat sich soeben erledigt:

        Es lag am Pfad, bei dem Linuxserver den ich benutze, musste ich also der gesamte Pfad angeben, vom root-Verzeichnis (/) aus und nicht vom Basisverzeichnis der Homepage aus.

        Gruss
        cyberscout