Защита от внедрения 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, первая секция, а потом интерпретатор дальше просто не идёт. Будет дальше ход хакера или нет, он не проинтерпретируется.
Остаётся открытым вопрос как этот самый код внедрить в нужное место, «после заголовка»
А не проще заливать картинки в папку, в которой запрещена обработка php?
Комментарий для kurapov.name:
Это же просто совсем. Код что ли написать? :)
Комментарий для aktuba:
Есть масса уязвимостей при которых удаётся выполнить только локальный код. Что-то вроде:
$file = ’pages/’ . $_GET[’page’];
if (is_file($file)) include $file;
При этом мы можем залить на такой хостинг картинку в коде и подключить её через указание somepage.php?page=../../userimages/hack.jpg
Комментарий для Евгения Степанищева:
Да, для меня это не тривиально.. Или это вне зависимости от формата можно где-то с десятого-двадцатого символа просто врезать произвольный текст?
Комментарий для kurapov.name:
Примерно такой алгоритм, ага.
Ну давайте теперь и в видео файлы вставлять PHP код, и в текстовые. Лучший метод защиты, это настроить сервер так, чтобы нельзя было запускать такой вредоносный код.
Комментарий для Евгения Степанищева:
Подскажете как настроить сервер таким образом? И обратите внимание на этот вот мой коментарий: http://bolknote.ru/all/3703#n35672
Правильно ли я понимаю, что практически любой сайт, на котором можно заливать картинки, потенциально уязвим? Если мы просто используем стандартные функции php для работы с графикой и файлами).
Комментарий для Василий Топоров:
Все зависит от реализации и настроек сервера.
Способов взломать много, нужно смотреть конкретный пример.
Комментарий для Василий Топоров:
Нет, конечно. Всё зависит от сочетания факторов. Например, см. мой комментарий выше: http://bolknote.ru/all/3703#n35672 Если есть возможность залить какие-то файлы и такой промах со стороны программиста — уязвимость есть. Или может быть некорректно настроен Апач (там некоторые настройки по-умолчанию могут дать уязвимость).
Я правильно понял, что эта защита от двух разных но схожих дыр?
Комментарий для masterspammer.livejournal.com:
Да, правильно.
<html>
Комментарий для НЕГЕНГ:
Ещё один тупой.
Спасибо автору за статью. Метод интересный ) Сам столкнулся с такой проблемой, но решить ее хочу на уровне веб сервера. Если с Apache все более-менее понятно (там можно использовать настройки .htaccess), то как быть с Nginx? Кто-нибудь писал конфигурацию для запрета выполнения кода из определенного каталога?
Комментарий для Авакян Овсеп:
Написать ему там пустой location.