Форум АНТИЧАТ

Форум АНТИЧАТ (https://forum.antichat.xyz/index.php)
-   PHP, PERL, MySQL, JavaScript (https://forum.antichat.xyz/forumdisplay.php?f=37)
-   -   Еще раз о шеллах в картинках (https://forum.antichat.xyz/showthread.php?t=46077)

Helios 05.08.2007 02:46

Еще раз о шеллах в картинках
 
Читал мануал по пхп с комментариями, наткнулся на один пост, который дал повод для размышления.

Автор использует этот скрипт для подгонки всех подгружаемых изображений:

PHP код:

<?php
class picture
{
        var 
$save_dir;                     //where file will be saved
        
var $filename="spacer.gif";        //default file name initially 
        
var $error_message="";             //string to be output if neccesary
        
var $width;                        //height of final image
        
var $height;                       //width of final image

        
function picture($save_directory$file_array$max_width$max_height)
        {
                
$this->save_dir $save_directory;                
                
$this->width =    $max_width;
                
$this->height =   $max_height;

                
//--change filename to time - make it unique
                
$temp_filename $file_array['name'];
                
$ext explode('.',$temp_filename);
                
$ext $ext[count($ext)-1];
                
$temp_filename time().".".$ext;

                
//--check that it's a jpeg or gif
                
if (preg_match('/^(gif|jpe?g)$/',$ext)) { 
                        
// resize in proportion
                        
list($width_orig$height_orig) = getimagesize($file_array['tmp_name']);
                        if (
$this->width && ($width_orig $height_orig)) {
                                
$this->width = ($this->height $height_orig) * $width_orig;
                        } else {
                                
$this->height = ($this->width $width_orig) * $height_orig;
                        }

                        
$image_p imagecreatetruecolor($this->width$this->height);                        

                        
//handle gifs and jpegs separately
                        
if($ext=='gif'){
                            
$image imagecreatefromgif($file_array['tmp_name']);                            
                            
imagecopyresampled($image_p$image0000$this->width$this->height$width_orig$height_orig);
                            
imagegif($image_p$this->save_dir.$temp_filename80);
                        }
                        else
                        {
                            
$image imagecreatefromjpeg($file_array['tmp_name']);                             
                            
imagecopyresampled($image_p$image0000$this->width$this->height$width_orig$height_orig);                            
                            
imagejpeg($image_p$this->save_dir.$temp_filename80);
                        }

                        
imagedestroy($image_p);
                        
imagedestroy($image);

                        
$this->filename=$temp_filename;

                }else{
                        
$this->error_message.="<br> file is not a jpeg or gif picture <br>";
                }
        }
}

Но чем не способ фильтровать полученные файлы?
Проблема только одна: для работы требуется поддержка GD в пхп, но в данный момент на большинстве хостингов она есть.

Вот набросанный за пару минут класс для фильтрации картинок:

PHP код:

<?php
/**
 * Класс для проверки изображений
 *
 */
class SecureImage
{
    
/**
     * Картинка
     * @var resource
     */
    
private $img null;
    
    
/**
     * Данные о картинке
     * @var array
     */
    
private $data null;
    
    
/**
     * Тип изображения
     * @var string
     */
    
private $type null;

    
/**
     * Конструктор класса
     * 
     * @param string $s_patch Папка для сохранения картинки
     */
    
public function __construct($image_data)
    {
        
$this->data $image_data;
    }
    
    
/**
     * Деструктор класса
     */
    
public function __destruct()
    {
        if (
$this->img)
        {
            
imagedestroy($this->img); // освобождаем память
        
}
    }
    
    
/**
     * Проверка изображения
     * 
     * @param array $image Массив с данными о загруженом файле из $_FILES
     * @return boolean Результат проверки
     */
    
public function check()
    {
        
$ext explode('.',$this->data['name']);
        
$ext trim(strtolower($ext[count($ext)-1]));
        
        switch (
$ext)
        {
            case 
'gif':
                
$this->img = @imagecreatefromgif($image['tmp_name']);
                
$this->type 'gif';
                break;
            
            case 
'jpeg':
            case 
'jpg':
                
$this->img = @imagecreatefromjpeg($image['tmp_name']);
                
$this->type 'jpg';
                break;
            
            case 
'png':
                
$this->img = @imagecreatefrompng($image['tmp_name']);
                
$this->type 'png';
                break;
        }
        
        if (
$this->img)
        {
            return 
true// и правда, картинка
        
}
        else
        {
            return 
false;// шелл батькович
        
}
    }
    
    
/**
     * Созранение изображения
     *
     * @param string $patch Путь для сохранения
     * @return boolean Результат сохранения
     */
    
public function save($patch)
    {
        if (!
$this->img) { return false; }
        switch (
$this->type)
        {
            case 
'gif':
                return 
imagegif($this->img$patch); // на случай, если прав на запись в указанном месте нет
                
break;
            
            case 
'jpg':
                return 
imagejpeg($this->img$patch);
                break;
            
            case 
'png':
                return 
imagepng($this->img$patch);
                break;
            
            default:
                return 
false;
                break;
        }
    }
    
    
/**
     * Возвращает расширение для картинки
     */
    
public function getExtension()
    {
        return 
$this->type;
    }
}

Вот пример его использования:

PHP код:

$img = new SecureImage($_FILES['some_image']);
if (
$img->check())
{
    
// и правда, картинка - продолжаем.
    
$img->save('/path/to/images/my_image.' $img->getExtension());
}
else
{
    
// shell, как он есть, или ошибка в картинке


Недостаток в том, что поддерживаются только gif, jpeg и png. Хотя аватарок в psd я нигде и не видел...

В общем, хочу узнать ваше мнение

Isis 05.08.2007 03:22

Как тебе отобразаятся изображения в .psd формате?
Бразуер предлагает скачать файл, но он никак не отобразится как картинка..
.psd файл вроде - исходник изображения в фотошопе...

inv 05.08.2007 03:48

А что если переименовать jpg в png ?(сорец не смотрел)
Форматов изображений очень много

A110ut 05.08.2007 04:36

ждем обещаного в ирц мегатру кода by Z

ps: Isis, было бы желание, а написать модуль для отображения какой либо графики не проблема

Helios 05.08.2007 12:12

Гема в irc доказывал, что проверка содержимого не состоятельна, т.к. благодаря специфике форматов изображений можно вставить нужный код в различные коментарии, etc в тело картинки.

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

И сохраняет GD, соответственно, только графическую информацию, т.е. вставки шеллкода в различных полях идут лесом.

Вот этим кодом преобразовал файл с встроенным куда только можно кодом <?php phpinfo(); ?> (image.jpg)
PHP код:

$im imagecreatefromjpeg('image.jpg');
imagejpeg($im'newimage.jpg'); 

После сохранения были вырезаны все мета данные, и размер избражения изменился:
image.jpg: 3.75 кб
newimage.jpg: 2.33 кб

На выходе имеем "чистую" картинку, что и требовалось.

nerezus 05.08.2007 13:03

А можно просто не трахать мозг и не проверять файлы с именами *.png, *.jpeg, *.jpg, *.gif вообще.

A110ut 05.08.2007 15:26

да собственно никто етого делать и не заставляет. просто пример как можно поиздевается с ГД. сели не уверен в отсутствии локального инклуда в скриптах, то можно перестраховаться таким способом. хотя в етом случае можно разводить демагогию по поводу "ты хyевый программер если предполагаешь саму возможность ошибки".
в крайнем случае, всегда можно оправдать подобные телодвижения довольно неслабым уменьшением размера полученной картинки =) кстати, если не ошибаюсь на nnm используется что-то подобное.

gemaglabin 05.08.2007 18:59

Я не знал что библиотека gd режет все лишнее поэтому вот окончательный код имхо.Правда если мы имеем дело с залитием например видео то wmv не прописан в майм тайпах апача по умолчанию и поэтому файл shell.php.wmv будет интерпретироваться именно как php , так что проверка по расширению имхо наилучшая.

http://underwater.itdefence.ru/safe_upload.txt

nerezus 05.08.2007 19:08

Цитата:

http://underwater.itdefence.ru/safe_upload.txt
А зачем такие сложности?
Ну допустим у тебя шелл внутри картинки. И что с того?
Я еще понимаю, можно что из-за кривых bb-кодов(человеческий фактор) допустить дыру, но вот из-за инклюдов....

gemaglabin 05.08.2007 19:34

Нер я тоже не понимаю как люди допускают ошибки типа инклуда но ведь даже очень хорошие программисты ошибались.х3


Время: 14:37