Я программирую сценарий для загрузки изображений в мое приложение. Имеются ли следующие меры безопасности, чтобы сделать приложение безопасным со стороны сценария?
Это мой сценарий:
$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("Ymd").'/' ; 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"; }
Любые новые подсказки приветствуются 🙂
Повторно обработайте изображение с помощью GD (или Imagick) и сохраните обработанное изображение. Все остальные просто забавны для хакеров.
Изменить: И, как указывал rr, используйте move_uploaded_file()
для любой загрузки.
Позднее редактирование. Кстати, вы хотите быть очень ограничительным в своей папке загрузки. Эти места являются одним из темных уголков, где происходит много подвигов. Это допустимо для любого типа загрузки и любого языка / сервера программирования. Проверьте https://www.owasp.org/index.php/Unrestricted_File_Upload
Для проверки безопасности файлов изображений я могу представить себе 4 уровня ценных бумаг. Они были бы:
($file_info = getimagesize($_FILES['image_file']; $file_mime = $file_info['mime'];)
Примечание. Загрузка всего изображения будет медленной.
Еще одно очень важное замечание. Не загружайте и не загружайте все, что можно интерпретировать как HTML в браузере.
Поскольку файлы находятся в вашем домене, javascript, содержащийся в этом документе HTML, будет иметь доступ ко всем вашим куки-файлам, позволяя какую-то атаку XSS.
Атакующий загружает HTML-файл с JS-кодом, который отправляет все файлы cookie на его сервер.
Злоумышленник отправляет ссылку вашим пользователям по почте, PM или просто через iframe на своем или любом другом сайте.
Сделать загруженный контент доступным только в субдомене или другом домене. Таким образом, файлы cookie не будут доступны. Это также один из советов по эффективности Google:
https://developers.google.com/speed/docs/best-practices/request#ServeFromCookielessDomain
Возможно, вы захотите запустить «is_uploaded_file» в $ _FILES ['my_files'] ['tmp_name']. См. http://php.net/manual/en/function.is-uploaded-file.php
Создайте новый файл .htaccess в каталоге uploads и вставьте этот код:
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
Просто не забудьте переименовать файлы u upload + забыть о проверке типов, содержимого и т. Д.
Я повторю что-то, что я разместил в связанном вопросе.
Вы можете определить тип контента, используя функции Fileinfo (mime_content_type () в предыдущих версиях PHP).
Выдержка из PHP-руководства по старшему расширению Mimetype, которое теперь заменено на Fileinfo:
Функции в этом модуле пытаются угадать тип содержимого и кодировку файла путем поиска определенных последовательностей магического байта в определенных положениях файла. Хотя это не пуленепробиваемый подход, используемые эвристики делают очень хорошую работу.
getimagesize()
также может делать хорошую работу, но большинство других проверок, которые вы выполняете, нонсенс. Например, почему строка php
не разрешена в имени файла. Вы не собираетесь включать файл изображения в PHP-скрипт, просто потому, что его имя содержит строку php
, не так ли?
Когда дело доходит до повторного создания изображений, в большинстве случаев это улучшит безопасность … пока библиотека, которую вы используете, не уязвима.
Итак, какое расширение PHP лучше всего подходит для безопасного повторного создания образа? Я проверил сайт CVE . Я думаю, что применимое трио – это те расширения:
Из сравнения я думаю, что GD подходит лучше всего, потому что у него наименьшее количество проблем безопасности, и они довольно старые. Три из них критичны, но ImagMagick и Gmagick не работают лучше … ImageMagick кажется очень глючным (по крайней мере, когда дело доходит до безопасности), поэтому я выбираю Gmagick как второй вариант.
если безопасность очень важна, используйте базу данных для сохранения имени файла и переименованного имени файла, и здесь вы можете изменить расширение файла на somthing как .myfile и создать файл php для отправки изображения с заголовками. php может быть более безопасным, и вы можете использовать его в теге img как blow:
<img src="send_img.php?id=555" alt="">
также проверяйте расширение файла EXIF перед загрузкой.
Самый простой ответ, который позволяет пользователям безопасно загружать файлы на PHP : Всегда сохранять файлы за пределами вашего корня документа.
Например: Если ваш корневой каталог вашего документа /home/example/public_html
, сохраните файлы в /home/example/uploaded
.
Благодаря безопасному сохранению ваших файлов из-за того, что ваш веб-сервер напрямую выполняется, существует несколько способов сделать их доступными для ваших посетителей:
Однако, если вы переходите с вариантами 1 или 3 в этот список, и у вас есть уязвимость включения локального файла в вашем приложении, ваша форма загрузки файлов все равно может быть вектором атаки .
Лучший способ защитить свой сайт при загрузке изображения пользователя – это сделать следующие шаги:
Для файла изображения вы также можете изменить разрешение файла после переименования, чтобы убедиться, что оно никогда не выполняется (rw-r-r–)
Я использую php-upload-script, который создает новый случайный 4-байтовый номер для каждого загруженного файла, затем XOR содержимое файла с этими 4 байтами (повторяя их так часто, как это необходимо) и, наконец, присоединяет 4 перед сохранением файла.
Для загрузки 4 байта необходимо снова отключить от файла, содержимое будет снова обработано с помощью XORed и результат будет отправлен клиенту.
Таким образом, я могу быть уверен, что файлы, которые я сохраняю на сервере, не будут исполняемыми или иметь какое-либо потенциальное значение для любого приложения. Кроме того, мне не нужна дополнительная база данных для хранения имен файлов.
Вот код, который я использую для этого:
Загрузить:
<?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); ?>
Скачать:
<?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); ?>