ОФИЦИАЛЬНОЕ ОПИСАНИЕ ДЛЯ ПУБЛИЧНОГО РАСПРОСТРАНЕНИЯ IOS Exploitation Techniques An IRM Research White Paper by Gyan Chawdhary Information Risk Management Plc 8th Floor Kings Building Smith Square London SW1P 3JJ Tel: +44 (0)20 7808 6420 Fax: +44 (0)20 7808 6421 [email protected] http://www.irmplc.com Технические приемы эксплуатирования операционных систем IOS Прошло более года с тех пор как Michael Lynn впервые продемонстрировал вполне правдоподобный эксплойт выполнения кода на Cisco IOS на Black Hat 2005. Хотя его презентация получила значительный охват целевых групп в секьюрити-сообществе, очень мало известно об атаке и о технических деталях, которые окружают уязвимость IOS check_heaps(). Данный документ является результатом исследования проведенного администратором информационных ресурсов чтобы проанализировать и понять атаку check_heaps() и ее воздействие на аналогичные встроенные устройства. Более того, она также помогает разработчикам понять специфические проблемы, связанные с безопасностью во встроенных средах и разработкой подавляющих стратегий для аналогичных уязвимостей. Документ прежде всего фокусируется на техниках, разработанных для обхода процесса check_heaps(), который традиционно препятствовал надежному эксплуатированию основанных на памяти переполнений на платформе IOS. Используя встроенные команды IOS, дампы памяти и инструментальные средства “open source” администратор информационных ресурсов смог воссоздать уязвимость в лабораторных условиях. Документ разделен на три секции, которые охватывают вектор атак ICMPv6 источника компоновки, внутренности операционной системы IOS, и в конце концов анализ самой атаки. Уязвимость источника компоновки запросов роутера (маршрутизатора) ICMPv6. Чтобы понять уязвимость check_heaps() нам сначала нужно проанализировать вектор атаки, используемый для эксплойта. Следует отметить, что проблема check_heaps() использованная Линном (Lynn) была в высокой степени зависимой от уязвимости, так как требуется специфическое распределение памяти для того чтобы успешно эксплуатировать данное состояние. Уязвимость, которая использовалась чтобы продемонстрировать атаку находилась в реализации протокола IPv6 ND (Neighbor Discovery) “Обнаружения Соседнего Узла”. Новый стандарт IPv6 представил протокол ND, в основном в качестве замены для того чтобы преодолеть ограничения дизайна и проблемы, ассоциируемые с ARP (протокол разрешения адресов). Протокол ND в первую очередь ответственен за управление всеми взаимодействиями связи между удаленными хостами посредством обмена управляющими сообщениями. Эти сообщения предоставляют данные необходимые для самоконфигурирования хоста и использования управляющих сообщений ICMPv6 для обмена данными. Без особого углубления в дальнейшие детали опций протокола, мы фокусируемся на сообщении запроса роутера ICMPv6 которое формирует главный вектор атаки для уязвимости check_heaps(). Для дальнейшей информации о протоколе ND читателю следует обратится к RFC 2461. Сообщения запроса роутера генерируются когда новый хост инициализируется в сети, для того, чтобы сгенерировать немедленное срабатывание Извещения Роутера. Пакет берет дополнительную (суб-) опцию Type Length Value (Значение Типа Длины), где “Value” является 128-байтным адресом ссылки источника IPv6. Этот адрес используется роутером для определения физического адреса отправляющего хоста для генерирования правильных ответов Извещений Роутера. Уязвимость в частности лежит в обработке этой дополнительной опции, так как области длины и размера опции ссылки источника не проверяются точно программой синтаксического анализа Обнаружения Соседнего Узла, что позволяет буферу внутреннего накопителя (пула) IOS переполняться в рамках области динамической памяти. С точки зрения атакующего, уязвимость довольно-таки уникальная так как размер поля контролирует количество динамической памяти которая должна быть назначена нашему буферу. Было также отмечено что переполнение было переполнением не основанного на строках типа которое разрешало “нулевым” (содержащий код 00h) байтам отправляться в поток данных. Внутренности IOS Для того, чтобы полностью понимать атаку check_heaps() нам необходимо ознакомиться с основной подсистемой IOS и некоторыми лежащими в основе процессами. Процесс check_heaps() и программируемый сторожевой таймер охватываются ниже , так как эти процессы играют критическую роль в обходе процесса check_heaps(). Процесс check_heaps() Так как IOS не использует полную поддержку виртуальной памяти в отличие от большинства современных операционных систем, концепция процесса выделения адресного пространства для единичного активного процесса отсутствует. Это означает, что все процессы делят между собой одну и ту же область памяти и могут модифицировать содержание памяти вне зависимости от привилегий, которые с ними ассоциируются. Более того, вышеупомянутый сценарий также делает крайне трудной возможность отладки и выявления ошибок в программном обеспечении и утечек памяти в подобной среде. В результате, процесс check_heaps() был представлен чтобы преодолеть эти проблемы и обеспечить программистов полезной информацией для отслеживания утечек памяти и признаков переполнения под IOS. Программируемый сторожевой таймер. Для поддержки процесса отладки ошибок и управления ресурсами ЦП, IOS реализует программируемый сторожевой таймер процессов для обнаружения присутствия неотвечающих процессов, чтобы они не блокировали ресурсы ЦП. Когда предусмотрено, что процесс должен запуститься под IOS, планировщик включает программируемый сторожевой таймер для активного процесса. Значение тайм-аута в две секундыиспользуется по умолчанию перед тем как таймер процесса истечет, в момент чего сообщение —SYS-3-CPUHOG“ генерируется роутером. След выполнения события истечения программируемого сторожевого таймера показан на рисунке 1. Code: [B]%SYS-3-CPUHOG: Task ran for 4844 msec (0/0), process = Check heaps, PC = 80475E90.[/B] Рисунок 1: След истечения программируемого сторожевого таймера. Если процесс программируемого сторожевого таймера встречает второе событие истечения, планировщик забирает управление у текущего процесса. Основываясь на различных конфигурациях IOS и уровнях приоритета процессов, процесс либо временно приостанавливается либо просто завершается. Атака IOS check_heaps() Атака, включающая в себя check_heaps() произошла в первую очередь из-за проблем разработки функциональности лога ошибки в check_heaps() и была в дальнейшем возможна в использовании благодаря недостатку поддержки защиты памяти между процессами. Первый из когда-либо известных эксплойтов для демонстрации выполнения основанного на памяти кода под IOS был исследован и разработан FX из Phenoelit. Его техника полагалась на тот факт что атакующий должен загодя получить определенные переменные величины, связанные со структурами управления динамической областью памяти, чтобы наверняка достичь выполнения кода. В основном это выполнялось для того чтобы обойти процесс check_heaps() чтобы он не обнаружил порчу памяти после того, как произошло переполнение, что вызвало бы как результат немедленную перезагрузку роутера, таким образом препятствуя всем попыткам проведения атаки успешного переполнения буфера для выполнения произвольного кода. Дальнейшая информация о его техниках задокументирована в его великолепной статье по эксплуатированию переполнения буфера IOS в публикации Phrack 60 – “Burning the bridge“ (“Сжигая мост”). Как все современные операционные системы, IOS обеспечивает функциональность для записи отладочной информации в случае отказа работы системы используя встроенные возможности записи. Процесс check_heaps() использует эти функции для записи информации, связанной с падением системы после выявления испорченного блока памяти. Далее следует список проверок выполняемых check_heaps() перед перезагрузкой роутера. • Проверить и записать процесс, который вызвал функцию check_heaps() • Запись всех событий связанных с порчей памяти, что включает след отдельного процесса. • Наконец, перезагрузка IOS, основанная на реестре конфигурации переключений, либо в режиме —ROMMON“ или при нормальной конфигурации. Как отмечено выше, первая проверка выполняемая IOS определяет процесс который вызвал то, что check_heaps() пометил порчу памяти. Это выполняется посредством инициализации логической (Булева) переменной которая изначально установлена на ноль. Для простоты, давайте назовем эту переменную “crashing” (аварийной) как уже описано в презентации Линна. Когда процесс check_heaps() инициирует последовательность при отказе, то он проверяет установлена ли эта переменная на неположительное значение перед тем, как передать управление записи информации об отказе и функциям отладки в рамках функциональных возможностей check_heaps(). Если “crashing” уже ранее была установлена на позитивное значение, функция check_heaps() просто возвращается вызывающей программе. Это было реализовано как отказоустойчивый механизм во избежание одновременного отказа двух параллельных процессов, что в противном случае сделало бы сложным выявление и отладку этих состояний ошибки. Как раньше было упомянуто, одна из самых главных мотиваций для обхода процесса check_heaps() была возможность достичь безотказности эксплойта, в то же время сохраняя доступ к системе без отказа работы устройства. С точки зрения атакующего, вышеназванный механизм может быть использован для достижения этого сценария путем установки переменной crashing_already на неположительное значение. В конфигурации по умолчанию, когда процесс check_heaps() выявляет порчу памяти, он пытается мягко отключить роутер. Однако как только переменная crashing_already помечается для выявления происходящего в текущий момент сбоя, каждый отдельный момент check_heaps() просто возвратит логическое значение истины при выявлении переполнения инициированного атакующим. Рисунок 2 показывает технологическую блок-схему процесса check_heaps(). Рисунок 2: Течение процесса check_heaps() Теперь, когда мы знаем каким образом можно обойти check_heaps(), мы можем продемонстрировать вышеупомянутое путем перезаписи флага crashing_already используя следующие две техники: • Перезапись неконтролируемой перестановки указателя-идентификатора • Перезапись связанных списков структуры таймера Ядра Техника неконтролируемой перестановки указателя-идентификатора. Как только процесс check_heaps() всесторонне проверяет указатель-идентификатор хипа —PREVIOUS“ (хип - область динамически распределяемой памяти для структур данных, размер которых не может быть определён до момента исполнения программы) чтобы проконтролировать целостность памяти освобождаемого участка, мы можем перезаписать только вплоть до указателя-идентификатора —NEXT“ в структуре управления хипа. Это предоставляет возможность перезаписать произвольное значение в адресе предоставленном пользователем когда участок памяти несвязный. Используя эту технику атакующий может перезаписать адрес “crashing”_уже в указателе-идентификаторе —NEXT“, что приведет к тому что произвольное ненулевое значение будет записано в переменную когда участок памяти несвязан. Перезапись связанных списков структуры таймера ядра Недавняя инструкция по безопасности Cisco описывает отладку в таймерах операционной системы, которая позволяла выполнение кода на IOS. Во время отладки уязвимости ICMPv6, было отмечено что аналогичные сообщения об ошибках генерировались в связи с проблемами таймера. Одно подобное сообщение об ошибке, сгенерированное аварийно отказавшим устройством было ошибка —SYS-3-MGDTIMER“ которое было в дальнейшем проанализировано. Как показано на рисунке 3, адрес в коде ошибки (0x82FCBB18) является указателем-идентификатором структуры системного таймера, который оставался постоянным во время тестов. Как только это было подтверждено, было сгенерировано несколько триггеров путем перезаписи специфических элементов структуры данных таймера. С использованием этой техники, были собраны и проанализированы дампы отказа, все возвратившие одни и те же сообщения об ошибках , имеющие отношение к порче структуры таймера. Рисунок 3 демонстрирует некоторые из ошибок таймера зафиксированные во время теста. Code: [B] #*Mar 1 00:02:49.515: %SYS-3-MGDTIMER: Uninitialized timer, timer stop, timer = 82FCBB18. #-Process= "IPv6 ND", ipl= 0, pid= 133 #-Traceback= 80477D34 80478E10 817AE1CC 8048F680 80492BC8 #*Mar 1 00:02:54.499: %SCHED-3-UNEXPECTEDTIMER: Unknown timer expiration, timer = 82FCBB18, type 16705. #-Process= "IPv6 ND", ipl= 0, pid= 133 #-Traceback= 817AE1C4 8048F680 80492BC8 #*Mar 1 00:00:39.911: %SYS-3-MGDTIMER: Timer not a leaf, set_exptime, timer = 82FCBB18. #-Process= "IPv6 Input", ipl= 0, pid= 84 #-Traceback= 80477D78 80478500 80478610 817AA414 817AC184 817ACEB4 817B48C4 817B1CCC 817B1FB0 817B18F4 817B13BC 817B8F24 80488 #*Mar 1 00:00:44.895: %SCHED-3-STUCKMTMR: Sleep with expired managed timer 0, time 0xAF64 (00:00:00 ago). #-Process= "IPv6 ND", ipl= 6, pid= 133 #-Traceback= 8047FEFC 804802BC 817AE060 8048F680 80492BC8 #*Mar 1 00:04:42.023: %SCHED-3-UNEXPECTEDTIMER: Unknown timer expiration, timer = 82FCBB18, type 16705. #-Process= "IPv6 ND", ipl= 0, pid= 133 #-Traceback= 817AE1C4 8048F680 80492BC8 #*Mar 1 00:04:47.039: %SYS-3-MGDTIMER: Uninitialized timer, timer stop, timer = 82FCBB18. #-Process= "IPv6 ND", ipl= 0, pid= 133 #-Traceback= 80477D34 80478E10 817AE1CC 8048F680 80492BC8[/B] Рисунок 3: Зафиксированные ошибки таймера. Данные, что окружают указатель-идентификатор таймера были в дальнейшем проанализированы с использованием памяти показа и контекстных команд показа. Дамп памяти выявил (обращайтесь к рисунку 4) то, что эти адреса указывали на одни и те же структуры в памяти, которые наводили на мысли о структуре данных связанного списка таймера IOS. Code: [B]#82FCBB10: 00000000 82FCBB18 .....|;. #82FCBB20: 82D89218 82FCBAE8 00000000 004B4760 .X...|:h.....KG` #82FCBB30: 00014240 00000000 00000000 004B33D8 [email protected] #82FCBB40: 00000000 004B33D8 00000004 00000000 .....K3X........ #82FCBB50: 00000000 00000000 00000000 00000000 ................ #82FCBB60: 00000000 00000000 00000000 00000000 ................ #82FCBB70: 00000000 00000000 00000000 00000000 ................ #82FCBB80: 00000000 00000000 00000000 00000000 ................[/B] Рисунок 4: Дамп памяти показывающий структуру данных связанного списка таймера. Системные таймеры IOS аналогичны реализации таймера UNIX и координируют некоторые специфические процессы в связанном списке. Перезаписав связанный список таймера данными, предоставленными атакующим можно было бы сделать возможным достичь выполнения кода, что было проверено путем манипуляции этими адресами. Было отмечено что четвертый элемент структуры таймера обрабатывался IOS и модифицировался некоторыми функциями таймера. Для того чтобы это проверить, структура была заменена на адрес crashing_already используя уязвимость ICMPv6 в качестве вектора переполнения. Было отмечено что эта структура позднее была обработана IOS что привело к тому что адрес crashing_already изменился на положительное число. Когда процесс check_heaps() определил порчу памяти в связи с нашим переполнением, роутер инициировал процесс “crashing”. Однако так как переменная crashing_already была переписана, после дампа содержания памяти, он продолжил нормальную работу не перезагружая роутер. Скриншот выходных данных консоли роутера прикреплен в приложении A. Следует отметить что эта техника была только лишь использована чтобы продемонстрировать обход процесса check_heaps(). Более того, эти структуры таймера можно использовать путем перезаписи контекстных указателей-идентификаторов и информации обратного вызова чтобы достичь полного выполнения кода; однако детали касательно этого находятся вне рамок этого документа. Заключения Уязвимость check_heaps() в основном имела место благодаря проблемам проектирования (дизайна) и в дальнейшем эксплуатируема благодаря недостатку поддержки защиты памяти между процессами. Многие продавцы встроенных систем все еще полагаются на выбор в пользу производительности и скорости вместо безопасности. По мере того, как все больше и больше “интеллекта” встраивается в потребительские и коммерческие устройства, использующие встроенные операционные системы и программное обеспечение, тем более значительными эти потенциальные уязвимости могут стать. Поэтому, продавцам встроенных систем нужно быть осведомленными насчет потенциальных атак против их систем и того, что многим хакерам наскучило исследовать традиционные операционные системы и они переключились на встроенные устройства в качестве новых для себя испытаний.
Об авторе Gyan Chawdhary является Старшим Консультантом по Безопасности в компании ОАО Information Risk Management Plc (Администратор информационных ресурсов) где он возглавляет Центр Успешности встроенных систем и находится в Европейском Техническом Центре Администраторов информационных ресурсов, Cheltenham, Англия. У Gyan 6 лет опыта консультирования по безопасности в Европе, на Ближнем Востоке и в Азии включая исследование уязвимостей, реверсивное (обратное) проектирование и аудит исходного кода. Он также публично выпустил код эксплойта для уязвимостей PHP и Sendmail. О IRM Компания ОАО Information Risk Management Plc (IRM - Администратор информационных ресурсов) это независимая от продавцов консалтинговая компания по информационному риску, основанная в 1998. IRM стала лидером в оценке рисков со стороны клиента, аудиту технического уровня и в исследовании уязвимостей в безопасности и разработке инструментов безопасности. Головной офис IRM находится в Лондоне с Техническими Центрами в Европе и Азии также как и Региональные офисы на Дальнем Востоке и в Северной Америке. Пожалуйста посетите наш вебсайт www.irmplc.com для дальнейшей информации. Приложение A Code: [B] #attack# #attack# #*Mar 1 00:01:53.043: %SYS-3-MGDTIMER: Parent is a leaf, set_exptime_internal, timer = 82FCBB18. #-Process= "IPv6 Input", ipl= 0, pid= 84 #-Traceback= 80477DBC 80478090 80478508 80478610 817AA414 817AC184 817ACEB4 817B48C4 817B1CCC 817B1FB0 817B18F4 817B13BC 817B8F24 8048F680 80492BC8 #========= Dump bp = 82FC895C ====================== # #82FC885C: 82FC8868 82B24504 82E90FF8 82FC8858 82FC8878 82B244D0 82E90FF8 82FC8868 #82FC887C: 82FC8888 82B2449C 82E90FF8 82FC8878 82FC8898 82B24468 82E90FF8 82FC8888 #82FC889C: 82FC88A8 82B24434 82E90FF8 82FC8898 82FC88B8 82B24400 82E90FF8 82FC88A8 #82FC88BC: 82FC88C8 82B243CC 82E90FF8 82FC88B8 82FC88D8 82B24398 82E90FF8 82FC88C8 #82FC88DC: 82FC88E8 82B24364 82E90FF8 82FC88D8 82FC88F8 82B24330 82E90FF8 82FC88E8 #82FC88FC: 82FC8908 82B242FC 82E90FF8 82FC88F8 82FC8918 82B242C8 82E90FF8 82FC8908 #82FC891C: 82FC8928 82B24294 82E90FF8 82FC8918 82FC8938 82B24260 82E90FF8 82FC8928 #82FC893C: 82FC7EE0 82B24228 82E90FF8 0 0 0 0 FD0110DF #82FC895C: AB1234CD 54 8334B7CC 826282B4 817AA7B8 82FCBBB8 82FC8368 8000191A #82FC897C: 2 0 0 0 0 0 0 40 #82FC899C: 60 700080 5F 1 1 5F 5C 210000 #82FC89BC: 82CE7B2C 49507636 204E4420 7461626C 65000000 82FC8B58 82FCBB58 82FC8B68 #82FC89DC: 82FC8BE8 82FC8C68 82FC8CE8 82FC8D68 82FC8DE8 82FC8E68 82FC8EE8 82FC8F68 #82FC89FC: 82FC8FE8 82FC9068 82FC90E8 82FC9168 82FC91E8 82FC9268 82FC92E8 82FC9368 #82FC8A1C: 82FC93E8 82FC9468 82FC94E8 82FC9568 82FC95E8 82FC9668 82FC96E8 82FC9768 #82FC8A3C: 82FC97E8 82FC9868 82FC98E8 82FC9968 82FC99E8 82FC9A68 82FC9AE8 82FC9B68 #========= Dump bp->next = 82FCBBB8 ====================== # #82FCBAB8: 0 0 0 0 0 0 0 0 #82FCBAD8: 15A3C78B 1 817AA860 82FC8984 0 830FF914 20000001 10001 #82FCBAF8: 2112FFF FE14E6F2 1414141 44444444 44444444 44444444 44444444 44444444 #82FCBB18: 0 82FCBB18 82FCBAE8 828DD61B 0 294E794 14240 0 #82FCBB38: 0 20202020 0 1B998 3 BBBBBBBB CCCCCCCC 80818283 #82FCBB58: 80CBB76 808A8B8C 51515151 52525252 20 828DD684 828DD684 828DD684 #82FCBB78: 828DD684 828DD684 828DD684 828DD684 828DD684 828DD684 828DD684 828DD684 #82FCBB98: 828DD684 828DD684 828DD684 828DD684 828DD684 828DD684 828DD684 FD0111DF #82FCBBB8: AB1234CD FFFFFFFF 0 81DA6944 80487020 82FCBC10 82FC8970 80000018 #82FCBBD8: 1 0 832BDE14 BB8 A2C 82466764 0 0 #82FCBBF8: 0 0 0 0 0 FD0110DF AB1234CD FFFFFFFE #82FCBC18: 0 81DA7020 80484554 82FCC40C 82FCBBCC 800003EA 1 8046650C #82FCBC38: 82FCC434 83460658 0 0 83032FE8 64 77 C000C #82FCBC58: 0 1115 1115 1E C 10000 82CE7B2C 52656720 #82FCBC78: 46756E63 74696F6E 20310000 82FCBE68 82FCC3FC 82FCBE68 82FCBE74 82FCBE80 #82FCBC98: 82FCBE8C 82FCBE98 82FCBEA4 82FCBEB0 82FCBEBC 82FCBEC8 82FCBED4 82FCBEE0 #========== Dump bp->previous = 82FC8368 ===================== # #82FC8268: 82B235FC 82E90FF8 82FC8260 82FC8280 82B235C8 82E90FF8 82FC8270 82FC8290 #82FC8288: 82B23594 82E90FF8 82FC8280 82FC82A0 82B23560 82E90FF8 82FC8290 82FC82B0 #82FC82A8: 82B2352C 82E90FF8 82FC82A0 82FC82C0 82B234F8 82E90FF8 82FC82B0 82FC82D0 #82FC82C8: 82B234C4 82E90FF8 82FC82C0 82FC82E0 82B23490 82E90FF8 82FC82D0 82FC82F0 #82FC82E8: 82B23414 82E90FF8 82FC82E0 82FC8300 82B233E0 82E90FF8 82FC82F0 82FC8310 #82FC8308: 82B233AC 82E90FF8 82FC8300 82FC8320 82B23378 82E90FF8 82FC8310 82FC8330 #82FC8328: 82B23344 82E90FF8 82FC8320 82FC78D8 82B23310 82E90FF8 0 0 #82FC8348: 0 0 FD0110DF AB1234CD FFFFFFFE 0 82FAF4F0 80476940 #82FC8368: 82FC895C 82FC7D60 800002F0 1 804664F4 0 82FC22FC 82FC776C #82FC8388: 82FAF328 82FAF4B4 32 46 100010 0 0 0 #82FC83A8: 0 10 830000 82CE7B2C 4C697374 20456C65 6D656E74 73000000[/B]