Данная статья является вводной для небольшого цикла, посвященного механизмам безопасности, предназначенным для противодействия успешной эксплуатации уязвимостей класса memory corruption в web-браузерах. В рамках этого цикла мы рассмотрим, какие механизмы и с какой целью внедряются разработчиками браузеров, и поговорим о том, как их можно было или до сих пор можно обойти.
Если вам интересна тема защиты приложений или то, как разработчики эксплоитов преодолевают защиту, добро пожаловать под кат.
Security mitigations
Как-то подобную тему мы уже поднимали в своем блоге в статье “О флагах в 0x41414141 раз”.
Подобные механизмы можно разделить на категории по уровню, на котором они работают или применяются:
- На уровне аппаратного обеспечения – (DEP, MPX, CFI, SMEP, SMAP, UMIP, …).
- На уровне операционной системы – реализовано создателями ОС. Например, SEHOP, ForceASLR. В случае ОС Linux может быть еще выполнено в виде дополнительного патча (Grsecurity).
- На уровне компилятора/линковщика – stack cookie, SafeSEH.
- На уровне приложения:
- Стороннего – EMET, Malwarebytes Anti-Exploit, HitmanPro, PaX и подобные реализации в различных антивирусах;
- Встроенного – реализовано прямо в исходном коде приложения.
Справедливости ради стоит отметить, что данное разделение условно, и не всегда столь категорично. Например, CFG (Control Flow Guard) в ОС Windows требует, чтобы ОС поддерживала этот механизм, и само приложение было собрано со специальными флагами. При несоблюдении хотя бы одного условия CFG не выполняет своих задач.
Механизмы могут быть также направлены на решение конкретной задачи:
- Усложнить (понизить стабильность техники)
- Сделать невозможной работу какой-то техники (Противодействие конкретной технике)
- Смягчить последствия (Изоляции от остальной системы, sandbox)
В историю появления подобных механизмов вдаваться в данной статье не будем, и просто порекомендуем ознакомиться с презентациями:
- “Exploit Mitigation Improvements in Windows 8” с BlackHat USA 2012
- “WINDOWS 10 MITIGATION IMPROVEMENTS” с BlackHat USA 2016
App specific security mitigations
Данный цикл статей как раз и будет посвящен последней категории, т.н. app specific security mitigations. Появление этих механизмов обусловлено самой функциональностью приложения и особенностями его реализации, как правило, затрагивающими или реализующими собственные абстракции манипулирования памятью: собственная ВМ, собственный менеджер кучи, собственный скриптовый язык и т.д.
Самыми яркими представителями можно назвать:
- Браузеры
- Редакторы документов (Word)
- Виртуальные машины (JVM, Dalvik VM, ActionScript VM)
Так, например, на уровне современных ОС механизмы защиты той же кучи (heap) уже есть, но из-за того, что разработчики создают внутреннюю реализацию, механизмы защиты кучи от ОС, по большому счету, не задействуются в рамках функционирования самой программы. Внутренняя реализация порождает внутренние структуры, связи между объектами, алгоритмы, на которые нацеливается атакующий. Естественно, что все это первоначально создавалось для удобства, простоты и быстродействия, но, как показывает практика, впоследствии начинает обрастать различными дополнительными механизмами, предназначенными для обеспечения безопасности. Ну и про функциональность таких решений не стоит забывать, поскольку это также имеет особый отпечаток на вводимых механизмах безопасности.
Браузеры
Поскольку браузеры — самые яркие (и, наверное, самые интересные) представители ПО, реализующие собственные механизмы безопасности от эксплуатации уязвимостей класса memory corruption, мы решили в нашем исследовательском центре сосредоточиться на них. Цикл статей будет посвящен: IE + Edge, Chrome и Firefox для настольных ПК под управлением ОС Windows на x86/x64 архитектуре. Список этих механизмов был взят из обновляемой подборки «Browser security mitigations against memory corruption vulnerabilities»: нашего друга Артура Геркиса, за что ему большое спасибо.
В 2011 году компания Accuvant LABS выпустила документ «Browser Security Comparison: A Quantitative Approach», но уже много воды утекло с того момента, и браузеры серьезно изменились. Однако, ознакомиться с этой информацией все равно не лишне.
Если обобщить рассматриваемые нами в дальнейшем механизмы, можно обозначить несколько групп:
- предотвращение непредусмотренного выполнения кода или данных
- предотвращение проблем, связанных со временем жизни объекта
- сохранение целостности кода, данных или метаданных
- ограничение информации об адресном пространстве
- ограничение возможностей атакующего (sandbox)
Эксплуатация широко распространённого клиентского ПО, включая браузеры или Adobe Flash, представляет собой цепочку уязвимостей, техник и подходов. Достаточно посмотреть на небольшую подборку того, как они ломались на pwn2own 2016:
Для тех, кто хочет более подробно ознакомиться с успешными эксплоитами для браузеров, советуем обратить внимание на выступление “$HELL ON EARTH: FROM BROWSER TO SYSTEM COMPROMISE” (презентация и whitepaper) с BlackHat LasVegas 2016.
Как можно заметить, даже такие “бронированные” программы успешно атакуются с обходом всех механизмов защиты как ОС, так и их собственных. В итоге, исследователи обходят с десяток механизмов безопасности – в действительности, конечно, меньше, так как это сильно зависит от типа используемых уязвимостей. Например, не обходятся механизмы stack cookie с SafeSEH, SEHOP, если уязвимость UaF — поскольку природа уязвимости никак не связана со стеком, и данные механизмы не задействованы. Самую большую угрозу для браузеров представляют уязвимости типа use-after-free (UaF) — CWE-416 – тут все обусловлено сложностью браузеров. Поэтому неудивительно, что разработчики трудятся над созданием механизмов защиты, ориентированных на противодействие данному типу уязвимостей. Следующий момент, которому уделено также пристальное внимание (с точки зрения безопасности) создателями браузеров, это написание JIT (just-in-time) кода. Это связано с тем, что атакующий может использовать такой код для расположения своего шеллкода внутри JIT spray, который одновременно позволяет обойти как DEP, так и ASLR. Поэтому разработчики и стали «закручивать гайки» в этом направлении. Об этом мы также поговорим позже.
Важно понимать, что у любого атакующего есть определенные цели, и он будет к ним идти по пути наименьшего сопротивления. Так, например, не всегда ему нужно выполнять свой собственный шеллкод и закрепляться в системе, получая доступ к данным других приложений. Если в этом нет необходимости, то не нужно обходить CFG и sandbox. При этом, он способен похитить какие-то данные доступные/хранимые браузером, или задействовать его же стандартный функционал, но в своих целях (например, подмена данных или изменение настройки браузера).
RW-примитив
Все постепенно идет к тому, что при наличии у атакующего RW-примитива (уязвимости или ряда уязвимостей, позволяющих ему читать и писать в память), все текущие механизмы защиты обходятся.
Чаще всего, это реализуется благодаря:
- CWE-401: Improper Release of Memory Before Removing Last Reference ('Memory Leak')
- CWE-123: Write-what-where Condition — write-what-where memory corruption примитива
Благодаря утечке памяти, можно обойти рандомизацию памяти (ASLR), найдя в памяти то, что нам нужно, а благодаря возможности писать что угодно и куда угодно – лишь остается задаться вопросом: “Что необходимо переписать, чтобы исполнить свой код (shellcode)?”. Порой, это может быть нужный адрес, где располагается shellcode, флаг в памяти (обход проверки), значение токена (для поднятия привилегий в системе) и т.д.
Стоит отметить, что примитив “Write-what-where” иногда бывает ограничен:
- Не контролируется, то что пишется
- Возможно писать только NULL
- Возможно только инкрементировать значение
- Как-то ограничен диапазон адресов, куда мы можем писать
Но даже с такими ограничениями порой можно провести успешную эксплуатацию – все зависит от приложения и природы уязвимости.Это очень хорошо показано в презентации “Write Once, Pwn Anywhere” с BlackHat USA 2014 в Internet Explorer.
Для ознакомления с мощностью RW-примитива приведем ряд примеров:
- Замечательный пример побега из гостевой виртуальной машины VirtualBox, также благодаря RW примитиву.
- Пример эксплотации в Silverlight (CVE-2016-0034)
- Отличный пример под Linux
- Пример [1,2] под Android
- Пример [1,2,3] с ядром Windows
- Браузеры, конечно, не исключение, но об этом позже.
Этой небольшой подборкой хотелось показать один общий и очень мощный примитив при эксплуатации memory corruption уязвимостей. Он работает для любого браузера, но найти RW-примитив не так-то просто.
В цикле статей мы рассмотрим более специфичные техники обходов механизмов браузеров.
Промежуточный вывод
Уязвимости класса memory corruption были, есть и будут и их будут продолжать эксплотировать. Единственное со временем это все становится сложнее. И очень много зависит от природы уязвимости. Так что на компилятор, ОС, надейся, а сам не плошай.
P.S. Повреждение памяти это хорошо для атакующего, а логические уязвимости просто замечательно или даже web баги типа UXSS это всегда это 100% надёжность, и часто кросплатформенность.
Автор: Digital Security