Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Общие вопросы > PHP в src y <IMG>: насколько опасно?


Автор: Dmitry_177 27.1.2008, 20:05
не так давно узнал что в тег <img> в src можно не только файл картинки писать, а например php-скрипт который генерирует картинку.. Так фот у меня возник вопрос в плане безопасности.. а если пользователь будет загружать файл картинки, он же может выбрать файл скрипта и тогда может случиться мало чего приятного... Как такого можно избежать? Можно проверять расширение файла.. Вот интересно, а если он php расширение сменит например на jpg, то скрипт выполнится?

Автор: GeneralElectric 27.1.2008, 20:17
Цитата(Dmitry_177 @  27.1.2008,  20:05 Найти цитируемый пост)
 и тогда может случиться мало чего приятного... 

Чего именно? И почему нельзя загружать файл скрипта?

Цитата(Dmitry_177 @  27.1.2008,  20:05 Найти цитируемый пост)
Вот интересно, а если он php расширение сменит например на jpg, то скрипт выполнится? 

какой скоипт?

ты не мог бы свои фантазии описывать более конкретно? Не в виде "сменить шило на мыло", а с конкретными именами файлов и видимыми опаснстями.

Автор: Dmitry_177 27.1.2008, 20:27
ОК.. Есть форма для загрузки картинок, после загрузки эти картинки отображаются в <IMG>.. Вот я и предположил, если загрузить не картинку(*.jpg, *.gif, *.png) а php-скрипт(*.php), так вот по идее он выполнится, а это уже дыра в безопасности.. Чтобы этого не произошло, можно проверять расширение загружаемых файлов, т.е. файлы *.php НЕ загружать.. Но тут тоже можно попробовать обойти это... Написать скрипт, сохранить с расширением как *.jpg, тогда файл проверку на расширение пройдет и загрузится на сервер.. А вот при отображении, если в этом файле не картинка а скрипт, выполнится ли этот скрипт???

Автор: flashaa 27.1.2008, 21:28
Скрипт с расширением жпг выполнится как скрипт, только если в настройке сервера прописано обрабатывать  файлы жпг как php-скрипты. Короче говоря, не выполнится.

Автор: Sannis 27.1.2008, 22:29
Другое дело, что содержимое загружаемых изображений(и вообще любого отображаемого в браузере фала) хорошо бы проверить на наличие html-кода, при отображении некоторых видов изображений в браузере выполняется этот код, в том числе и яваскрипт, а это уже возможность XSS. Пример из IP.B:
Код

    function check_xss_infile()
    {
        // HTML added inside an inline file is not good in IE...
        
        $fh = fopen( $this->saved_upload_name, 'rb' );
        
        $file_check = fread( $fh, 512 );
        
        fclose( $fh );
        
        if( !$file_check )
        {
            @unlink( $this->saved_upload_name );
            $this->error_no = 5;
            return;
        }
        
        # Thanks to Nicolas Grekas from comments at www.splitbrain.org for helping to identify all vulnerable HTML tags
        
        else if( preg_match( "#<script|<html|<head|<title|<body|<pre|<table|<a\s+href|<img|<plaintext|<cross\-domain\-policy#si", $file_check ) )
        {
            @unlink( $this->saved_upload_name );
            $this->error_no = 5;
            return;
        }
    }

Автор: Dmitry_177 27.1.2008, 23:24
ок, подскажите тогда пожалуйста, какие файлы не следует загружать... Я для себя составлю списочек smile Пока он такой:

.php
.phtml
.phtm
.php3
.html
.htm
.pl

Автор: GeneralElectric 28.1.2008, 00:12
надо составлять список не тех файлов, которые нельзя загружать, а тех, которые можно.

Автор: SelenIT 28.1.2008, 00:18
Цитата(GeneralElectric @  27.1.2008,  23:19 Найти цитируемый пост)
Sannis, это шутка? 

GeneralElectric, похоже, не шутка. Есть у IE такая подлая черта - http://msdn2.microsoft.com/en-us/library/ms775148(VS.85).aspx. Пример Sannisа, судя по всему, ссылается http://www.splitbrain.org/blog/2007-02/12-internet_explorer_facilitates_cross_site_scripting.

Цитата(GeneralElectric @  28.1.2008,  00:12 Найти цитируемый пост)
надо составлять список не тех файлов, которые нельзя загружать, а тех, которые можно. 

Абсолютно верно (например, для картинок - .gif, .png, .jpg, .jpeg, можно еще .bmp). Для пущей уверенности можно на всякий случай проверять их ф-цией Sannisа. 




Автор: Dmitry_177 28.1.2008, 00:19
Цитата

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

ок, тогда вот так:

.jpg
.jpeg
.gif
.bmp
.png

есть еще какие-нибудь расширения картинок отображаемые <IMG>?

Автор: skyboy 28.1.2008, 00:49
Цитата(Dmitry_177 @  27.1.2008,  23:19 Найти цитируемый пост)
есть еще какие-нибудь расширения картинок отображаемые <IMG>? 

зависит от браузера.
к примеру, текущий вариант FireFox http://www.google.com/search?hl=en&sa=X&oi=spell&resnum=0&ct=result&cd=1&q=firefox+svg&spell=1 с http://en.wikipedia.org/wiki/Scalable_Vector_Graphics, некоторые браузеры работают с http://en.wikipedia.org/wiki/Vector_Markup_Language(Internet Explorer). Не делать же полный список всех возможных графических типов? Проще определить, что "я, мол, поддерживаю только то-то, то-то и то-то; остальное идет лесом".

Автор: Sannis 28.1.2008, 00:54
Цитата(GeneralElectric @  27.1.2008,  23:19 Найти цитируемый пост)
Sannis, это шутка?

Нет, вполне серьёзно. Мало кто может сфабриковать картинку для такой уязвимости, но пренебрегать ей не стоит.

Автор: Golda 28.1.2008, 01:26
Sannis, SelenIT, спасибо за интересную информацию

Автор: SelenIT 28.1.2008, 01:47
Sannis, кстати, я тут задумался: а как можно использовать эту уязвимость? Скрипт в картинке ведь сработает, только если вызвать ее напрямую (в крайнем случае, через iframe/object), со стандартным <img src="..."> ничего страшного не грозит. Единственное, что приходит на ум - это сделать какую-нибудь пакость от имени авторизованного юзера (вроде http://phpclub.ru/talk/showthread.php?threadid=54325&rand=45, причем предложенная там защита по рефереру в этом случае как раз не поможет). Но такой случай, имхо, сам по себе довольно экзотичен, к тому же вскользь упомянутое там же "железное" решение (с уникальным идентификатором формы в сессии) не позволит и этого...

Но вообще, конечно, приведенный код (как и само поведение IE, правда) отдает каким-то шаманством. Ну почему '<a href=...' заставляет картинку отображаться как html, а '<a id=... href=...' - уже нет? Кто знает, нет ли еще подобных "волшебных" комбинаций?..

Автор: bars80080 28.1.2008, 10:42
меня по-поводу шаманства преследует такая мысль:

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

(как при производстве памяти: штампуют стандартно 1024Мб, битых 300Мб, они дорезают до стандарта в 512 - вот и результат)

отсюда и проблемы в разнице стандартов

п.с. шутка, хотя кто его знает...

Автор: Sannis 28.1.2008, 22:19
SelenIT, довольно просто. http://www.securitylab.ru/contest/291564.php, как раз годичной давности.

Автор: SelenIT 28.1.2008, 22:43
Sannis, спасибо за ссылку!

Автор: skyboy 30.1.2008, 10:26
значит, при загрузке картинку придется обработать(приводимый в статье по ссылке Sannis говорится о растяжении/сжатии, но я бы предложил просто открыть и сохранить со сменой формата). и проблем не будет. по крайней мере с IE. так?

Автор: Dmitry_177 2.2.2008, 18:43
Странно, а почему выполняется такое условие?

Код

$bnfiletype = substr(strrchr($_FILES['bnfile']['name'], "."), 1);
if(empty($bnfiletype) || $bnfiletype != "png" ||
   $bnfiletype != "jpg" || $bnfiletype != "jpeg" ||
   $bnfiletype != "gif" || $bnfiletype != "bmp")
   {
     echo "неизвестное расширение файла";
   }


загружаю *.jpg пишет что "неизвестное расширение файла", выводил echo $bnfiletype; все правильно - пишется "jpg".. непонятно..

Автор: SelenIT 2.2.2008, 18:50
Dmitry_177, ничего странного. Условие ИЛИ выполняется, когда хотя бы один из вариантов истинен, а "jpg" действительно не равно "png" smile

Вообще я бы рекомендовал делать проверку через !in_array(<массив допустимых расширений>) - и короче, и нагляднее.

Автор: Dmitry_177 2.2.2008, 18:58
по идее $bnfiletype != "jpg" не должно же выполняться, т.к. равно этому.. отсюда все условие по идее должно было бы НЕ выполниться..

Посмотрю как через массив сделать, может переделаю..

Автор: SelenIT 2.2.2008, 19:07
Dmitry_177, до него просто не доходит, потому что условие ИЛИ, а if в PHP "короткозамкнутый" - обнаружив первое сработавшее условие, дальше просто не проверяет. В данном случае первым сработавшим, и, тем самым, последним проверенным условием оказывается $bnfiletype != "png". Но дело не в этом, а в неправильной логике - по смыслу тут нужно условие И.

Автор: Dmitry_177 2.2.2008, 19:14
в качестве саморазвития smile

чтобы мое условие заработало, так правильно будет?

Код

$bnfiletype = substr(strrchr($_FILES['bnfile']['name'], "."), 1);
if(empty($bnfiletype) || ($bnfiletype != "png" &&
   $bnfiletype != "jpg" && $bnfiletype != "jpeg" &&
   $bnfiletype != "gif" && $bnfiletype != "bmp"))
   {
     echo "неизвестное расширение файла";
   }



через массив, вот так?

Код

$bnfiletype = substr(strrchr($_FILES['bnfile']['name'], "."), 1);
if(!in_array($bnfiletype, array("png", "jpg", "jpeg", "gif", "bmp")))
  {
    echo "неизвестное расширение файла";
  }

Автор: Dmitry_177 2.2.2008, 19:47
и еще ИМХО, лучше перевести $bnfiletype в нижний регистр..

Код

$bnfiletype = strtolower(substr(strrchr($_FILES['bnfile']['name'], "."), 1));

Автор: SelenIT 2.2.2008, 20:36
Цитата(Dmitry_177 @  2.2.2008,  19:14 Найти цитируемый пост)
так правильно будет?

По-моему, да - для обоих вариантов...

Автор: Dmitry_177 2.2.2008, 20:40
по поводу функции strtolower, в книге пишут что нужно локали настраивать, иначе с крилицей будет неправильно работать.. Но т.к. в расширении файлов нету крилицы, я думаю ничего настраивать ненадо..

Автор: SelenIT 2.2.2008, 20:41
Цитата(Dmitry_177 @  2.2.2008,  20:40 Найти цитируемый пост)
я думаю ничего настраивать ненадо

Для данного случая справедливо. Но вообще желательно работать на правильной локали.

Автор: flashaa 28.2.2008, 22:56
Цитата из ссылки Sannis



Цитата

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


Получается, если я создам 1.jpg с текстом <script>alert('a');</script> и открою его в ИЕ, то выскочит алерт? Что-то он не выскакивает.
К тому же никто не обратил внимания на комментарий к статье, в котором говорится, что примеры  XSS через картинку повторить не удалось.
То ли эта уязвимость была закрыта (пробовал в ИЕ6) и не так уж важна, толи это вообще утка какая-то.

Автор: skyboy 29.2.2008, 00:34
в статье приводятся "внешние ссылки". так вот, http://ha.ckers.org/xss.html из них намного информативнее указанной статьи на securitylab.

Автор: Sannis 29.2.2008, 00:55
Цитата(skyboy @  29.2.2008,  00:34 Найти цитируемый пост)
в статье приводятся "внешние ссылки". так вот, одна из них намного информативнее указанной статьи на securitylab.

Насколько я понял, в этой статье описаны разные XSS через HTML-код страницы. Я же выше говорил о том, что содержимое самого файла изображения может трактоваться IE как код smile

А о методах XSS и защиты от него, я надеюсь, разработчики знают...

Автор: flashaa 29.2.2008, 12:25
Цитата(skyboy @  29.2.2008,  00:34 Найти цитируемый пост)
в статье приводятся "внешние ссылки". так вот, одна из них намного информативнее указанной статьи на securitylab.

Посмотрел ссылку. Но к моему вопросу она не имеет отношения.
Мой вопрос был таков: если файл картинки .jpg содержит html-код, который выполняется в браузере при открытии этой картинки, то можно привести пример или объяснить такой случай? 
В cтатье securitylab говорилось именно про картинки. Про различные вариации html-кода со скриптами я вопросов не имею.
Так вот сама идея интерпретации картинки .jpg как скрипта - маразматична. Поэтому я усомнился в этом и пытаюсь уточнить, правда ли это. 
Допустим у меня есть файл image.jpg. Я пишу в него <script>alert('aa');</script> и открываю в браузере ИЕ6. Почему то у меня отображается красный крестик, но нет никакого скрипта? 
Ведь
Цитата

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

Автор: Glip 29.2.2008, 12:31
кроме проверки по расширению файла, можно еще попробовать
http://ru2.php.net/manual/en/function.getimagesize.php
данная функция кроме размера возвращает еще и тип файла (jpeg, png, ....)

Автор: Sannis 29.2.2008, 17:56
flashaa, вы же ставите время от времени заплатки, не так ли? Сейчас, думается мне, Микрософт уже закрыл это на уровне браузера...

Автор: flashaa 29.2.2008, 18:41
Sannis, ну и тогда следует принять к сведенью то, что данный баг давно устарел. В связи с его маразматичностью, думаю он устарел очень и очень давно. Ещё до выхода ИЕ7. А статья автора относится к желтой прессе )

Автор: Sannis 29.2.2008, 22:28
flashaa, не спорю smile

А статья автора уже более чем годичной давности, тогда ещё не закрыли .

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)