Ядовитая ОБЕРТКА: как врапперы РНР могут быть использованы для атаки на веб-приложения

Гибкость языка программирования добавляет удобства разработчикам, но и открывает новые векторы для атаки. Разработчики РНР часто используют так называемые wrapper’ы и даже не подозревают, что это может привести к обходу встроенных в приложение фильтров безопасности и, к примеру, позволить выполнить на сервере произвольный код. О врапперах, их особенностях и угрозах, с ними связанных, и пойдет сегодня речь.

INTRО

В этой статье мы сначала кратко рассмотрим, что представляют собой РНР wrappers и как они могут быть полезны программистам. Затем разберем их особенности, которые позволяют обходить встроенные в приложение фильтры безопасности и реализовывать атаки.

WRAPPERS

В РНР есть такое понятие, как потоки (Streams), которые появились в интерпретаторе начиная с версии 4.3.0. Это абстрактный слой для работы с файлами, сетью, сжатыми данными и другими ресурсами, использующими единый набор функций. В простейшем определении, поток —это ресурс, имеющий «потокообразное» поведение.

Помимо тривиального пути к файлу могут быть использованы так называемые врапперы (wrapper). Лучший способ пояснить, что это такое, —привести несколько примеров. Итак, с использованием врапперов через все ту же функцию fopen становится возможным:

— скачивать файлы с РТР: ftp://user:password@10.0.0.1/pub/file.txt;

— обращаться, если доступ к ним ограничен, к server-status/server-info по IP: http://127.0.0.1/server-status;

— обращаться к файловым дескрипторам, открытым на чтение (РНР >= 5.3.6): php://fd/XXX;

— и даже выполнить команды OS (если установлено расширение expect): expect://ls.

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

Если происходит запись данных, то и в этом случае врапперы также могут расширить возможности многих функций. Например, функция сору() поддерживает врапперы в обоих своих аргументах, и если во втором аргументе используется обертка php://output, то копируемый файл отправляется в выходной буфер. Таким образом, функция сору() позволяет не только копировать файлы, но и читать их.

Аналогичным образом можно использовать функцию file_put_ contents и любую другую функцию, поддерживающую враппер в режиме write.

В версии PHP 5.3.6 появился враппер php://fd, который предоставляет прямой доступ к файловым дескрипторам. Если РНР установлен как модуль Apachea, враппер php://fd дает возможность записывать произвольные данные в access_log/error_log (обычно права на этих файлах 644, и напрямую в них может писать только root).

Надо сказать, что в РНР довольно много встроенных врапперов, но при этом можно создавать и регистрировать собственные обертки, используя функцию stream_wrapper_register. Некоторые врапперы имеют недокументированные особенности, позволяющие более эффективно эксплуатировать уязвимости веб-приложений. Именно эти особенности мы сегодня и рассмотрим.

ЧТО ТАИТ В СЕБЕ ZIP?

В РНР для работы с этим форматом удобно использовать модуль zip.

В Linux-системах модуль zip становится доступным, если РНР скомпилирован с опцией—enable-zip. Архивировать можно не только отдельные файлы, но и целые каталоги; чтобы сохранялась структура каталога, в именах файлов, добавляемых в архив, допустимо использовать слеш /. Еще одной важной особенностью модуля zip является возможность обрабатывать файлы с произвольным именем: главное, чтобы содержимое файла было корректно сформированным zip-архивом.

После того как zip-архив создан, с помощью враппера zip:// можно напрямую обращаться к файлам внутри архива. Возможность помещать в архив файлы, в именах которых присутствует слеш, позволяет эксплуатировать уязвимости типа Remote File Include, при отсутствии null-байта. Bспользование врапперов http://, ftp://, data:// ограничивается директивой allow_url_include, а использованию null-байта при инклуде локальных файлов скорей всего помешает директива magic_quotes_gpc. И может даже показаться, что при allow_url_include=Off и magic_quotes_gpc=On проэксплуатировать уязвимость никаким образом не получится. Но есть еще один способ!

Если нет возможности создать нужный файл с помощью РНР-функции, то можно использовать временные файлы, которые создает РНР при загрузке контента через HTML-форму. Путь до временного файла можно узнать из phpinfo(). Важно отметить, что директива allow_url_fopen не ограничивает применение обертки zip://.

WHERE IS MY DATA://?

Враппер data://с момента своего появления привлекал внимание специалистов по веб-безопасности. В официальной документации этот враппер предлагают использовать в очень ограниченной форме.

Mediatype может либо полностью отсутствовать, либо быть заполнен произвольными значениями. Эту особенность враппера можно использовать для обхода проверок и фильтров. Например, в популярном скрипте TimThumb vl.x есть такой фильтр:

В PHP существует такая функция, как stream_get_meta_data(). Согласно официальной документации, она извлекает метаданные из потоков и файловых указателей. При этом в возвращаемом массиве содержатся элементы с четко заданными ключами, и задача добавления в этот массив новых элементов выглядит на первый взгляд весьма проблематичной. Но с помощью враппера data:// можно довольно просто манипулировать этим массивом!

ХОЛОДНЫЙ КОМПРЕСС

Согласно документации, обертка compress.zlib:// позволяет распаковывать gz-архивы. Если с помощью этого враппера обрабатывать данные, не являющиеся zlib-архивом, то данные возвращаются без изменений.

Например, прочитать файл /etc/hosts можно таким образом:

— readfile( compress.zlib:///etc/hosts );

«Очень полезно!» —подумаешь ты. Сейчас будет круче. Если ты хоть немного программировал на РНР для веба, то наверняка знаком с функцией prase_url(). Напомню, эта функция осуществляет парсинг URL. И тут есть один интересный момент: на вход функции можно предоставить не только URL, но и строку довольно общего типа:

— print_r(parse_url(

— anysheme://anysite.сот/;http://w?v@1=! ));

Учитывая эту особенность, можно обходить различные проверки и фильтры на основе функции parse_url, используя многофункциональные врапперы.

ЭКСПЛУАТАЦИЯ УЯЗВИМОСТЕЙ В TIMTHUMB V1.X

TimThumb —это популярный скрипт для работы с изображениями, который используется во многих темах и плагинах для WordPress. В августе 2011 года в скрипте TimThumb v 1.32 была найдена критическая уязвимость, позволяющая загружать на атакуемый сервер вместо изображений с доверенных хостов файлы с РНР-кодом. Почти в одночасье в публичном доступе появилась адвизори, подробно рассказывающая об эксплуатации этой уязвимости. Суть уязвимости заключалась в том, что-скрипт некорректно проводил проверку URL по списку доверенных хостов, с которых возможно было загрузить изображения. Для обхода фильтров, к примеру по доверенному хосту blogger.com, предлагалось зарегистрировать домен четвертого уровня, содержащего в себе URL доверенного хоста, например blogger.com.attacker.com, и загружать файлы с этого домена. Этим способом можно было проэксплуатировать уязвимость до версии 1.32 (revision 142). Но более новые версии оказались также уязвимы.

Таким образом, с помощью враппера data:// можно обойти все фильтры и создать файл в директории кеша с произвольным содержимым.Или с помощью враппера compress.zlib:// скопировать в кеш локальный файл. Профит в том, что к файлам из кеша можно обращаться напрямую, в результате чего добиться RCE через запись шелла с помощью враппера data, а также получить содержимое локальных файлов, используя compress.zlib.

ВМЕСТО ЗАКЛЮЧЕНИЯ

Очевидно, что встроенные в РНР врапперы дают большие возможности при эксплуатации уязвимостей типа File Manipulation. Но при этом стоит отметить, что даже самые простые проверки на основе функций file_exists, is_file, filesize не дадут воспользоваться врапперами. Также при установленном патче Suhosin по умолчанию невозможно использовать врапперы в инклудах, даже если директива allow_url_include имеет значение On.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

четырнадцать − 12 =