Google Project Zero обнаружил, как обойти гипервизор Knox от Samsung (исправлено в январском патче)

В последнем сообщении в блоге Project Zero команда обнаружила способ обойти защиту ядра Samsung в режиме реального времени, получившую название Knox Hypervisor.

Команда Google Project Zero проверила ряд эксплойтов, которые позволяют атаковать телефоны Samsung, на которых установлен предположительно безопасный пакет безопасности Samsung Knox. В блоге отмечается, что все уязвимости были переданы компании Samsung, которая фактически выпустила их исправления в январском обновлении программного обеспечения.


Фон

В рамках пакета программного обеспечения безопасности Samsung Knox, представленного компанией Samsung, существует часть программного обеспечения, которая находится между приложениями Android и ядром, называемая Гипервизор. Это можно использовать в качестве дополнительного уровня для дополнительной защиты устройств Android. Гипервизор Samsung Knox называется "Защита ядра в реальном времени«или сокращенно RKP, как я буду ссылаться на него в оставшейся части этой статьи.

Ядро находится ниже RKP в стеке программного обеспечения Android, а приложения, работающие на устройстве, располагаются вверху. Идея RKP заключается в обеспечении дополнительного уровня безопасности устройства, поскольку все запросы (памяти и других ресурсов), сделанные приложения к ядру сначала должны пройти через Knox, который пытается определить, делает ли приложение что-то, что не должен. RKP также обеспечивает безопасность за счет скрытности с дополнительным уровнем, позволяющим скрыть конфиденциальную информацию, которую приложение может использовать для компрометации устройства.

В этом блоге довольно глубоко рассматривается принцип работы памяти Android, RKP и операционных систем в целом, поэтому я сократил и упростил его, чтобы дать краткий обзор того, что было обнаружено. Однако я советую вам прочитать всю статью, если у вас есть время, поскольку она очень поучительна.


Эксплойт №1:

КАСЛР или Рандомизация структуры адресного пространства ядра — это процесс изменения местоположения кода ядра в памяти на случайную величину при загрузке. Каждый раз, когда устройство загружается, ядро ​​загружается в другое адресное пространство (область памяти). Идея состоит в том, чтобы усложнить поиск места расположения кода ядра для его атаки, поскольку после каждой загрузки код ядра «смещается» в памяти на случайную величину. Это звучит как отличный шаг для предотвращения потенциальных злоумышленников, но недавно исследовать показал, что на самом деле вы можете победить эту проблему, не требуя наличия программной ошибки или уязвимости, поскольку KASLR на самом деле очень сложно реализовать надежным способом против локальных злоумышленников.

В случае с программным обеспечением RKP возможность обойти KASLR на самом деле проще, чем в исследовании, упомянутом выше. Память всех устройств Android используется с помощью указателей и для защиты устройств от атак всякий раз, когда устройства Android печатают или выводят данные (будь то на экран или в файл для журналов или отладки), ссылки на указатели анонимизируются, что делает невозможным определение того, куда на самом деле указывает указатель при чтении выход.

Думайте об указателях памяти как о дорожном знаке, указывающем на местоположение, и думайте об анонимности как о размытии этого места. Как и на телевидении, анонимизация выполняется после съемок, Android также применяет эту анонимизацию во время вывода и только в том случае, если анонимизация настроена правильно, и автор заявляет что на каждом устройстве, с которым [он] столкнулся, анонимизация указателя была правильно настроена. Может показаться, что взломать это очень сложно, но все, что вам нужно сделать, это найти единственный указатель (например, дорожный знак), который не был анонимизирован (размыт). разработчиком ядра (будьте осторожны, это не обычный разработчик приложений для Android), когда указатель записывается в журналы или другое место, например. экран или файл.

Итак, если вы можете найти указатель, который не был анонимизирован, вы можете вычислить случайный сдвиг адреса ядра как разницу между ними. Интересно, что автор не смог найти уязвимый указатель в ядре, но нашел его внутри RPK. где разработчики забыли анонимизировать указатель в выводе отладки (регистрации), что произошло в результате опечатка. Для анонимизации указателей в Android приходится использовать специальный код, и оказывается, разработчики РПК по ошибке использовали строчная буква "к" вместо заглавная буква «К». Поэтому было относительно просто определить величину случайного сдвига кода ядра и атаковать ее.


Эксплойт №2:

Следующий эксплойт немного сложнее: Samsung Knox защищает ваше устройство, применяя к памяти устройства набор правил, чтобы остановить вредоносный код. Правила следующие:

  1. Все страницы (код в памяти), за исключением кода ядра, помечены как «Привилегированное выполнение никогда» (это означает, что код здесь никогда не может выполняться).
  2. Страницы данных ядра (данные, используемые программой в памяти) никогда не помечаются как исполняемые (поэтому код здесь никогда не может быть запущен).
  3. Кодовые страницы ядра (код в памяти) никогда не помечаются как доступные для записи (поэтому никакой вредоносный код не может их изменить).
  4. Все страницы ядра помечены как доступные только для чтения в таблице трансляции этапа 2 (таблица, которая находится между приложением и ядром, чтобы в дальнейшем не дать приложениям узнать о реальных местах памяти).
  5. Все записи трансляции памяти помечаются приложениями как доступные только для чтения.

Мы сосредоточимся на правиле 3, поскольку именно здесь автор обнаружил проблему с реализацией приведенных выше правил. RPK действительно помечает память ядра как доступную только для чтения, однако из-за недосмотра KASL была обнаружена дыра, которая привела к запись кода в предположительно раздел «только для чтения». Чтобы скрыть расположение ядра во время загрузки, ядру выделяется память, но этот объем памяти намного больше, чем текстовый сегмент ядра. Выделение большего объема памяти значительно затрудняет поиск фактического кода ядра, который может находиться где угодно, и, как мы видели выше, он перемещается случайным образом при каждой загрузке устройства.

_text и _etext обозначают защищенный диапазон.

Автор смог подтвердить, что память, используемая ядром, действительно была помечена как «только для чтения», однако остальная часть этого большого объема памяти, используемая для сокрытия ядра, была нет помечен как «только для чтения». Это связано с тем, что RKP защищает только область, содержащую текст ядра, после применения слайда KASLR.


Эксплойт №3

В третьем эксплойте автор смог получить доступ к другой области памяти, которая также должна быть доступна только для чтения. RKP защищает память и использует Регистр конфигурации гипервизора (HCR) для управления ключевыми операциями ядра. Цель HCR — предоставить действительным и реальным операциям ядра доступ к регистрам и блокировать вредоносные атаки. Это делается путем проверки вызовов регистров, которые управляют функциями виртуализации. HCR настроен на блокировку определенных операций, которые обычно обрабатываются, позволяя RKP выбирать, разрешать или запрещать запрос.

В этом эксплойте управление HCR было не охватывает два регистра это оказалось очень важно. Автор углубился в справочное руководство ARM и обнаружил, что первый регистр позволяет ему фактически отключить RKP для приложений. "Регистр управления системой для EL1 (SCTLR_EL1) обеспечивает контроль верхнего уровня над системой, включая систему памяти...» В идеальном мире приложение будет использовать память, которая была отображена через RKP, чтобы RKP мог контролировать то, к чему приложение может получить доступ. Однако отключение этого регистра позволило РКП будет отключен путем эффективного возврата устройства к тому состоянию, в котором оно работало до установки RKP — это означает, что устройство отображается в физическую память без дополнительной безопасности, обеспечиваемой RKP. Это, в свою очередь, означало, что автор мог читать и писать в память, которая изначально и правильно была заблокирована программным обеспечением RKP.

Второй пропущенный регистр имел более тонкое влияние, но в конечном итоге столь же разрушительный для безопасности. Регистр управления трансляцией для EL1 Регистр (TCR_EL1) напрямую связан с объемом памяти, с которой работает приложение, называемое страницей. В RKP жестко запрограммирован размер страницы 4 КБ, поскольку ядра Linux AARCH64 (например, Android) используют размер трансляции 4 КБ. Рассматриваемый регистр (TCR_EL1) устанавливает для чипсетов ARM размер возвращаемой памяти. Оказывается, что этот реестр не защищен HCR и, следовательно, злоумышленник может изменить его, поскольку автор изменил размер страницы на 64 КБ.

Это означает, что когда запрос выполняется RKP, фактический объем доступной памяти теперь составляет 64 КБ вместо 4 КБ. Причина в том, что чипсет ARM по-прежнему контролирует размер страницы, и эксплойтом было установлено значение 64 КБ. Поскольку RKP защищает память от записи в рамках правил, перечисленных в эксплойте №2, память по-прежнему фактически защищена. Но вот в чем загвоздка: поскольку RKP жестко запрограммирован на 4 КБ, размер страницы не меняется на 64 КБ при обновлении реестра, поэтому защищены только первые 4кб памяти позволяя злоумышленнику сделать все, что он хочет с оставшимися 60кб.


Эксплойт № 4

Последний эксплойт, показанный автором, — это обращение к памяти, где находится программное обеспечение RKP, чтобы злоумышленник мог атаковать само программное обеспечение RKP. Один из способов остановить этот тип атаки, который также используют ядра Linux, — это отключить вашу программу от адресного пространства виртуальной памяти, чтобы никакие приложения не могли атаковать ее, потому что они не могут ссылаться на нее.

Помните, что память — это указатели и таблицы, которые сопоставляют физическую память с виртуальной. В соответствии с обычной защитой в этом типе атаки, RKP разворачивает карту, чтобы его нельзя было атаковать. Однако там, где ядро ​​не предоставляет таких возможностей, RKP позволяет отобразить часть памяти и пометить ее как чтение/запись. Единственная проверка заключается в том, что это не само базовое ядро, поскольку RKP не проверяет, являются ли адреса, которые запрашиваются для сопоставления, областью, в которой сам RKP находится в памяти. В общем, РКП. позволяет переназначить себя обратно в адресное пространство, к которому могут получить доступ приложения, и, как побочный эффект, влияет на память автоматически помечается как чтение/запись поэтому злоумышленник теперь может использовать память по своему усмотрению.


Заключение

Одна из самых больших проблем с четырьмя перечисленными выше эксплойтами заключается в том, что автор упоминает, насколько сложно их будет реализовать из-за отсутствия функций в базовом ядре Android. По иронии судьбы, безопасный гипервизор RKP предоставлял все инструменты, необходимые для проведения атак. Это показывает, что иногда программное обеспечение, созданное с благими намерениями, вызывает больше проблем, чем решает, и нам повезло, что у нас есть люди. как Галь Бениамини, готовый запачкать руки и проверить, соответствует ли документация тому, что на самом деле представляет собой программное обеспечение. делает.

Хотя эти эксплойты кажутся пугающими и делают Knox очень уязвимым, я хотел бы заверить всех, что все эти проблемы были решены. исправлено в январском обновлении от Самсунг. Кроме того, эти эксплойты требуют очень глубокого понимания процессоров ARM и программирования, поэтому барьер для входа в использование этих эксплойтов астрономически высок.


Источник: Проект Ноль.