Жаропонижающие средства для детей назначаются педиатром. Но бывают ситуации неотложной помощи при лихорадке, когда ребенку нужно дать лекарство немедленно. Тогда родители берут на себя ответственность и применяют жаропонижающие препараты. Что разрешено давать детям грудного возраста? Чем можно сбить температуру у детей постарше? Какие лекарства самые безопасные?
В текущем месяце багокопатели не хотят нас баловать новыми громкими эксплойтами в популярных приложениях. Конечно, опубликовано множество advisory в продуктах известных фирм, но очень малое их количество содержит удобоваримые PoC-коды. В нашем обзоре я постарался собрать самые значимые и полные уязвимости из описанных в последнее время, так что устраивайся поудобнее и наслаждайся чтением.
Уязвимость PHP при обработке HTTP Head-запросов Brief3 марта некий Адам Иванюк обнаружил интересную особенность в интерпретаторе PHP, который не совсем корректно обрабатывает HEAD-запросы. Данную уязвимость исследователь назвал «HTTP HEAD method trick in php scripts».
Многие кодеры разрабатывают свои PHP-скрипты, надеясь, что все записанные в них инструкции успешно выполнятся, не прервавшись где-нибудь посередине (особенно в коротких скриптах). Так и происходит, если скрипт запрашивается конечным пользователем с помощью методов GET, POST, PUT.
Но тебе должно быть известно, что существуют и другие HTTP-методы - например, HEAD. Как раз-таки при обработке этого метода в PHP и может возникнуть дыра в безопасности.
Смотрим один из исходников интерпретатора: ./main/SAPI.c, линия 315:
if (SG(request_info).request_method &&
!strcmp(SG(request_info).request_method, "HEAD"))
{
SG(request_info).headers_only = 1;
...
Когда поступают какие-либо данные, выполняется функция php_ub_body_write. Дальше смотрим main/output.c, линия 699:
if (SG(request_info).headers_only) {
if(SG(headers_sent))
{
return 0;
}
php_header(TSRMLS_C);
zend_bailout();
}
Здесь видно, что при первом выводе на экран и при использовании метода HEAD функция zend_bailout прерывает работу скрипта.
ExploitТеперь давай обратимся к этому скрипту с помощью метода HEAD:
Как и следовало ожидать, наша гостевая книга остановит свое выполнение на строчке «echo $data;», таким образом файл book.txt просто-напросто обнулится.
Данный пример носит скорее деструктивный характер. Во втором примере мы сможем обойти авторизацию в примитивной админке:
В этом скрипте при заходе обычными методами устанавливается административная переменная в сессии. Затем, если пользователь ввел неправильный пароль, эта переменная обнуляется и пользователь не становится админом.
Если мы обратимся к админке через HEAD, ее выполнение прервется на куске кода с «echo», таким образом административная переменная не обнулится, и мы сможем спокойно бродить по закрытой части приложения. Здесь надо учесть, что в большинстве веб-серверов значение буферизации вывода установлено равным 4096 байт, так что в рабочем примере нам может понадобиться строка "A long string contains about 4090 characters".
Exploit- PHP
Здесь массив $check содержит наши POST-данные, а переменная $locked - это обфусцированная с помощью функции str_rot13() сериализованная строка, которая полностью находится под нашим контролем.
На этом месте стоит сделать небольшое отступление для тех, кто не читал соответствующие статьи в ][, и кратко рассказать о баге, проявляющемся в волшебных методах PHP. Итак, в PHP версии 5 появилась базовая концепция ООПпрограммирования: конструктор и деструктор. Конструктор реализуется с помощью метода «__construct», а деструктор - с помощью метода «__destruct». По окончании своей работы и при вызове через функцию unserialize() каждый объект выполняет свой собственный __ destruct-метод, если он прописан в коде.
Теперь вернемся к нашему фреймворку и посмотрим на деструктор App-класса из файла./libs/configure.php:
function __destruct()
{
if ($this->__cache)
{
$core = App::core("cake");
unset($this->__paths);
Cache::write("dir_map", array_fi lter($this->__paths),
"cake_core ");
Cache::write("fi le_map", array_fi lter($this->__map),
"cake_core ");
Cache::write("object_map", $this->__objects,
"cake_core ");
}
}Из приведенного кода можно понять, что данный метод может быть скомпрометирован путем записи произвольных значений в объект Cache. Наиболее интересный ключ для взлома - это ‘file_map’. Он управляет связями между классами и соответствующими PHP-файлами, а также используется для подгрузки дополнительных классов во время выполнения скрипта.
Реальный код для загрузки классов выглядит немного сложнее, но все это сводится к следующему коду из метода __load внутри класса App:
Бинго! Путем подмены переменной $file мы сможем проинклудить свой собственный PHP-код! Причем это будет самый настоящий Remote File Inclusion баг - таким образом, нам не понадобятся никакие дополнительные ухищрения с загрузкой локальных файлов на сервер. Однако автор найденной уязвимости предлагает LFI-вариант эксплуатации этой дырки, потому что CakePHP использует базирующийся на файлах локальный кэш, который находится в сериализированной форме в известной взломщику директории.
ExploitВ качестве небольшого PoC для генерации ядовитой сериализованной строки felix предлагает следующий код:
Конечно, предварительно ты должен проинклудить необходимые классы из CakePHP. Существует также и полнофункциональный эксплойт на Питоне, найти который ты сможешь по адресу malloc.im/burnedcake.py .
Данный сплойт должен работать в каждом приложении, построенном на CakePHP, использующем POST-формы с security-токенами, и в котором не изменено стандартное расположение файлов кэша. По дефолту эксплойт выводит на экран конфиг базы данных, другие полезности легко добавляются путем измененения встроенного PHP-пэйлоада.
Targets- CakePHP getState("fi lter_order_dir");
$fi lter_order = JFilterInput::clean($fi lter_order, "cmd");
$fi lter_order_dir =
JFilterInput::clean($fi lter_order_dir, "word");
// We need to get a list of all
// weblinks in the given category
$query = "SELECT *" .
" FROM #__weblinks" .
" WHERE catid = ". (int) $this->_id.
" AND published = 1" .
" AND archived = 0".
" ORDER BY ". $fi lter_order ."".
$fi lter_order_dir .", ordering";
return $query;
}Здесь видно, что переменные $filter_order и $filter_order_dir не проходят проверку на строгое соответствие операторам SQL, проверка идет лишь путем использования стандартного метода clean из класса JFilterInput:
- CakePHP getState("fi lter_order_dir");