>
Сентябрь 2017
Пн Вт Ср Чт Пт Сб Вс
« Авг    
 123
45678910
11121314151617
18192021222324
252627282930  

Как эксплуатировать уязвимость PHP OBJECT INJECTION

Уязвимости связанная с преобразованием непроверенных сериализованных данных в представление PHP, они же unserialize-баг, все еще актуальны. Более того, проведенное мной исследование встроенных классов PHP показало, что возможны и новые, более универсальные
способы эксплуатации, использующие уязвимости самого интерпретатора.

PHP OBJECT INJECTION

В 2009 году небезызвестный Стефан Эссер на конференции Power of Community в Сеуле выступил с исследованием Shocking News in PHP Exploitation, где, помимо прочего, выявил возможные сценарии атак, когда пользовательские данные попадают в функцию unserialize(). Можно сказать,
что именно тогда появился новый термин PHP Object Injection, обозначающий уязвимость, позволяющую внедрять произвольные объекты PHP в контекст веб-приложения. Уязвимость позволяет проводить множество атак: от XSS до выполнения произвольного кода, в зависимости от структуры объектов уязвимого приложения.

Сериализованные данные после преобразования в объект PHP могут изменить рабочий процесс приложения с помощью так называемых магических методов. Например, если у класса определен магический метод __get(), то он будет вызываться каждый раз, когда у объекта запрашивается несуществующее свойство. При эксплуатации PHP Object Injection наиболее полезны методы __wakeup() и __destruct(): первый вызывается при десериализации объекта, второй — при выгрузке объекта, то есть при завершении работы скрипта. Оба метода вызываются автоматически, без необходимости проводить какие-либо операции над объектом.

В сложных современных веб-приложениях без объектноориентированного подхода просто не обойтись, поэтому очень часто можно встретить деструкторы классов, которые выполняют действия для выгрузки объекта. Например, класс взаимодействия с базой данных закрывает соединение, класс кеша может удалять временные файлы. Именно в деструкторах таится главная опасность для разработчиков, которые зачастую не учитывают, что при десериализации возможна подмена свойств объекта на произвольные значения. Многие популярные веб-приложения были затронуты
PHP Object Injection, в их числе Invision Power Board, Joomla и vBulletin.

В последней версии vBulletin я обнаружил любопытный unserialize(). Он показал, что полезными могут оказаться не только __wakeup() и __destruct(), все зависит от того, какие данные ожидает веб-приложение после десериализации данных. И более того, необязательно ориентироваться только на собственные классы приложения, ведь есть и внутренние классы PHP, речь о которых пойдет ниже.

VBULLETIN

В плане безопасности популярный форум vBulletin знал лучшие годы. В пятой версии «вобла» еще дальше ушла от простого форума и стала громоздким комьюнити-комбайном. Ради праздного интереса я открыл папку core (которая, к слову, не защищена .htaccess), где в инклудах обнаружил исходники Apache log4php. Данный фреймворк — удобный инструмент логирования в PHP и используется в таких проектах, как SugarCRM, vtiger и CMS Made Simple. Но если в этих веб-приложениях от log4php остался только основной функционал, то в vBulletin обнаружился полный код фреймворка, в том числе доступная из веба папка с примерами использования логфреймворка. Один из скриптов оказался крайне любопытным: при обращении к нему на порту
4242 запускался сервер, который при получении данных пытался их десериализовать. Так как полезных магических методов в log4php найти не удалось, было решено обратиться к классам PHP. С помощью следующего скрипта я получил список всех магических методов в объявленных классах:

Список получился объемным, но, как оказалось, почти все классы не позволяли сериализацию либо были бесполезными. Внимание привлек класс SoapClient и его метод __call(), который вызывается, если попытаться вызвать несуществующий метод. Это как раз то, что нужно, ведь в уязвимом скрипте после преобразования данных в объект вызывался метод getRootLogger(). Класс SoapClient имеет множество свойств, а при вызове несуществующего метода он позволяет отправлять SOAP-запросы на произвольные адреса. Уже интересно, посмотрим, что можно из этого выжать.

XXE через unserialize в Joomla

XXE через unserialize в Joomla

SOAPCLIENT

Конструктор класса SoapClient принимает два аргумента: адрес WSDL-документа в формате XML, описывающий SOAP интерфейс, а также массив опций. Если передать в качестве $wsdl значение NULL, то объект будет инициализирован в non-WSDL режиме. Проблема в том, что при режиме с WSDL-документом класс не предусматривает нормальной сериализации свойств, а вот с non-WSDL все в порядке. Поэтому остается один вариант с $wsdl=null и ограниченным набором опций. Но даже с тем, что было доступно, получилось довольно много. Начнем с банальной XSS’ки, конструируем следующий объект SoapClient:

Контролируемый нами скрипт api.php отдает HTTP-ответ
с кодом 404:

Вместо статус-сообщения «Not Found» api.php отправляет произвольную строку, SoapClient видит код 404, генерирует исключение SoapFault, сообщая о том, что удаленный ресурс не найден, и возвращает нашу строку в тело ответа.

Работа класса SoapClient

Работа класса SoapClient

Одна из возможностей SoapClient — локальное кеширование WSDL-документа. Хотя это не помогло бы эксплуатации PHP Object Injection в vBulletin, все же стало интересно, как это делает SoapClient. Оказалось, что документ сохраняется без всяких проверок соответствия пути директиве конфигурации PHP open_basedir, которая запрещает файловые операции вне указанного каталога:

Итак, нужно было что-то более интересное, чем просто XSS. Почему бы не XXE, ведь SOAP работает с XML? И действительно, SoapClient был уязвим перед внедрением внешних XML-сущностей, даже несмотря на то, что при попытке парсинга DOCTYPE сообщал, что он не поддерживается! Дело в том, что исключение вызывалось уже после обработки DTD, а в используемом XML-парсере LibXML опция обработки внешних сущностей включена по умолчанию. Никакого вывода сущностей добиться не удалось, однако помогло замечательное исследование реализации XXE через внешние каналы связи моих коллег Алексея Осипова и Тимура Юнусова. Техника позволяет отправлять содержимое файла через HTTP-запросы прямо в запрашиваемом пути. А вместе с разнообразными PHP-обработчиками схем удалось добиться чтения любых файлов.
В этом помог враппер php:// и фильтр base64:

Итак, эксплуатация PHP Object Injection через внутренний класс PHP оказалась успешной. Помимо vBulletin, данный вектор будет работать в Joomla <=3.0.3, где через unserialize() возможна SQL-инъекция и удаление произвольной директории.

Схема реализации XSS через SoapClient

Схема реализации XSS через SoapClient

Вполне очевидно, что не всегда можно встретить вызов метода на десериализованном объекте, и, к сожалению, в классах PHP нет ни одного деструктора, который брал бы из свойства объект и пытался выполнить у него какой-либо метод. Если обратиться к популярным компонентам, то одним из самых подходящих будет шаблонизатор Smarty. В нем можно встретить следующий код:

Если поместить в свойство handler наш объект SoapClient, то операции над объектом в коде веб-приложения не потребуются и XXE будет проэксплуатирована автоматически через метод __destruct().

WHAT’S NEXT?

В PHP 5.5 намечается нововведение в функции unserialize(), а именно второй аргумент, который позволит разработчикам запретить обработку объектов либо указать белый список разрешенных. В настоящее время используются регулярные выражения, которые зачастую можно легко обойти, либо данные не проверяются вовсе. Например, в Invision Power Board <= 3.3.4 была вот такая смешная проверка:

В строке проверяются первые два символа: если это «a:», то есть сериализованный массив, то строка попадает в unserialize(). Однако атакующему ничто не мешает отправить массив объектов, что приведет к обходу проверки.

Говоря о будущем PHP Object Injection, стоит рассказать о PHP-фреймворке следующего поколения под именем Phalcon, который становится все более популярным у вебразработчиков. Весь его код написан на чистом C, что делает его самым быстрым PHP-фреймворком. Phalcon реализован в качестве расширения PHP, соответственно, требует компиляции и включения в конфигурацию PHP. При этом все классы фреймворка становятся доступными в контексте веб-приложения без каких-либо инклудов внешних файлов. Если представить shared-хостинг, у которого Phalcon включен для всех пользователей по умолчанию, то очевидно, что это позволит использовать классы фреймворка через unserialize(), даже если уязвимое веб-приложение написано не на его базе. Я решил проверить, возможна ли эксплуатация unserialize() через классы Phalcon, и оказалось — очень даже просто!

PHALCON

Получив магические методы из всех классов фреймворка, я не нашел ни одного деструктора, но обнаружил один__wakeup():

Данный код получает из protected-свойства _path путь и открывает его функцией fopen() в режиме, передающемся в свойстве _options. С помощью данного кода можно открыть тысячи файлов и забить все дескрипторы, но это неинтересно. Но что, если поместить в _path объект? При вызове fopen() он будет преобразован в строку, за что отвечает магический метод __toString(). А вот этот метод Phalcon использует очень широко. Я не буду описывать все внутренности фреймворка, скажу
лишь, что в одном из __toString() удалось добиться инициализации произвольных объектов и вызова любых методов. Уже на этом этапе можно подсунуть наш SoapClient и провести XXE, но RCE всегда лучше! Пробежавшись по исходникам на предмет вызова функции phalcon_require  (инклудит файлы так же, как и require в PHP), я обнаружил класс PhalconMvcViewEnginePhp, в котором метод render позволяет инклудить произвольные файлы. Таким образом, через __wakeup() удалось вызвать __toString, а через него — подключение произвольных файлов.

RCE с помощью классов фреймворка Phalcon

RCE с помощью классов фреймворка Phalcon

PHP Object Injection все еще жив и будет жить. Вместе с «безопасной» версией unserialize() в PHP 5.5 появится много новыхклассов, и, возможно, не без уязвимостей. Так что смотрим в будущее!

Ссылки:

PHP Object Injection на OWASP: bit.ly/15vbvAW
Shocking News in PHP Exploitation: bit.ly/11mcvHy
Магические методы PHP: bit.ly/172anb
Apache log4php: bit.ly/aF7jHG
XXE Out-of-Band Data Retrieval: bit.ly/12pyfWb

Share Button
[Всего голосов: 3    Средний: 5/5]

Вам может быть интересно также:

Last updated by at .

1 comment to Как эксплуатировать уязвимость PHP OBJECT INJECTION

Leave a Reply

You can use these HTML tags

<a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">