it-swarm.com.de

PHP Checkliste für das Hochladen von Bildern

Ich programmiere ein Skript, um Bilder in meine Anwendung hochzuladen. Reichen die folgenden Sicherheitsmaßnahmen aus, um die Anwendung auf der Skriptseite sicher zu machen?

  • Deaktivieren Sie PHP mithilfe von .httaccess im Upload-Ordner.
  • Erlaube das Hochladen nicht, wenn der Dateiname die Zeichenfolge "php" enthält.
  • Lassen Sie nur Erweiterungen zu: jpg, jpeg, gif und png.
  • Nur Bilddateityp zulassen.
  • Bild mit zwei Dateitypen nicht zulassen.
  • Ändern Sie den Bildnamen.
  • Hochladen in ein Unterverzeichnis, nicht im Stammverzeichnis.

Das ist mein Skript:

 $filename=$_FILES['my_files']['name'];
 $filetype=$_FILES['my_files']['type'];
 $filename = strtolower($filename);
 $filetype = strtolower($filetype);

 //check if contain php and kill it 
 $pos = strpos($filename,'php');
 if(!($pos === false)) {
  die('error');
 }




 //get the file ext

 $file_ext = strrchr($filename, '.');


 //check if its allowed or not
 $whitelist = array(".jpg",".jpeg",".gif",".png"); 
 if (!(in_array($file_ext, $whitelist))) {
    die('not allowed extension,please upload images only');
 }


 //check upload type
 $pos = strpos($filetype,'image');
 if($pos === false) {
  die('error 1');
 }
 $imageinfo = getimagesize($_FILES['my_files']['tmp_name']);
 if($imageinfo['mime'] != 'image/gif' && $imageinfo['mime'] != 'image/jpeg'&& $imageinfo['mime']      != 'image/jpg'&& $imageinfo['mime'] != 'image/png') {
   die('error 2');
 }
//check double file type (image with comment)
if(substr_count($filetype, '/')>1){
die('error 3')
}

 // upload to upload direcory 
 $uploaddir = 'upload/'.date("Y-m-d").'/' ;

if (file_exists($uploaddir)) {  
} else {  
    mkdir( $uploaddir, 0777);  
}  
  //change the image name
 $uploadfile = $uploaddir . md5(basename($_FILES['my_files']['name'])).$file_ext;



  if (move_uploaded_file($_FILES['my_files']['tmp_name'], $uploadfile)) {
 echo "<img id=\"upload_id\" src=\"".$uploadfile."\"><br />";
  } else {
   echo "error";
  }

Alle neuen Tipps sind willkommen :)

60
usef_ksa

Verarbeiten Sie das Bild mit Gd (oder Imagick) erneut und speichern Sie das verarbeitete Bild. Alle anderen sind nur gerecht spaß langweilig für Hacker.

Bearbeiten: Und wie rr hervorgehoben hat, verwenden Sie move_uploaded_file() für jeden Upload.

Späte Bearbeitung: Übrigens möchten Sie Ihren Upload-Ordner sehr einschränken. Diese Orte sind eine der dunklen Ecken, an denen viele Exploits stattfinden. Dies gilt für jede Art von Upload und jede Programmiersprache/Server. Überprüfen Sie https://www.owasp.org/index.php/Unrestricted_File_Upload

33
Halil Özgür

Für den Sicherheitstest der Bilddateien kann ich mir 4 Sicherheitsstufen vorstellen. Sie würden sein:

  • Stufe 1: Überprüfen Sie die Erweiterung (Erweiterungsdatei endet mit)
  • Ebene 2: Überprüfen Sie den MIME-Typ ($file_info = getimagesize($_FILES['image_file']; $file_mime = $file_info['mime'];)
  • Stufe 3: Lesen Sie die ersten 100 Bytes und prüfen Sie, ob sie Bytes im folgenden Bereich enthalten: ASCII 0-8, 12-31 (dezimal).
  • Stufe 4: Suchen Sie im Header nach magischen Zahlen (die ersten 10-20 Bytes der Datei). Einige der Kopfzeilen der Dateien finden Sie hier: http://en.wikipedia.org/wiki/Magic_number_%28programming%29#Examples

Hinweis: Das Laden des gesamten Bildes wäre langsam. 

12
tanjir

XSS-Warnung

Noch eine sehr wichtige Bemerkung. Senden/laden Sie nichts, was im Browser als HTML interpretiert werden könnte.

Da sich die Dateien in Ihrer Domain befinden, hat das in diesem HTML-Dokument enthaltene Javascript Zugriff auf alle Ihre Cookies und ermöglicht so eine Art XSS-Angriff.

Angriffsszenario:

  1. Der Angreifer lädt eine HTML-Datei mit JS-Code hoch, der alle Cookies an seinen Server sendet.

  2. Der Angreifer sendet den Link per E-Mail, PM oder einfach per iframe auf seiner oder einer anderen Website an Ihre Benutzer.

Sicherste Lösung:

Machen Sie hochgeladene Inhalte nur in der Subdomain oder in einer anderen Domain verfügbar. Auf diese Weise werden Cookies nicht zugänglich sein. Dies ist auch einer der Leistungstipps von Google:

https://developers.google.com/speed/docs/best-practices/request#ServeFromCookielessDomain

7
Rok Kralj

Möglicherweise möchten Sie "is_uploaded_file" auch für $ _FILES ['my_files'] ['tmp_name'] ausführen. Siehe http://php.net/manual/de/function.is-uploaded-file.php

6
rr.

Erstellen Sie eine neue .htaccess-Datei im Upload-Verzeichnis und fügen Sie diesen Code ein:

php_flag engine 0
RemoveHandler .phtml .php .php3 .php4 .php5 .php6 .phps .cgi .exe .pl .asp .aspx .shtml .shtm .fcgi .fpl .jsp .htm .html .wml
AddType application/x-httpd-php-source .phtml .php .php3 .php4 .php5 .php6 .phps .cgi .exe .pl .asp .aspx .shtml .shtm .fcgi .fpl .jsp .htm .html .wml

Stellen Sie sicher, dass Sie die Dateien umbenennen

6
jloa

Ich werde etwas wiederholen, das ich in einer verwandten Frage gepostet habe.

Sie können den Inhaltstyp mithilfe der Fileinfo-Funktionen (mime_content_type () in früheren PHP-Versionen) ermitteln.

Ein Auszug aus dem Formular PHP zur älteren Mimetype-Erweiterung, das jetzt durch Fileinfo ersetzt wird:

Die Funktionen in diesem Modul versuchen, den Inhaltstyp und .__ zu erraten. Kodierung einer Datei durch Suchen nach bestimmten magischen Byte-Sequenzen bei bestimmte Positionen in der Datei. Dies ist zwar kein kugelsicherer Beweis Herangehensweise machen die verwendeten Heuristiken einen sehr guten Job.

getimagesize() kann auch gute Arbeit leisten, aber die meisten anderen Überprüfungen, die Sie durchführen, sind Unsinn. Zum Beispiel, warum die Zeichenfolge php in Dateiname nicht zulässig ist. Sie werden keine Bilddatei in das Skript PHP einschließen, nur weil der Name php string enthält, oder?


Bei der Neuerstellung von Images wird in den meisten Fällen die Sicherheit verbessert ... bis die von Ihnen verwendete Bibliothek nicht anfällig ist.

Welche PHP -Erweiterung eignet sich am besten für eine sichere Image-Erstellung? Ich habe die CVE details Website überprüft. Ich denke, das anwendbare Trio sind diese Erweiterungen:

  1. Gd (6 Schwachstellen)
  2. ImageMagick (44 Schwachstellen)
  3. Gmagick (12 Schwachstellen)

Aus dem Vergleich finde ich, dass Gd am besten geeignet ist, weil es die geringste Anzahl von Sicherheitsproblemen hat und sie ziemlich alt sind. Drei von ihnen sind kritisch, aber ImagMagick und Gmagick schneiden nicht besser ab ... ImageMagick scheint sehr fehlerhaft zu sein (zumindest was die Sicherheit angeht), daher wähle ich Gmagick als zweite Option.

5
doc

wenn die Sicherheit sehr wichtig ist, verwenden Sie die Datenbank für den Namen der Sicherungsdatei und den umbenannten Dateinamen. Hier können Sie die Dateierweiterung in eine Datei wie .myfile ändern und eine PHP-Datei für das Senden von Bildern mit Kopfzeilen erstellen. php kann sicherer sein und Sie können es im img-Tag wie blow verwenden: 

<img src="send_img.php?id=555" alt="">

Überprüfen Sie auch die Dateierweiterung vor dem Hochladen mit EXIF. 

2
Mohamad Rostami

Der beste Weg, um Ihre Website sicher zu halten, wenn ein Benutzer ein Bild hochlädt, um diese Schritte auszuführen:

  • Überprüfen Sie die Bilderweiterung
  • Überprüfen Sie die Bildgröße mit dieser Funktion "getimagesize ()"
  • danach können Sie die Funktion "file_get_contents ()" verwenden
  • Am Ende sollten Sie file_Content in Ihre Datenbank einfügen Ich denke, das ist der beste Weg! Was ist deine Meinung?
2
Hamza Ouha

Die einfachste Antwort auf Benutzer dürfen sicher Dateien in PHP hochladen lautet: Speichern Sie Dateien immer außerhalb Ihres Dokumentenstamms.

Beispiel: Wenn Ihr Dokumentstammverzeichnis /home/example/public_html ist, speichern Sie die Dateien unter /home/example/uploaded.

Da Ihre Dateien nicht direkt von Ihrem Webserver ausgeführt werden können, gibt es mehrere Möglichkeiten, sie für Ihre Besucher zugänglich zu machen:

  1. Richten Sie einen separaten virtuellen Host für das Bereitstellen statischer Inhalte ein, der niemals Skripts für PHP, Perl usw. ausführt.
  2. Laden Sie die Dateien auf einen anderen Server hoch (z. B. einen billigen VPS, Amazon S3 usw.).
  3. Behalten Sie sie auf demselben Server, und verwenden Sie ein PHP - Skript, um Anforderungen zu proxyieren, um sicherzustellen, dass die Datei nur lesbar und nicht ausführbar ist.

Wenn Sie jedoch die Optionen 1 oder 3 in dieser Liste wählen und in Ihrer Anwendung eine Schwachstelle für die lokale Dateieinschließung besteht, kann Ihr Dateiuploadformular immer noch ein Angriffsvektor sein.

2

Ich verwende ein PHP-Upload-Skript, das eine neue zufällige 4-Byte-Nummer für jede hochgeladene Datei erstellt, dann den Inhalt der Datei mit diesen 4 Bytes XORs (sie so oft wie nötig wiederholt) und schließlich die 4 anfügt Bytes in die Datei, bevor Sie sie speichern.

Zum Download müssen die 4 Bytes wieder von der Datei abgeschnitten werden, der Inhalt wird erneut mit XORs versehen und das Ergebnis wird an den Client gesendet.

Auf diese Weise kann ich sicher sein, dass die Dateien, die ich auf dem Server speichere, nicht ausführbar sind oder irgendeine potenzielle Bedeutung für eine Anwendung haben. Außerdem brauche ich keine zusätzliche Datenbank, um Dateinamen zu speichern.

Hier ist der Code, den ich dafür verwende:

Hochladen:

        <?php
            $outputfilename = $_POST['filename'];
            $inputfile = $_FILES["myblob"]["tmp_name"];
            $tempfilename="temp.tmp";

            if( move_uploaded_file($inputfile, $tempfilename) ) {
                $XORstring = random_bytes(4);

                $tempfile=fopen($tempfilename, "r");
                $outputfile=fopen($outputfilename, "w+");
                flock($outputfilename, LOCK_EX);

                fwrite($outputfilename, $XORbytes1);

                while ( $buffer = fread($tempfile, 4) ) {
                    $buffer = $buffer ^ $XORstring;
                    fwrite($outputfilename, $buffer);
                }

                flock($outputfilename, LOCK_UN);

                fclose($tempfile);
                fclose($outputfile);

                unlink($tempfilename);
            }

            exit(0);
        ?>

Herunterladen:

        <?php
            $inputfilename = $_POST['filename'];
            $tempfilename = "temp.tmp";

            $inputfile=fopen($inputfilename, "r");
            $tempfile=fopen($tempfilename, "w+");
            flock($tempfile, LOCK_EX);

            $XORstring = fread($inputfile, 4);

            while ( $buffer = fread($inputfile, 4) ) {
                $buffer = $buffer ^ $XORstring;
                fwrite($tempfile, $buffer);
            }

            flock($tempfile, LOCK_UN);

            fclose($inputfile);
            fclose($tempfile);

            readfile($tempfile);
            unlink($tempfile);

            exit(0);
        ?>
0
Max M.

Bei einer Image-Datei können Sie auch die Dateiberechtigung nach dem Umbenennen ändern, um sicherzustellen, dass sie niemals ausgeführt wird (rw-r - r--).

0
Jesus