Генератор форм

Для веб-мастера

Реклама

Загрузка файлов на сервер с помощью PHP. Основные уязвимости и способы их избежать.

Рейтинг:
Дата: 19 января 2011 Просмотры 25237 Комментарии 6

В прошлой статье я рассказал Вам о механизме загрузки файлов на сервер при помощи PHP. В той статье я лишь раскрыл сам процесс загрузки и не касался вопросов безопасности.

Часто загрузка файлов без обеспечения надлежащего контроля безопасности приводит к образованию уязвимостей, которые, как показывает практика, стали настоящей проблемой в веб-приложениях на PHP.

Если Вы не обеспечите необходимый уровень безопасности, то злоумышленник сможет закачать произвольный файл на сервер, например, php-скрипт, при помощи которого он сможет просмотреть любой файл на сервере или что еще хуже выполнить произвольный код!

Поэтому в этой статье я постараюсь рассказать об основных уязвимостях веб-приложений по загрузке файлов на сервер и способах их избежать.

Итак, приступим. Первое что приходит в голову каждому разработчику это проверять Content-Type файлов. Другими словами — разрешить загрузку файлов строго определенного типа. Давайте взглянем на код:

<?php

if(isset($_POST['upload'])){
   
   if($_FILES['uploadFile']['type'] != "image/gif") {

      echo "Ошибка,  Вы можете загружать только gif картинки";

      exit;
  }

  $folder =  'path/to/folder/';

  $uploadedFile =  $folder.basename($_FILES['uploadFile']['name']);

  if(is_uploaded_file($_FILES['uploadFile']['tmp_name'])){

     if(move_uploaded_file($_FILES['uploadFile']['tmp_name'], $uploadedFile)){

        echo Файл загружен;
     }
     else {

        echo "Во время загрузки файла произошла ошибка";
     }
  }
  else {

       echo "Файл не  загружен";
  }
}

?>

Если обычный пользователь попытается загрузить любой другой файл, кроме gif-картинки, то ему будет выдано предупреждение!Но злоумышленник не будет использовать веб-форму на Вашем сайте.

Он может написать небольшой Perl-скрипт(возможно на любом языке), который будет эмулировать действия пользователя по загрузке файлов, дабы изменить отправляемые данные на свое усмотрение.Так как проверяемый MIME-тип приходит вместе с запросом, то ничего не мешает злоумышленнику установить его в «image/gif», поскольку с помощью эмуляции клиента он полностью управляет запросом, который посылает.

Если вы загружаете только изображения,то не стоит доверять заголовку Content-Type, а лучше проверить фактическое содержание загруженного файла, чтобы удостовериться что это действительно изображение. Для этого в РНР очень часто используют функцию getimagesize().

Функция getimagesize() определяет размер изображения GIF, JPG, PNG, SWF, PSD, TIFF или BMP и возвращает размеры, тип файла и высоту/ширину текстовой строки, используемой внутри нормального HTML-тэга IMG.

Давайте посмотрим, как можно использовать эту функцию в нашем скрипте:

<?php

if(isset($_POST['upload'])){
   
   $imageinfo =  getimagesize($_FILES['uploadFile']['tmp_name']);

   if($imageinfo['mime'] != 'image/gif' &&  
      $imageinfo['mime'] != 'image/jpeg'){

      echo "Вы можете загружать только gif и  jpeg картинки!";
      exit;
   }

  $folder =  'path/to/folder/';

  $uploadedFile =  $folder.basename($_FILES['uploadFile']['name']);

  if(is_uploaded_file($_FILES['uploadFile']['tmp_name'])){

     if(move_uploaded_file($_FILES['uploadFile']['tmp_name'],

        $uploadedFile)){

        echo Файл загружен;
     }
     else {

        echo "Во время загрузки файла произошла ошибка";
     }
  }
  else {

       echo "Файл не  загружен";
  }
}

?>

Можно подумать, что теперь мы можем пребывать в уверенности, что будут загружаться только файлы GIF или JPEG. К сожалению, это не так. Файл может быть действительно в формате GIF или JPEG, и в то же время PHP-скриптом. Большинство форматов изображения позволяет внести в изображение текстовые метаданные. Возможно создать совершенно корректное изображение, которое содержит некоторый код PHP в этих метаданных. Когда getimagesize() смотрит на файл, он воспримет это как корректный GIF или JPEG. Когда транслятор PHP смотрит на файл, он видит выполнимый код PHP в некотором двоичном «мусоре», который будет игнорирован.

Вы наверное спросите, а почему бы не проверять просто расширение файла? Если мы не позволим загружать файлы *.php, то сервер никогда не сможет выполнить этот файл как скрипт. Давайте рассмотрим и этот подход.

Вы можете составить белый список расширений и проверять имя загружаемого файла на соответствие белому списку.

<?php
if(isset($_POST['upload'])){
   
   $whitelist = array(".gif", ".jpeg", ".png"); 

   $error = true;
	
   //Проверяем разрешение файла
   foreach  ($whitelist as  $item) {
        if(preg_match("/$item\$/i",$_FILES['userfile']['name'])) $error = false;
   }

  if($error) die("Ошибка,  Вы можете загружать только gif,jpeg,png картинки"); 

  $folder =  'path/to/folder/';

  $uploadedFile =  $folder.basename($_FILES['uploadFile']['name']);

  if(is_uploaded_file($_FILES['uploadFile']['tmp_name'])){

     if(move_uploaded_file($_FILES['uploadFile']['tmp_name'],

        $uploadedFile)){

        echo Файл загружен;
     }
     else {

        echo "Во время загрузки файла произошла ошибка";
     }
  }
  else {

       echo "Файл не  загружен";
  }
}

?>

Выражение !preg_match ("/$item\$/i", $_FILES['uploadFile']['name']) проверяет соответствие имени файла, определенному пользователем в массиве белого списка. Модификатор «i» говорит, что наше выражение регистронезависимое. Если расширение файла соответствует одному из пунктов в белом списке, файл будет загружен, иначе скрипт выдаст ошибку!

Как видите доверять расширению и  Content-Type файла нельзя. Поэтому необходимо в каталог, куда закачиваются все Ваши файлы добавить файл .htaccess куда прописать следующие строки:


RemoveHandler .php .php5 .php4 .php3 .phtml .pl 
AddType text/plain .php .php .htm .html .phtml .pl

Данные строки в .htaccess заставит сервер не исполнять php и др. файлы, а выводить их содержимое на экран.

На этом все! Удачи!

Оцените эту статью:



Похожие статьи
Интересно почитать

    Получать новые материалы этого сайта на свой email адрес?

    Отправлять мне комментарии по эл. почте?

Простая CRM

Нашли ошибку в тексте

Система Orphus
https://biznesguide.ru/coding/119.html
4,45 из 5 на основе 31 оценок.