Защита от внедрения PHP-кода в картинки (JPEG, GIF, PNG)

На «Хабре» всплыла тема атаки, старой как мир — заливаем на сайт картинку, у которой внутри (в поле комментариев) есть ПХП-код, потом всякими трюками этот код запускаем. Валидатор картинок на сайте такую картинку пропускает — это вполне валидная картинка.

Во всех форматах принятых в вебе, есть поле, позволяющее вставить такие данные. В JPEG есть специальные секции APPn и COM, в PNG — iTXt, tEXt и можно создавать произвольные секции, в GIF — блоки расширений, в SVG можно использовать обычный XML-комментарий.

В качестве абсолютного метода защиты на «Хабре» предлагается пропустить картинку через какую-либо графическую программу, чтобы убедиться, что все дополнительные данные исчезли. Мне кажется, плохой способ — медленный, а в случае JPEG это ещё и скажется на качестве.

Можно ещё попробовать вырезать все секции файла, куда можно запихнуть текстовую информацию, но это не спасёт от файлов, где ПХП вставлен прямо в графическую часть, так, чтобы детектор валидности картинки (в ПХП для этого обычно используют getimagesize) не спотыкался на файле.

Мне кажется, я придумал более удачный метод защиты.

В загруженный файл можно добавить первой секцией (сразу после заголовка) свой собственный кусок ПХП-кода с вызовом __halt_compiler эта специальная конструкция останавливает интерпретатор в этой точке и всё остальное содержимое файла дальше не интерпретируется:

# смотрим что внутри файла
bolk@Bolk ~ $ hexdump -Cn128 sample.jpg 
00000000  ff d8 ff e0 00 10 4a 46  49 46 00 01 01 00 00 01  |......JFIF......|
00000010  00 01 00 00 ff fe 00 1a  3c 3f 70 68 70 20 5f 5f  |........<?php __|
00000020  68 61 6c 74 5f 63 6f 6d  70 69 6c 65 72 28 29 3b  |halt_compiler();|
00000030  ff db 00 43 00 02 02 02  02 02 01 02 02 02 02 03  |...C............|
00000040  02 02 03 03 06 04 03 03  03 03 07 05 05 04 06 08  |................|
00000050  07 09 08 08 07 08 08 09  0a 0d 0b 09 0a 0c 0a 08  |................|
00000060  08 0b 0f 0b 0c 0d 0e 0e  0f 0e 09 0b 10 11 10 0e  |................|
00000070  11 0d 0e 0e 0e ff db 00  43 01 02 03 03 03 03 03  |........C.......|

# запускаем
bolk@Bolk ~ $ php sample.jpg
????JFIF??

Т. е. на экран выводится бинарный заголовок JPEG, первая секция, а потом интерпретатор дальше просто не идёт. Будет дальше ход хакера или нет, он не проинтерпретируется.

Поделиться
Отправить
17 комментариев
Artjom Kurapov (kurapov.name) 2012

Остаётся открытым вопрос как этот самый код внедрить в нужное место, «после заголовка»

aktuba 2012

А не проще заливать картинки в папку, в которой запрещена обработка php?

Евгений Степанищев (bolknote.ru) 2012

Комментарий для kurapov.name:

Остаётся открытым вопрос как этот самый код внедрить в нужное место, «после заголовка»

Это же просто совсем. Код что ли написать? :)

Евгений Степанищев (bolknote.ru) 2012

Комментарий для aktuba:

А не проще заливать картинки в папку, в которой запрещена обработка php?

Есть масса уязвимостей при которых удаётся выполнить только локальный код. Что-то вроде:

$file = ’pages/’ . $_GET[’page’];
if (is_file($file)) include $file;

При этом мы можем залить на такой хостинг картинку в коде и подключить её через указание somepage.php?page=../../userimages/hack.jpg

Artjom Kurapov (kurapov.name) 2012

Комментарий для Евгения Степанищева:

Это же просто совсем. Код что ли написать? :)

Да, для меня это не тривиально.. Или это вне зависимости от формата можно где-то с десятого-двадцатого символа просто врезать произвольный текст?

Евгений Степанищев (bolknote.ru) 2012

Комментарий для kurapov.name:

Примерно такой алгоритм, ага.

ibnteo.klava.org/ 2012

Ну давайте теперь и в видео файлы вставлять PHP код, и в текстовые. Лучший метод защиты, это настроить сервер так, чтобы нельзя было запускать такой вредоносный код.

Евгений Степанищев (bolknote.ru) 2012

Комментарий для Евгения Степанищева:

Подскажете как настроить сервер таким образом? И обратите внимание на этот вот мой коментарий: http://bolknote.ru/all/3703#n35672

Василий Топоров 2012

Правильно ли я понимаю, что практически любой сайт, на котором можно заливать картинки, потенциально уязвим? Если мы просто используем стандартные функции php для работы с графикой и файлами).

Karsonito 2012

Комментарий для Василий Топоров:

Все зависит от реализации и настроек сервера.
Способов взломать много, нужно смотреть конкретный пример.

Евгений Степанищев (bolknote.ru) 2012

Комментарий для Василий Топоров:

Правильно ли я понимаю, что практически любой сайт, на котором можно заливать картинки, потенциально уязвим? Если мы просто используем стандартные функции php для работы с графикой и файлами).

Нет, конечно. Всё зависит от сочетания факторов. Например, см. мой комментарий выше: http://bolknote.ru/all/3703#n35672 Если есть возможность залить какие-то файлы и такой промах со стороны программиста — уязвимость есть. Или может быть некорректно настроен Апач (там некоторые настройки по-умолчанию могут дать уязвимость).

masterspammer (masterspammer.livejournal.com) 2012

Я правильно понял, что эта защита от двух разных но схожих дыр?

  1. запуск кода на выполнение вебсервером (если его настройки удаётся обмануть).
  1. включение кода картинки как модуля/библиотеки (если удалось залить «злой» код только в виде картинки).
Евгений Степанищев (bolknote.ru) 2012

Комментарий для masterspammer.livejournal.com:

Да, правильно.

НЕГЕНГ 2013

<html>

Евгений Степанищев (bolknote.ru) 2013

Комментарий для НЕГЕНГ:

Ещё один тупой.

Авакян Овсеп 2014

Спасибо автору за статью. Метод интересный ) Сам столкнулся с такой проблемой, но решить ее хочу на уровне веб сервера. Если с Apache все более-менее понятно (там можно использовать настройки .htaccess), то как быть с Nginx? Кто-нибудь писал конфигурацию для запрета выполнения кода из определенного каталога?

Евгений Степанищев (bolknote.ru) 2014

Комментарий для Авакян Овсеп:

Написать ему там пустой location.

Популярное