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

Форум АНТИЧАТ (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

George767 06.08.2007 10:21

Я на своих проектах юзаю следующий алгоритм
1 Проверка расширения
2 Проверка Mime типа
3 Проверка типа вообще (через exif_imagetype)
4 Проба ширины и высоты - имеют ли числовые значения
Далее можно пере-рендерить картинку как уже написал Helios:
$im = imagecreatefromjpeg('image.jpg');
imagejpeg($im, 'newimage.jpg', 100);

Если рендерить и менять ширину/высоту по какой-то причине нельзя, то можно проверсти вот такую проверочку содержимого картинки

<meta http-equiv="content-type" content="text/html; charset=windows-1251">
<?php

$result_of_scan="";

$uploaded_img="resized.jpg";
$fh=fopen($uploaded_img, 'r');
$contents_of_uploaded_img=fread($fh, filesize($uploaded_img));
fclose($fh);

$list_of_potential_xss=array('javascript', 'vbscript', 'expression', 'applet', 'blink', 'link', 'style', 'script', 'embed',

'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'title', 'base', 'onabort', 'onactivate',

'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate',

'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce',

'oncellchange', 'onchange', 'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavailable',

'ondatasetchanged', 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave',

'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterchange', 'onfinish', 'onfocus', 'onfocusin',

'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown',

'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onmove',

'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset', 'onresize', 'onresizeend',

'onresizestart', 'onrowenter', 'onrowexit', 'onrowsdelete', 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange',

'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload', 'input', 'form', 'post','input', 'echo', 'background',

'alert', 'img src', 'table', 'Content-Type', 'charset', 'http-equiv', 'meta', 'body', 'document', 'style', 'cookie',

'false', 'true', 'delete', 'UTF-7', 'UTF-8', '.html', '.dhtml');


for($x = 0; $x < count($list_of_potential_xss); $x++)
{
preg_match("/".$list_of_potential_xss[$x]."/", $contents_of_uploaded_img, $matches);
if(count($matches) > 0)
{
$result_of_scan="true";
echo "$list_of_potential_xss[$x] - присутсвует<br><br>";
}
else
{
echo "$list_of_potential_xss[$x] - отсутсвует<br><br>";
}
}

if ($result_of_scan==="true")
{
echo ("<b><h1>XSS есть");
}
else
{
echo ("<b><h1>Все чисто");
}

?>

SQLHACK 06.08.2007 10:52

1. Эта проверка идёт лесом. пример тому.
<IMG DYNSRC="javas cript:al ert('XSS')">

2. вроде разговор о шеллах, а чёт похоже на защиту от XSS, если ты имел ввиду XSS то читай первый пост.

А если ты говорил про пхп шелл то за GZIP'еный шелл склееный с картинкой ты тоже не спалишь этим скриптом.

Так что либо дорабатывай, либо забудь об этой защите ;)

George767 06.08.2007 11:10

Цитата:

Сообщение от SQLHACK
1. Эта проверка идёт лесом. пример тому.
<IMG DYNSRC="javas cript:al ert('XSS')">

2. вроде разговор о шеллах, а чёт похоже на защиту от XSS, если ты имел ввиду XSS то читай первый пост.

А если ты говорил про пхп шелл то за GZIP'еный шелл склееный с картинкой ты тоже не спалишь этим скриптом.

Так что либо дорабатывай, либо забудь об этой защите ;)

Эта проверка чисто для экспериментов (хз каких))

В любом случае проще пере-рендерить картинку и весь побочный код идет лесом.

SQLHACK 06.08.2007 11:29

Цитата:

Сообщение от George767
В любом случае проще пере-рендерить картинку и весь побочный код идет лесом.

А ведь есть ещё и технические поля.
Где можно сохранить. Хз как передендеринг, удалит их, или нет.

Helios 06.08.2007 11:53

Цитата:

А ведь есть ещё и технические поля.
Где можно сохранить. Хз как передендеринг, удалит их, или нет.
Как я уже говорил, Gd считывает и сохраняет только графические данные, используемые для построения растра, т.е. все техничесие поля остаются неудел.

SQLHACK 06.08.2007 12:48

сорри не увидел первую страницу разговора. Теперь всё ясно.


Время: 20:56