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?
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 :)
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
Für den Sicherheitstest der Bilddateien kann ich mir 4 Sicherheitsstufen vorstellen. Sie würden sein:
($file_info = getimagesize($_FILES['image_file']; $file_mime = $file_info['mime'];)
Hinweis: Das Laden des gesamten Bildes wäre langsam.
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.
Der Angreifer lädt eine HTML-Datei mit JS-Code hoch, der alle Cookies an seinen Server sendet.
Der Angreifer sendet den Link per E-Mail, PM oder einfach per iframe auf seiner oder einer anderen Website an Ihre Benutzer.
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
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
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
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:
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.
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.
Der beste Weg, um Ihre Website sicher zu halten, wenn ein Benutzer ein Bild hochlädt, um diese Schritte auszuführen:
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:
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.
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);
?>
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--).