Ankündigung

Einklappen
Keine Ankündigung bisher.

[Erledigt] Upload - Prüfung Dateityp

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • [Erledigt] Upload - Prüfung Dateityp

    So, jetzt kommt noch mein Upload-Script für Dokumente. Ich will sicherstellen, dass nur valide Datei eines bestimmten Typs hochgeladen werden können.
    PHP-Code:
    <form enctype="multipart/form-data" action="<?php echo $_SERVER['SCRIPT_NAME']."?sid=".$sid?>" method="POST">
        <!-- Der Name des Input Felds bestimmt den Namen im $_FILES Array -->
        Diese Datei hochladen:<br /> <input name="userfile" type="file" /> 
        <input type="submit" name="los" value="Hochladen" />
    </form>
    PHP-Code:
    if ($_POST['los']) {

    $uploaddir _DOCPFAD_ABS;
    $uploaddatei basename(strip_tags($_FILES['userfile']['name']));
    $uploadfile $uploaddir $uploaddatei;
    $dateiendung substr (stristr $uploaddatei'.' ), 1);

    /* MIME-Typ einer spezifischen Datei ermitteln */
    $filename $_FILES['userfile']['tmp_name'];
    $finfo finfo_open(FILEINFO_MIME_TYPE); 
    if (!
    $finfo) {
        echo 
    "Öffnen der fileinfo-Datenbank fehlgeschalgen";
        exit();
    }
    echo 
    "MIMETYPE nach finfo_file: ".finfo_file($finfo$filename);
    $mimetype_import finfo_file($finfo$filename);
    /* Verbindung schließen */
    finfo_close($finfo);
    echo 
    "<hr />";
    $mimetype_erlaubt = array("application/pdf""application/msword""application/vnd.ms-excel""application/vnd.ms-powerpoint""text/plain");
    if (!
    in_array($mimetype_import,$mimetype_erlaubt)) {
        echo 
    "Kein gültiger Mime-Type<br />";
        exit;
        }
    echo 
    "<hr />";
    $endung = array("pdf""doc""docx""xls""xlsx""ppt""pptx""txt");    
    if (!
    in_array($dateiendung,$endung)) {
        echo 
    "Keine gültige Dateiendung<br />";
        exit;
        }

    if (
    substr_count $dateiendung'.' ) > 0) {
        echo 
    "Wahrscheinlich doppelte Dateiendung<br />";
        exit;
        }
    if (
    file_exists($uploadfile)) {
        echo 
    "Diese Datei gibt es schon!<br />";
        exit;
        }
    $suche "/[^0-9a-zA-Z_\.\-\@]|NULL/";
    if (
    preg_match($suche,$uploaddatei)) {
        echo 
    "Kein gülter Dateiname!";
        exit;
    }    

    else {
    if (
    move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
        echo 
    "Datei ist valide und wurde erfolgreich hochgeladen.\n";
        }
        else {
        echo 
    "Möglicherweise eine Dateiupload-Attacke!<br />";
        echo 
    "Fehler: ".$_FILES['userfile']['error']."<br />";
        }
    }

            echo 
    "<table border='1' width='80%'><tr><td>";
            echo 
    "<h3>Gerade hoch geladenes Dokument:</h3>";    
            echo 
    $uploaddatei."<br/>";
            echo 
    "</td></tr></table>";


    // Ende if ($_POST['los']) { 
    Bin schon gespannt auf Kritik / Feedback usw. Danke schon mal!

  • #2
    Fortgeschritten ist das nun eimal gar nicht.

    - Du formatierst nicht immer gleich.
    - Du mischst Ein- und Ausgabe. Informiere dich über EVA.
    - Das ist nicht Objekt-Orientiert, also in dem Falle nicht wiederverwendbar.
    - Bereits die erste Zeile kann eine Notice werden. Siehe isset()
    [URL="https://github.com/chrisandchris"]GitHub.com - ChrisAndChris[/URL] - [URL="https://github.com/chrisandchris/symfony-rowmapper"]RowMapper und QueryBuilder für MySQL-Datenbanken[/URL]

    Kommentar


    • #3
      Hallo Christian,

      dann hilf doch mal einem als Fortgeschrittenem getarnten Anfänger...
      - Du formatierst nicht immer gleich.
      >> was meinst du damit genau?
      - Du mischst Ein- und Ausgabe. Informiere dich über EVA.
      >> wo mische ich Ein- und Ausgabe? Und wer ist EVA?
      - Das ist nicht Objekt-Orientiert, also in dem Falle nicht wiederverwendbar.
      OOP werde ich mir erst noch aneignen; ist aber sicher kein Hindernis hier im Forum Fragen zu stellen, oder?
      - Bereits die erste Zeile kann eine Notice werden. Siehe isset()
      Meinst du sowas wie
      PHP-Code:
      if ( isset($_POST['los']) 
      oder was meinst du?

      Bin sehr dankbar für deine Tipps - besonders was die Sicherheitsaspekte des uploads angeht....

      Kommentar


      • #4
        dann hilf doch mal einem als Fortgeschrittenem getarnten Anfänger...
        warum sollte man das tun, sei ehrlich zu Dir selbst und ändere die Selbsteinschätzung.
        - Du formatierst nicht immer gleich.
        >> was meinst du damit genau?
        Damit meint er, daß Du bspw. geschweifte Klammern nicht einheitlich einrückst, Code wird dadurch unübersichtlich und schlechter lesbar!
        - Du mischst Ein- und Ausgabe. Informiere dich über EVA.
        >> wo mische ich Ein- und Ausgabe? Und wer ist EVA?
        E.V.A Prinzip in der EDV, darf man als Fortgeschrittener kennen.
        - Das ist nicht Objekt-Orientiert, also in dem Falle nicht wiederverwendbar.
        OOP werde ich mir erst noch aneignen; ist aber sicher kein Hindernis hier im Forum Fragen zu stellen, oder?
        Das sicher nicht, aber solange Du Dich als Fortgeschritten bezeichnest, kann man Deine Scripte nicht ernst nehmen!
        - Bereits die erste Zeile kann eine Notice werden. Siehe isset()
        Meinst du sowas wie
        PHP-Code:
        if ( isset($_POST['los']) 
        ...sowas in der Art meint er, fehlt zwar noch ne Klammer usw. aber Du hast es erfasst.

        Sorry, all die Dinge sollten Dir als Fortgeschrittener bekannt sein und keine Fragen aufwerfen!
        Competence-Center -> Enjoy the Informatrix
        PHProcks!Einsteiger freundliche TutorialsPreComposed Packages

        Kommentar


        • #5
          Ach hängt euch doch nicht an dem "Fortgeschritten" auf^^

          Paar Links zum Thema
          http://stackoverflow.com/questions/2...loading-a-file
          http://www.sitepoint.com/file-uploads-with-php/
          [COLOR=#A9A9A9]Relax, you're doing fine.[/COLOR]
          [URL="http://php.net/"]RTFM[/URL] | [URL="http://php-de.github.io/"]php.de Wissenssammlung[/URL] | [URL="http://use-the-index-luke.com/de"]Datenbankindizes[/URL] | [URL="https://www.php.de/forum/webentwicklung/datenbanken/111631-bild-aus-datenbank-auslesen?p=1209079#post1209079"]Dateien in der DB?[/URL]

          Kommentar


          • #6
            Ich würde eine Klasse für dies machen, dann kannst Du diese auch immer wieder benutzen auch für andere Projekte.

            Habe mal ein Beispiel von mir, wie man dann ein Upload definieren kann.

            PHP-Code:
            class service_upload{
            }

            $Upload = new service_upload();
            $Upload->setDocumentRoot(PROJECT_DOCUMENT_ROOT);
            $Upload->setBaseUploadDirectory('public_uploads');
            $Upload->setUploadDirectory('public_uploads'); 

            $Upload->setAllowMultiple(true);
            $Upload->setMaxFilesToUpload(5); //only for multiple

            $Upload->setAllowedTypes(array('jpg''png''gif''txt''pdf''sql''docx''xlsx''JPG')); //overwrites default set in class, so only these set here are allowed
            $Upload->setNotAllowedTypes(array('php''php0''php1''php2''php3''php4''php5''php6''php7''php8''php9''js''exe''cgi''pl'));    
            /*$Upload->setFilesToFolder(array(//'' => array('png', 'gif', 'tif', 'tiff', 'JPG'),
                                            'images' => array('jpg', 'png', 'gif', 'tif', 'tiff', 'JPG'),
                                            'pdf' => array('pdf'),
                                            'misc' => array('pdf', 'zip', 'gzip', 'txt', 'docx', 'xlsx')
                                            )
                                      ); //from (BaseUploadDirectory)/images as example -> method is optional*/
                                      
            $Upload->renameFilesTo('-'.uniqid().'-'.time());
            //$Upload->setMaxSize(34567);

                          
            if ($Upload->upload()) {
                
            //upload success
                
            $Upload->getStatus('files')
            } else {

                echo 
            $Upload->getErrors();

            Kommentar


            • #7
              Also, ich erkläre es jetzt einmal, dann ist aber auch gut.

              Ich habe einen anderen Beruf, mache das in der Freizeit nun seit über 10 Jahren und habe einige aus meiner Sicht komplexe Sachen hinbekommen (kleines CMS, Buchungssystem für Ferienwohnung u.ä.).

              Nach zwei Jahren Pause bin ich jetzt wieder eingestiegen (war früher im Self-PHP-Forum, aber da ist nix mehr los) und da lag es nicht so fern, mich nicht als Anfänger einzustufen. Nun bin ich positiv überrascht vom hohen professionellen Niveau des Forums hier und kann viel dazu lernen.

              Ich plane, die Seiten neu aufzusetzen, und werde mich dann auch in OOP einarbeiten, msqli oder PDO verwenden usw. Jetzt geht es mir nur darum die bestehende (autodidaktisch gestrickte) Webseite sicher zu machen (es gab einen Hackerangriff). Dabei nützen mir fachliche Hinweise zu meinen Lösungen bisserl mehr als Feststellungen, dass in einem 50-Zeilen-Script ein paar Zeilen nicht richtig eingerückt sind.

              So, damit einige gut schlafen können, werde ich meinen Status auf Anfänger ändern.

              Zur Sache selbst im nächsten Post.

              Kommentar


              • #8
                @VPh

                danke für die Links; da stehen gute Hinweise drin, zu denen ich noch Fragen habe. Hier
                http://stackoverflow.com/questions/2...loading-a-file
                Warum soll ich den Dateinamen nicht übernehmen und einen zufälligen generieren? Reicht es nicht, den Namen mit meinem regulären Ausdruck zu checken?

                Dann wird vorgeschlagen, den Download einer Datei (nicht Bild) zu erzwingen.
                Code:
                X-Download-Options: noopen
                Content-Disposition: attachment; filename=untrustedfile.html
                Wo muss das denn hin? In den Head-Bereich der Seite? Und welche Rolle spielt die "untrustedfile.html"?

                Aufnehmen werde ich noch den chmod. Im Uploadverzeichnis ist die php engine übrigens schon per htaccess ausgeschaltet. Diese Verzeichnisse außerhalb des Web-Root zu legen, find ich gut - ist aber bisserl Arbeit.

                Die andere Seite
                http://www.sitepoint.com/file-uploads-with-php/
                Ist dieses http://www.clamav.net/index.html zu empfehlen?

                @strub

                Danke für die Klasse. Wenn ich OOP kann, werde ich darauf zurück kommen.

                Kommentar


                • #9
                  Zitat von HeinrichK Beitrag anzeigen
                  A[...]



                  So, damit einige gut schlafen können, werde ich meinen Status auf Anfänger ändern.



                  Zur Sache selbst im nächsten Post.

                  Ob du Profi bist oder nicht definiert sich nicht nur an der Einrückung des Codes, sondern auch an der Art der Fragestellung. Das fehlte mir ein wenig - tut ja aber jetzt nichts zur Sache.

                  Ein Upload-Ordner ausserhalb des web-roots zu legen sollte null Aufwand sein. Im Idealfall definierst du einen absoluten Basispfad für die Uploads und die Dateien werden relativ dazu hochgeladen. Ja keine absoluten Pfade irgendwo in der DB speichern, sobald du das System umziehst gibt das einen Haufen Probleme.

                  PHP abzuschalten via htaccess mag ok sein, denk daran, dass es noch Python, Perl und andere Skriptsprachen gibt, die gefährlich sein könnten. Hier empfehle ich Lagern ausserhalb des web-roots. Löst ziemlich alle Probleme.
                  [URL="https://github.com/chrisandchris"]GitHub.com - ChrisAndChris[/URL] - [URL="https://github.com/chrisandchris/symfony-rowmapper"]RowMapper und QueryBuilder für MySQL-Datenbanken[/URL]

                  Kommentar


                  • #10
                    Danke Christian,

                    so habe ich's vor.
                    Ein Upload-Ordner ausserhalb des web-roots zu legen sollte null Aufwand sein. Im Idealfall definierst du einen absoluten Basispfad für die Uploads und die Dateien werden relativ dazu hochgeladen. Ja keine absoluten Pfade irgendwo in der DB speichern, sobald du das System umziehst gibt das einen Haufen Probleme.
                    @All

                    Vielleicht noch einige Tipps zu meinen letzten Fragen (voriges Posting)...?

                    Kommentar


                    • #11
                      Hallo Christian,

                      es gelingt mir nicht, ein Bild mit einem absoluten Pfad (oberhalb des Webroots) in der Webseite anzuzeigen. Scheint auch nicht zu gehen:
                      http://www.php.de/wiki-php/index.php...Webentwicklung
                      Auch alle Versuche, erstmal serverseitig das Bild "abzuholen" (file_get_contents oder so), funktionieren nicht.

                      Weiß auch nicht mehr, ob das mehr Sicherheit bringt, weil dann ja für jeden der absoluten Pfad auf dem Server im Browser erkennbar und für "Spielereien" verfügbar ist.
                      Ich könnte natürlich eine Subdomain auf diesen (Bilder-)Pfad legen, aber dann ist die erkennbar.
                      ist alles so etwa wie sich hintern Baum zu stellen in der Hoffnung, der Angreifer übersieht mich.

                      Kommentar


                      • #12
                        Ich könnte mir vorstellen, daß Du das etwas falsch verstanden hast.
                        Du kannst ein Bild sowieso nicht á la
                        Code:
                        <img src="/www/vhosts/example.com/images/foo.jpg" alt="" />
                        über den Serverpfad ziehen. Der HTTP-Request hat da keinen Zugriff drauf.
                        Du kannst aus Verzeichnissen ausserhalb des Webroot in Deinem Falle nur mit PHP zugreifen.

                        D.h., Du mußt das in PHP ziehen und für die Ausgabe bereitstellen.
                        Ich frage mich nur, wofür das für Bilder gut sein soll?

                        Rückfrage
                        Geht es immer noch darum, Bilder zum Download forcieren, die nicht über direkte Links zugänglich sind?
                        Competence-Center -> Enjoy the Informatrix
                        PHProcks!Einsteiger freundliche TutorialsPreComposed Packages

                        Kommentar


                        • #13
                          Hallo Arne,

                          Der HTTP-Request hat da keinen Zugriff drauf.
                          Das habe ich verstanden.
                          Du kannst aus Verzeichnissen ausserhalb des Webroot in Deinem Falle nur mit PHP zugreifen.
                          D.h., Du mußt das in PHP ziehen und für die Ausgabe bereitstellen.
                          Hier weiß ich nicht, wie das geht.
                          Ich frage mich nur, wofür das für Bilder gut sein soll?
                          Rückfrage
                          War ein Vorschlag von Christian, wobei ich inzwischen auch daran zweifele (siehe mein letztes Posting).
                          Geht es immer noch darum, Bilder zum Download forcieren, die nicht über direkte Links zugänglich sind?
                          Nein, sondern (s.o.) den Bilder-Ordner außerhalb des Webroots anzusiedeln, damit kein Schadcode innerhalb des Webroot ausgeführt werden kann. Hilft aber nur in dem Fall, wenn es jemand gelänge, eine entsprechende Datei durch meine Prüfungen zu schmuggeln.

                          Jetzt sind wir aber beim Thema Bilder angelangt. Ich wollte in diesem Thread eher den Upload anderer Dateitypen thematisieren. Da sind noch meine Fragen offen:
                          Code:
                          X-Download-Options: noopen
                          Content-Disposition: attachment; filename=untrustedfile.html
                          Aus: http://stackoverflow.com/questions/2...loading-a-file
                          Wo muss das denn hin? In den Head-Bereich der Seite? Und welche Rolle spielt die "untrustedfile.html"?

                          Und die Frage, ob dieser Virenscanner zu empfehlen ist:
                          http://www.clamav.net/index.html
                          Aus: http://www.sitepoint.com/file-uploads-with-php/

                          Kommentar


                          • #14
                            Nunja, die Idee war von mir, ja. Kommt halt drauf an, was für Bilder du hast und wieso du die speicherst. Wenn du den Zugriff von aussen verhindern möchtest ist ausserhalb des Web-Root die sicherere Variante als im Web-Root und mittels .htaccess den Zugriff zu verbieten.

                            Nein, das ist ein Header. Und "untrustedfile.html" ist der Vorschlag, wie der Browser die Datei benennen soll (beim Speichern auf der HD des Clients). Ist ja ein Download (attachment).
                            [URL="https://github.com/chrisandchris"]GitHub.com - ChrisAndChris[/URL] - [URL="https://github.com/chrisandchris/symfony-rowmapper"]RowMapper und QueryBuilder für MySQL-Datenbanken[/URL]

                            Kommentar


                            • #15
                              Kommt halt drauf an, was für Bilder du hast und wieso du die speicherst.
                              Die Bilder sollen in der Webseite angezeigt werden. Also treffen wohl die Überlegungen - außerhalb Webroot speichern - nicht zu. Wenn's gelingt, Schadcode reinzufummeln, kommt der dann trotzdem bei der Anzeige zur Ausführung.

                              Nein, das ist ein Header.
                              Dann müsste ich den in jede Datei vor/beim Upload einfügen? In PDF, Excel, Word...?

                              Kommentar

                              Lädt...
                              X