Обзор эксплойтов Крис Касперски Хакер, номер #099, стр. 052 После предновогодней лавины дыр, хлынувшей сквозь весь спектр программных и аппаратных продуктов, сотрясающей их, словно неожиданно проснувшейся вулкан, считавшийся давно потухшим, в январе-феврале наступило ленивое затишье. Не считая очередной порции дыр в IE, Office и Mozillа, никаких новых потрясений не последовало, и счет открытых уязвимостей пошел на единицы, о самых интересных из которых я и собираюсь рассказать. Удаленный BSOD на Intel 2200BG 802.11 Brief Очередная дыра в драйверах беспроводных устройств, обнаруженная хакером по имени Breno Silva Pinto из компании sekure.org, показывает, насколько еще сыры и небезопасны беспроводные технологии. Сценарий атаки вполне типичен: на жертву обрушивается мощный шквал разобщенных (disassociation) пакетов. Пакеты схватывает драйвер и складывает их в кучу для дальнейшей обработки, в процессе которой модифицируются глобальные (для драйвера) структуры данных, защищаемые критическими секциями и прочими средствами синхронизации. Но небрежно реализованная синхронизация (а когда она реализовалась иначе?) привела к серьезным дефектам, и часть структур данных осталась незащищенной, в результате чего появилась угроза их разрушения. Если в процессе обработки одного пакета приходит другой, структуры данных превращаются в мешанину и дальнейшее поведение драйвера становится непредсказуемым. Как правило, дело заканчивается голубым экраном смерти (то есть отказом в обслуживании). И хотя существует возможность передать зловредный shell-код и захватить управление ЦП на уровне нулевого кольца, пока она остается только в теории. Подробности об уязвимости - на www.securityfocus.com/bid/22260. Targets Уязвимость подтверждена в родном Intel-драйвере w29n51.sys версии 9.0.3.9, который датирован 9 декабря 2005 года и управляет беспроводными устройствами, смонтированными на адаптерах типа Mini-PCI, часто встречающихся в ноутбуках. Другие версии драйвера не проверялись, но существуют достаточно веские основания утверждать, что подобные дыры есть и в них. Exploit Исходный текст exploit'а, написанного все тем же Breno Silva Pinto (bsilva@secure.org), можно скачать с www.milw0rm.com/exploits/3224, а если он (сервер) лежит (убит, висит), то с www.securityfocus.com/data/vulnerabilities/exploits/22260.c. Solution На момент написания этих строк компания Intel не выпустила никакого обновления и даже не уведомила пользователей о грозящей им опасности, что вообще беспредел: www.intel.com/network/connectivity/products/wireless/prowireless_mobile.htm. А потому единственным возможным решением становится отключение беспроводных устройств (исправить дефект синхронизации патчем двоичного файла нереально). Sun Java - переполнение буфера в библиотеки времени исполнения Brief Java, изначально позиционируемая как абсолютно безопасная среда программирования, таковой, увы, не оказалась, и от Java-апплетов можно ожидать всего чего угодно (на них не только игры, но и вирусы пишут). Самое неприятное, что, помимо изъянов в архитектуре безопасности, дефекты обнаруживаются и в самом фундаменте: компиляторе, библиотеке времени исполнения и т.д. Кодокопатель, работающий на компанию Zero Day Initiative (www.zerodayinitiative.com) (наряду с TippingPoint (www.tippingpoint.com) — подразделением корпорации 3Com, окучивающим вопросы безопасности), обнаружил грубую ошибку в штатном gif-обработчике: если ширина валидного изображения выставлена в ноль, то библиотека времени исполнения выделяет указанное в заголовке количество байт, которое может и не совпадать с фактическим. В результате всего этого наступает классическое переполнение, допускающее возможность передачи управления на shell-код, содержащийся в этом же самом изображении. За подробностями обращайся к отчету компании Zero Day Initiative: www.zerodayinitiative.com/advisories/ZDI-07-005.html. Targets Уязвимость обнаружена в SDK и JRE версий вплоть до 1.4.2 (включая более ранние) и JDK/JRE версии 5.0 с обновлением 9, а также в продуктах сторонних компаний, построенных на их основе, в частности в Avaya Interactive Response версий 1.3 и 2.0. Exploit Исходный код боевого exploit'а, созданного хакером по кличке luoluo (luoluonet@hotmail.com) в тесной кооперации с членами команды Ph4nt0m Security Team (www.ph4nt0m.org), лежит на Security Focus'e: www.securityfocus.com/data/vulnerabilities/exploits/JvmGifVulPoc.java. Он несет на своем борту shell-код, запускающий calc.exe, однако после доработки напильником он будет запускать все что угодно, в том числе и backdoor :). Solution Компания Sun уже выпустила обновления для различных версий SDK и JRE, доступные по ссылке http://java.sun.com/javase/downloads/index_jdk5.jsp. С продуктами же сторонних компаний ситуация до сих пор остается туманной, однако, судя по популярности Java, их число должно быть весьма велико, так что дерзай — широкое поле исследований открыто! uTorrent — удаленное переполнение кучи Brief Популярность легендарного Осла (клиента файлообменной сети eDonkey) начинает постепенно слабеть под агрессивным натиском файлообменной сети нового поколения — BitTorrnet (используемой в том числе и для легального распространения дистрибутивов некоторых клонов Linux'а и BSD), одним из клиентов которой и является программа uTorrent (www.utorrent.com). В отличие от Осла, носящего свой хвост всегда с собой, в сети BitTorrnet обмен варезом осуществляется через специальные torrent-файлы, которые, в свою очередь, распространяются через того же Осла или web. Структура torrent-файлов (вместе с принципами работы самой сети) описана на http://en.wikipedia.org/wiki/BitTorrent. Ошибка, допущенная разработчиками uTorrent'а, вполне банальна: копируя данные из полей torrent-файла в динамически выделяемые блоки памяти, они полагаются на авось и никаких проверок не выполняют. В результате этого у хакеров появляется возможность через специальным образом сконструированный torrent-файл захватывать управление узлами, на которых установлены клиенты uTorrent. Уязвимость обнаружена компанией defsec (www.defacedsecurity.com), пославшей свой отчет на Security Focus, где ему был присвоен номер 22530: www.securityfocus.com/bid/22530. Target На данный момент уязвимость подтверждена в версии uTorrent 1.6, более ранние версии не проверялись, но, судя по всему, они также уязвимы. Exploit Исходный текст exploit'а можно нарыть на www.milw0rm.com/exploits/3296; ссылка на Security Focus'e – www.securityfocus.com/data/vulnerabilities/exploits/22533.c - битая и выдает знаменитую ошибку 404. Solution На момент написания этих строк разработчики uTorrent'а никак не отреагировали на сообщение об уязвимости и не выпустили никаких обновлений, поэтому лучшим решением будет отказ от использования uTorrent в пользу других клиентов. Linux Kernel – DoS при обработке ISO9660 Brief Легендарный хакер по кличке LMH (основавший не менее легендарный проект MOKB — Month of Kernel Bugs — http://projects.info-pull.com/mokb, lmh@info-pull.com), известный своими маниакальными замашками, в ноябре 2006 года в особо зверской форме изнасиловал ядро Linux'а, подсунув ему садистским образом испорченный образ ISO9660 (основная файловая система лазерных дисков, поверх которой обычно «натянута» Джульетта, поддерживающая длинные имена и другие фишки). Таким образом он погрузил ядро в состояние глубокой медитации, граничащей с нирваной, частным случаем которой является бесконечный цикл. В практическом плане это означает, что любой пользователь, обладающий правами монтирования дисков (или при задействованном автоматическом монтировании cd-rom) может устроить тотальный DoS, что не есть хорошо, особенно в случае сервера, для которого перезагрузка без правильного завершения работы зачастую сопровождается значительными потерями данных. Это довольно древняя ошибка (где мы, а где 2006 год?), подробнее о которой можно прочитать на http://projects.info-pull.com/mokb/MOKB-05-11-2006.html, но исправить ее удалось лишь 30 января 2007 года: http://rhn.redhat.com/errata/RHSA-2007-0014.html. Количество уязвимых узлов достаточно велико, так что, прежде чем смонтировать iso-образ, полученный из ненадежных источников, следует как минимум сохранить все несохраненные данные. Targets Дефект в ядре версии 2.6.18; более древние ядра не тестировались, однако есть все основания полагать, что эта ошибка присутствует и в них. Exploit Испорченный iso-образ (сжатый архиватором bzip и занимающий всего 696 Кб) лежит на http://projects.info-pull.com/mokb/bug-files/MOKB-25-11-2006.img.bz2. Чтобы его смонтировать без записи на CD-R/-RW, следует выполнить следующие команды: $ bunzip2 MOKB-05-11-2006.iso.bz2 $ mount -t iso9660 -o loop MOKB-05-11-2006.iso /media/test $ ls /media/test Solution Патчи для RedHat можно скачать с http://rhn.redhat.com/errata/RHSA-2007-0014.html, а для SuSE – с www.securityfocus.com/bid/20920/solution. Что же касается остальных поставщиков, то они, похоже, не считают эту ошибку критической и не спешат выкладывать обновления. Full disclose История эта была бы очень смешной, если не была бы такой грустной. Файловая система — это фундамент любой оси, отвечающий за сохранность наших данных. Помимо архитектуры самой файловой системы, необходимо иметь доброкачественный драйвер, сохраняющий работоспособность при любых разрушениях, в противном случае даже небольшой дефект может привести к потере всего дискового тома, размеры которого в наши дни измеряются сотнями гектар! Исследовательская программа, развернутая LMH, обнаружила огромное количество ошибок в драйверах практически всех файловых систем: ex2/3fs, gfs2, ntfs, ReiserFS (Linux); UFS (FreeBSD/Solaris), HFS+ (Mac OS) и т.д., что наводит на грустные размышления по поводу надежности того, на чем мы сидим. За подробностями обращайтесь к блогу «Kernel Fun — Kernel bugs and madness» (http://kernelfun.blogspot.com/search/label/fsfuzzer). Для экспериментов использовалась бесплатная утилита fsfuzzer (http://projects.info-pull.com/mokb/fsfuzzer-0.6-lmh.tgz), генерирующая испорченные образы различных файловых систем, на которых изучается реакция соответствующего драйвера. Кто-то может заметить, что драйвер вовсе не подписывался переваривать серьезные искажения базовых структур данных и что в реальной жизни такие разрушения практически никогда не возникают. На самом деле, драйвер файловой системы обязан сохранять работоспособность при любых разрушениях, вытаскивая максимум уцелевшей информации. Отказ монтировать разрушенный том вполне допустим (хотя и крайне нежелателен), а вот за выпадение в бесконечный цикл нужно расстреливать на месте без права переселения душ. Собственно говоря, этой статьей я хотел подтолкнуть своих сородичей - хакеров - к активным действиям в отношении файловых систем, ведь чем больше ошибок будет выявлено в ходе садистских издевательств, тем меньше их останется в реальной жизни. К слову сказать, потеря данных под Linux не редкость, и мне довольно часто приходится чинить испорченные дисковые тома в hex-редакторе (именно в hex-, а не в disk-, поскольку в Linux/BSD, в отличие от Windows, с диском можно работать как с файлом). И любой нормальный hex-редактор легко переварит /dev/xxx. Сейчас кто-то может встрять и сказать, что и в Windows диск можно открывать функцией CreateFile и работать с ним как с файлом. Теоретически, то есть на концептуально-архитектурном уровне, безусловно, да, но вот на житейско-практическом - ни фига подобного!!! Прежде всего, штатными средствами Windows нельзя демонтировать диск, и соответствующую утилиту придется писать самостоятельно. Во-вторых, методика работы с файлами и устройствами под Windows довольно существенно различается, и hex-редактор просто не сможет работать с диском, если только такая возможность в него не закладывалась изначально. Ладно, все это лирика. Переходим к практике. Разбираться, что именно искажено в образе, сгенерированном утилитой fsfuzzer, лениво и бесполезно, поэтому будем плясать от печки, то есть от исходных текстов ядра, а точнее, даже не всего ядра, а драйвера файловой системы ISO9660. Их можно найти, например, на http://lxr.linux.no/source/fs/isofs (хотя любой нормальный дистрибутив должен поставляться вместе с исходными текстами, так что можно обойтись и без интернета). Как именно локализовать ошибку в драйвере? В нашем случае это делается очень просто: монтируем испорченный образ, пытаемся войти в корневой каталог, и ядро разряжается пулеметной очередью грязных ругательств, выплевываемых в бесконечном цикле в файл /proc/kmsg (наверняка, при этом использовались вращающиеся стволы с продувкой сжатым воздухом для лучшего охлаждения). Короче, на ядрах семейства 2.6.х мы должны увидеть вот это: Сообщения, выплевываемые ядром в файл /proc/kmsg при просмотре дефективного ISO9660-образа __find_get_block_slow() failed. block=18446744073457893405, b_blocknr=4043309084 b_state=0x00000020, b_size=2048 device blocksize: 2048 __find_get_block_slow() failed. block=18446744073457893405, b_blocknr=4043309084 b_state=0x00000020, b_size=2048 device blocksize: 2048 __find_get_block_slow() failed. block=18446744073457893405, b_blocknr=4043309084 b_state=0x00000020, b_size=2048 device blocksize: 2048 __find_get_block_slow() failed. block=18446744073457893405, b_blocknr=4043309084 b_state=0x00000020, b_size=2048 device blocksize: 2048 __find_get_block_slow() failed. block=18446744073457893405, b_blocknr=4043309084 b_state=0x00000020, b_size=2048 device blocksize: 2048 __find_get_block_slow() failed. block=18446744073457893405, b_blocknr=4043309084 b_state=0x00000020, b_size=2048 device blocksize: 2048 __find_get_block_slow() failed. block=18446744073457893405, b_blocknr=4043309084 b_state=0x00000020, b_size=2048 device blocksize: 2048 Кстати говоря, ядра семейства 2.4 ведут себя гораздо спокойнее, лаконично сообщая о невозможности монтажа испорченного образа из-за ошибки чтения блока i-node. Фрагмент файла /proc/kmsg – реакция ядра версии 2.4.27 на дефективный ISO9660-образ <6>loop: loaded (max 8 devices) <7>ISO 9660 Extensions: Microsoft Joliet Level 3 <6>attempt to access beyond end of device <6>07:00: rw=0, want=3670074, limit=12698 <4>ISOFS: unable to read i-node block <7>ISOFS: changing to secondary root Таким образом, мы знаем, что ошибка сидит в ядре 2.6.x и сосредоточена где-то в окрестностях функции __find_get_block_slow(), имя которой ядро и выводит в /proc/kmsg. Смотрим в исходные тексты: Ключевой фрагмент функции __find_get_block_slow(), вызываемой в бесконечном цикле из ядра 2.6.х при чтении дефективного ISO9660-образа 386 __find_get_block_slow(struct block_device *bdev, sector_t block) 387 { *** [skip] [skip] [skip] [skip] [skip] [skip] [skip] 402 spin_lock(&bd_mapping->private_lock); 403 if (!page_has_buffers(page)) 404 goto out_unlock; 405 head = page_buffers(page); 406 bh = head; 407 do { 408 if (bh->b_blocknr == block) { 409 ret = bh; 410 get_bh(bh); 411 goto out_unlock; 412 } 413 if (!buffer_mapped(bh)) 414 all_mapped = 0; // <------< 415 bh = bh->b_this_page; 416 } while (bh != head); 417 418 /* we might be here because some of the buffers on this page are 419 * not mapped. This is due to various races between 420 * file io on the block device and getblk. It gets dealt with 421 * elsewhere, don't buffer_error if we had some unmapped buffers 422 */ 423 if (all_mapped) { 424 printk("__find_get_block_slow() failed. " 425 "block=%llu, b_blocknr=%llu\n", 426 (unsigned long long)block, 427 (unsigned long long)bh->b_blocknr); 428 printk("b_state=0x%08lx, b_size=%zu\n", 429 bh->b_state, bh->b_size); 430 printk("device blocksize: %d\n", 1 << bd_inode->i_blkbits); 431 } 432 out_unlock: 433 spin_unlock(&bd_mapping->private_lock); 434 page_cache_release(page); 435 out: 436 return ret; 437 } Сразу же ищем вызовы функции printk (записывающей ругательные сообщения в файл /proc/kmsg), находящиеся практически в самом конце __find_get_block_slow и предваренные следующим комментарием: «We might be here because some of the buffers on this page are not mapped. This is due to various races between file io on the block device and getblk. It gets dealt with elsewhere, don't buffer_error if we had some unmapped buffers» («мы могли бы очутиться здесь, если один или несколько буферов на этой странице не были бы спроецированы в память, что случилось по причине «гонки потоков» на операциях ввода/вывода блочного устройства и функции getblk. Если мы имеем несколько неспроецированных буферов, то ошибка находится черт знает где, но только не в функции buffer_error»). Судя по комментарию, причина кроется в некорректно реализованной синхронизации потоков, что «подтверждается» отчетами, опубликованными целым рядом компаний, специализирующихся на безопасности. Неполный перечень ссылок на них можно найти на http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2006-5757. В действительности же, все эти компании просто перепечатали исходный комментарий, не проводя никаких дополнительных исследований. Но комментарий — это не Коран и совсем не божественное откровение, в которое можно только верить, но нельзя проверить. Простейший эксперимент опровергает теорию гонки, поскольку ошибка проявляется как на однопроцессорных, так и на многопроцессорных системах, и уж тем более было бы странно, если бы потоки гнались в этом месте. Просматривая заплатку для ядра от Fabio M. Di Nitto (fabbione@ubuntu.com), мы видим следующий комментарий в diff-файле: http://security.ubuntu.com/ubuntu/pool/main/l/linux-source-2.6.12/linux-source-2.6.12_2.6.12-10.45.diff.gz Комментарий в заплатке, исправляющей множественные ошибки в драйвере файловой системы ISO9660 + * [SECURITY] Fix a bunch of range checks in ISO9660 fs: + - Add patch stolen-from-head_iso9660-flaws.dpatch. + (CAN-2005-0815) «Исправления множества проверок на принадлежность числа к диапазону в ISO9660 fs» — и никаких гонок потоков! Незалатанная версия драйвера файловой системы ISO9660 манипулировала ключевыми структурами данных, забывая о необходимости проверки корректности содержащихся в них значений. И вот результат! Теперь этот недостаток исправлен, и сами исправления настолько обширны, что здесь попросту не хватит места, чтобы привести даже небольшую их часть. Да и какой смысл, когда каждый может заглянуть в diff-файл самостоятельно? Тем более что проверки тривиальны и не несут в себе абсолютно ничего интересного. Обычные рутинные операции повседневных будней программиста. И вот в этих самых буднях концентрация ошибок максимальна. Что поделаешь, однообразная, унылая работа всегда рассеивает внимание… |