- Извлечение аппаратного ключа полнодисковой защиты в телефонах Android на процессорах Qualcomm
- Эксплоит опубликован на Github
- Android: извлекаем данные с зашифрованной SD-карты и получаем доступ к скрытым методам
- Содержание статьи
- Почитать
- Как Android обеспечивает безопасность
- Как работают атаки класса Cloak & Dagger
- Как получить доступ к зашифрованной карте памяти
- Как обойти ограничения на доступ к внутренним библиотекам и методам
- Описание уязвимостей в Android Download Provider
Извлечение аппаратного ключа полнодисковой защиты в телефонах Android на процессорах Qualcomm
Эксплоит опубликован на Github
Компания Google начала внедрять полное шифрование диска (Full Disk Encryption, FDE) по умолчанию с версии Android 5.0 Lollipop. В первое время, когда шифрование реализовали в устройствах Nexus 6, многие пользователи жаловались на снижение производительности при чтении и записи данных на накопитель, но с версии Android 6.0 эту проблему вроде бы решили.
Полное шифрование диска защищает всю информацию на телефоне даже в том случае, если устройство попало в руки правоохранительных органов или других злоумышленников.
При включенном шифровании любая информация на телефоне автоматически на лету шифруется ключом AES перед записью на носитель. И наоборот, при считывании информации она автоматически расшифровываются этим ключом.
На устройствах iOS 9 этот ключ является производной функцией от пользовательского пароля и уникального 256-битного аппаратного ключа, зашитого в смартфон на заводе. Взломать шифрование такого уровня с помощью брутфорса не может даже ФБР, как известно из недавней истории со смартфоном стрелка из Сан-Бернардино, из-за которого ФБР и Apple дошли до суда. В итоге ФБР всё-таки сумело взломать телефон с помощью неизвестной 0day-уязвимости. Как можно понять из слов главы госструктуры, за обход защиты ФБР пришлось заплатить хакерам более миллиона долларов.
Полное шифрование диска в iOS
Таким образом, брутфорс FDE возможен только с использованием конкретного аппаратного устройства. Это значительно затрудняет проведение атаки. В обычном случае можно было бы создать миллион копий и распараллелить брутфорс в облачном сервисе, что позволяет очень быстро подобрать 99% реальных паролей. Но в данном случае приходится ограничиваться единственным устройством, на котором Apple добавляет ещё и дополнительные помехи — задержки между попытками ввода пароля, ограничение на максимальное количество попыток и т.д. Вот почему для спецслужб исключительно важно найти способ извлечения аппаратного UID, тогда брутфорс пароля становится банальной технической задачей.
Полное шифрование диска в Android 5.0+ реализовано несколько иначе, чем в iOS 9, и подробно описано в блоге Николая Еленкова и в официальной документации Android.
Здесь ключ шифрования тоже является производной функцией от обычно слабого пользовательского пароля, но также от случайным образом сгенерированного 128-битного мастер-ключа (Device Encryption Key — DEK) и случайно сгенерированной 128-битной соли. Поле генерации DEK защищается с помощью тщательно продуманной схемы, в которой используются введённые пользователем значения — пинкод/пароль/паттерн (графический ключ) для входа. Затем зашифрованный DEK помещается в специальное зашифрованное хранилище под названием crypto footer. Все эти уровни шифрования нужно преодолеть, прежде чем расшифровать DEK, а затем любую информацию, записанную на накопителе.
Как и в случае с iOS 9, в операционной системе Android реализована привязка схемы шифрования к конкретному аппаратному обеспечению, чтобы не допустить брутфорса на копиях операционной системы. Функцию аппаратной привязки выполняет специальное аппаратное хранилище — KeyMaster, которое работает в особом окружении Trusted Execution Environment (TEE), полностью независимом от операционной системы Android. Защищённость ключей в окружении KeyMaster имеет важнейшее значение. Только это защищает систему полного шифрования диска от проведения эффективного брутфорса в параллельных потоках на копиях ОС.
В устройствах Android изолированное окружение никогда не выдаёт свой собственный ключ наружу в «небезопасную» среду. Наоборот, модуль KeyMaster получает из небезопасной среды «блоб ключа» (key blob), расшифровывает хранящийся там ключ — и отдаёт его обратно. Другими словами, работа системы шифрования возможна только непосредственно на аппаратном устройстве, но не в виртуальной среде на другом компьютере.
В общем весь процесс схематично можно изобразить на такой диаграмме, которую приводит Николай Еленков.
Защиту окружения KeyMaster и выполнение команд на выделенном безопасном процессоре обеспечивает защищённая среда, предоставленная производителем оборудования. В Случае с Qualcomm это среда QSEE (Qualcomm Secure Execution Environment). Она допускает к исполнению на выделенном процессоре только отдельные маленькие приложения, которые называются «трастлеты» (trustlets). Один из таких трастлетов — KeyMaster. В исходном коде Android есть инструкции для обращения к приложению KeyMaster. На самом деле трастлет поддерживает всего четыре инструкции:
KeyMaster работает в точности как описано выше: он получает блоб ключа, вычисляет подпись и помещает её в буфер.
И вот теперь мы подошли именно к тому этапу, на котором действует новый эксплоит, который появился в открытом доступе 30 июня (репозиторий на Github). Эксплоит использует недавно найденные уязвимости CVE-2015-6639 и CVE-2016-2431.
Автор эксплоита, специалист по безопасности Гал Беньямини (Gal Beniamini) написал поддельную версию приложения QSEE и с помощью вышеупомянутых уязвимостей сумел загрузить её в защищённое окружение, тем самым осуществив повышение полномочий и взломав защиту окружения QSEE, которое участвует в процессе генерации ключа для шифрования диска.
Таким образом, гипотетический злоумышленник может «подделать» аппаратную составляющую ключа шифрования и осуществить брутфорс остальных компонентов, обойдя защиту Android на количество повторных попыток. Остаётся только подобрать перебором пользовательский пинкод/пароль.
Кстати говоря, для того редкого случая, когда пользователь установил для шифрования по-настоящему сложный пароль с высокой энтропией и его не удаётся подобрать брутфорсом за приемлемое время, есть запасной план. Если взломать шифрование действительно крайне необходимо, то можно найти точно такой же телефон, той же модели, с такими же царапинами и защитным корпусом — и запрограммировать его на отправку пароля, как только жертва введёт его. Этот поддельный аппарат подкладывается жертве вместо оригинального. Чтобы избежать раскрытия и одновременно устранить риск введения жертвой неправильного пароля с первой попытки, телефон должен быть запрограммирован на то, что никакой введённый пароль он не принимает как правильный.
Но это уже крайний случай, конечно. Обычные пинкоды и пароли на самом деле подобрать довольно просто, если нет аппаратных ограничений на брутфорс.
Есть интересный момент. Защищённую среду на мобильных устройствах устанавливает не сама компания Qualcomm, а OEM-производители. Они могут сотрудничать с правоохранительными органами той страны, в юрисдикции которой находятся, и выполнять требования судебных запросов. Соответственно, если подобная криптографическая схема будет реализована российским производителем, то информация на смартфоне будет рассекречена по запросу российского суда.
И ещё один интересный момент. Несмотря на то, что Гал Беньямини несколько месяцев обсуждал данные уязвимости с Qualcomm и Google, исправить их не так просто — здесь недостаточно программного апгрейда (для двух уязвимостей патчи для Android вышли в январе и мае), а может понадобиться аппаратный апгрейд. Дело в том, что если злоумышленник получит устройство, то теоретически может откатить программный апгрейд, вернуть аппарат на уязвимую версию и провести атаку.
Как уже говорилось выше, код эксплоита опубликован на Github. Вот схема его работы.
Гал Беньямини написал несколько скриптов на Python, которые упрощают брутфорс после срабатывания эксплоита. В комментариях к его блогозаписи коллеги выразили желание помочь в портировании скрипта на мощнейшую платформу для брутфорса hashcat/oclHashcat.
Беньямини предполагает, что компания Google вместе с OEM-сборщиками выработают новую абсолютно надёжную схему аппаратно-программного шифрования, которую даже теоретически невозможно будет взломать.
Будем надеется, что такую схему реализуют на новом поколении Android-устройств.
Источник
Android: извлекаем данные с зашифрованной SD-карты и получаем доступ к скрытым методам
Содержание статьи
Сегодня в выпуске: обзор систем безопасности Android, объяснение атак типа Cloak & Dagger, гайд по извлечению данных с зашифрованной карты памяти, обход ограничений на загрузку нативных библиотек и доступ к скрытым Java-методам, уязвимость в Android Download Provider. А также: несколько инструментов пентестера и подборка библиотек для программистов.
Почитать
Как Android обеспечивает безопасность
The Android Platform Security Model — написанный сотрудниками Google вайтпейпер, посвященный теории и практике реализации подсистем безопасности в Android. В документе много воды, но есть и хоть и не новая, но полезная новичкам информация. Наиболее интересные моменты:
- Android использует три вида аутентификации (проще говоря: метода разблокировки экрана) с разным уровнем надежности и, соответственно, уровнем доступа: 1) пароль или пин-код — считается наиболее надежным и поэтому дает полный контроль над устройством без всяких ограничений; 2) отпечаток пальца или снимок лица — менее надежный, поэтому система запрашивает пароль после каждой перезагрузки телефона, а также через каждые 72 часа; 3) аутентификация по местоположению или близости определенного Bluetooth-устройства — наименее надежный метод, поэтому на него накладываются те же ограничения, что и на биометрический метод, плюс он не позволяет получить доступ к аутентификационным ключам Keymaster (например, тем, что используются для платежей), а принудительный запрос пароля происходит не через 72 часа, а уже через четыре.
- Песочницы (изолированная среда исполнения) для приложений в Android реализованы с помощью запуска каждого приложения от имени созданного специально для него Linux-пользователя. Приложение имеет полный контроль над файлами своей песочницы ( /data/data/имя_пакета ), но не может получить доступ к файлам других приложений и многим системным файлам. Система также использует UID (идентификатор пользователя) для контроля полномочий приложения.
- Контроль доступа на основе UID не распространяется на карты памяти и USB-накопители, так как зачастую они используют файловую систему FAT, которая не позволяет назначить права доступа к файлам. Чтобы решить эту проблему, Android использует виртуальную файловую систему (sdcardfs), которая подключается к каталогу /sdcard/Android . Приложения могут хранить данные внутри нее без опасения, что другие приложения получат к ним доступ. Также Android позволяет подключить карту памяти в режиме Adoptable Storage, когда SD-карта форматируется в зашифрованную ФС ext4 и становится частью внутреннего хранилища данных.
- Единственный способ покинуть песочницу — получить права root. В Linux пользователь root имеет неограниченный доступ к файловой системе (ядро отключает любые проверки доступа для этого пользователя).
- Для защиты ключей шифрования/аутентификации Android и приложения могут использовать Keymaster. Это подсистема, позволяющая хранить данные в TEE (Trusted Execution Environment), специальном микрокомпьютере внутри SoC, к которому имеет доступ только система. TEE позволяет защитить данные даже в том случае, если злоумышленник получил права root. Начиная с девятой версии Android также поддерживает StrongBox, выделенный чип TEE, разработанный самой Google. Он позволяет защититься от атак класса Rowhammer.
- Для защиты от эксплуатации уязвимостей в системных компонентах Android использует SELinux, подсистему ядра Linux, позволяющую более тонко управлять правами доступа, а также контролировать доступ процессов к системным вызовам. К примеру, обнаружив в одном из системных компонентов уязвимость, взломщик может попытаться принудить этот компонент выполнить системный вызов exec для запуска root shell, но, если правила SELinux запрещают это делать данному компоненту, вызов будет отклонен.
- Начиная с седьмой версии Android способен гарантировать, что ни операционная система, ни загрузчик не были скомпрометированы. Такая проверка называется Verified Boot и выполняется на этапе загрузки: сначала загрузчик сверяет контрольную сумму раздела boot, затем один из следующих компонентов загрузки сверяет контрольные суммы файлов в разделе system. Тот же механизм используется для защиты от отката на предыдущую версию прошивки, которая может содержать уязвимости. Производители вольны сами выбирать, как должна повести себя система в случае обнаружения нарушения: вывести на экран предупреждающее сообщение или прекратить загрузку.
Как работают атаки класса Cloak & Dagger
Cloak and Dagger — Mobile Malware Techniques Demystified — небольшая заметка о том, как работают атаки класса Cloak & Dagger. Мы писали об этом типе атак еще в 2017 году, но тогда рассмотрели только одну из них: кейлоггер, не требующий дополнительных прав в системе. Эта статья посвящена другой атаке, позволяющей заставить пользователя включить настройку доступа к AccessibilityService (позволяет перехватывать любые нажатия пользователя и нажимать кнопки интерфейса за него), замаскировав переключатель под нечто безобидное.
Атака использует разрешение SYSTEM_ALERT_WINDOW, которое приложения из Google Play получают автоматически. SYSTEM_ALERT_WINDOW позволяет выводить элементы интерфейса поверх других приложений, то есть реализовать такие вещи, как плавающие окна, меню, панели управления. Создатели вирусов быстро смекнули, что эту возможность можно использовать для перекрытия текущего окна на экране и обмана пользователя, поэтому с версией Android 5 Google выкатила защиту, которая проверяет, не был ли перекрыт какой-либо опасный для включения элемент интерфейса оверлеем, и отказывается его включить, если это так. Поэтому Cloak & Dagger вместо одного оверлея на весь экран создает несколько небольших и выкладывает их вокруг элемента управления, так что в результате защита не срабатывает.
Обход защиты на включение AccessibilityService с помощью трех-четырех оверлеев
Атака работает на Android версий 4.4.4–7.1.2, исходный код доступен.
В дополнение можно отметить еще одну статью на смежную тему: Android Toast Overlay Attack: “Cloak and Dagger” with No Permissions. Ее авторы пошли еще дальше и реализовали ту же атаку вообще без использования разрешения SYSTEM_ALERT_WINDOW. Вместо него они засунули все оверлеи в toast-сообщение, то самое, которое позволяет выводить в нижней части экрана информационные сообщения. Как оказалось, такие сообщения тоже представляют собой полноценные полноэкранные окна, большая часть которых прозрачна. И у приложения есть доступ к этому окну и возможность его изменять.
Как получить доступ к зашифрованной карте памяти
Recovering data from a failing Android adoptable storage — статья о том, как восстановить данные с карты памяти, отформатированной с помощью механизма Adoptable Storage. В отличие от обычного подключения SD-карты, Adoptable Storage создает на карте памяти зашифрованный том, форматирует его в файловую систему ext4, а затем подключает ее к основному хранилищу данных так, что на нее можно сохранять не только фотки с пляжа, но и приложения, их данные и любую другую информацию, которая обычно хранится только во внутренней памяти устройства. Другими словами, Adoptable Storage позволяет расширить встроенную память устройства.
Но есть одна, а точнее две смежные проблемы: 1) если вставить карту памяти в другой телефон — он ее не увидит из-за отсутствия ключа для расшифровки данных; 2) если что-то пойдет не так (например, карта памяти начнет сбоить), восстановить данные с нее не получится, точнее получится, но через одно место. Как через это место восстанавливать данные, описано в статье.
Для начала на телефоне необходимо получить права root. Затем подключить карту памяти к Linux-машине (macOS тоже должна подойти, но действия описаны именно для Linux) и снять ее образ. Обычный dd в этом случае не подойдет, так как, если карта памяти начала сбоить, он, скорее всего, вывалится с ошибкой Input/output error. Выручит ddrescue, который предназначен как раз для таких случаев:
Далее необходимо извлечь из памяти устройства ключ шифрования (на устройствах с активным модулем TEE такой трюк, скорее всего, не пройдет):
Используем полученный ключ, чтобы смонтировать файловую систему:
Это все. Далее автор рассказывает, как залить файлы на другую карту памяти и изменить размер файловой системы. Про это можно прочитать в оригинальной статье. Также стоит отметить, что если карты памяти одинакового объема, то можно вообще не заморачиваться с подключением файловой системы на компе и копированием ключа, а просто залить полученный на первом шаге образ на новую карту памяти с помощью того же ddrescue:
Как обойти ограничения на доступ к внутренним библиотекам и методам
Android Runtime Restrictions Bypass — статья о том, как обойти ограничения на доступ к внутренним библиотекам и методам Android.
Начиная с Android 7 Google ввела ограничения на прямую загрузку нативных системных библиотек (например, /system/lib/libart.so ). Позже, уже в релизе Android 9, появилось ограничение на доступ к определенным скрытым методам, которые раньше можно было вызывать с помощью рефлексии. Как оказалось, эти механизмы достаточно просто обойти.
Принцип работы механизма, ограничивающего загрузку библиотек, построен на пространствах имен. Если JNI-библиотека приложения попытается загрузить библиотеку, которая расположена за пределами каталогов /data , /mnt/expand или в песочнице самого приложения, оно будет завершено с такой ошибкой:
Проверка осуществляется в лоадере библиотек ( /system/bin/linker ), который создает для каждой JNI-библиотеки приложения структуру soinfo, которая хранит информацию о ней и пространствах имен, к которым она может получить доступ:
Все структуры soinfo размещены в мэпе g_soinfo_handles_map.
Интересно здесь то, что g_soinfo_handles_map — это экспортированная статическая переменная. Поэтому с помощью символьной таблицы ELF можно найти базовый адрес /system/bin/linker , рассчитать адрес g_soinfo_handles_map JNI-библиотеки и изменить структуру soinfo, добавив нужные пути в доступное ей пространство имен:
После этого попытка загрузить библиотеку будет успешной:
Ограничение доступа к внутренним методам Java API, предназначенным только для использования системными компонентами, реализовано иначе, а именно с помощью прямых проверок на доступ. Например, функция GetStaticMethodID, используемая для доступа к Java-методам из JNI-библиотеки, вызывает функцию FindMethodID, которая в том числе проверяет, доступен ли данный метод:
ShouldBlockAccessToMember() в конечном итоге вызывает метод Runtime::GetHiddenApiEnforcement(), который сообщает, стоит ли отклонить вызов или нет. При этом система может либо пропустить его без вопросов, либо вывести предупреждение, либо использовать черный и серый списки, которые содержат имена запрещенных к использованию методов.
Чтобы отключить проверку, мы должны перевести рантайм в режим «пропускать без вопросов» (EnforcementPolicy::kNoChecks), но для этого нам нужен доступ к самому рантайму:
Однако в этом случае компилятор (а точнее, линковщик) будет вынужден импортировать символ art::Runtime::instance_ в JNI-библиотеку, то есть слинковать ее с libart.so. И здесь мы столкнемся с ограничением пространства имен, а предложенный ранее метод его обхода не сработает, так как мы не сможем изменить пространство имен раньше, чем в память загрузится libart.so.
Но есть другой способ получить доступ к рантайму. Дело в том, что метод JNI_OnLoad, который запускается при загрузке JNI-библиотеки, в качестве первого аргумента получает указатель на art::JavaVMExt, который имеет метод GetRuntime(). Так что все, что нам остается, — это получить доступ к рантайму и отключить проверку:
Примечательно, что команда Android security team не считает описанные методы обхода нарушением безопасности (мол, не для безопасности они были придуманы), поэтому быстро дала согласие на обнародование информации и публикацию исходного кода PoC.
Описание уязвимостей в Android Download Provider
Multiple Vulnerabilities in Android’s Download Provider — статья исследователя, нашедшего три уязвимости в Android: CVE-2018-9468, CVE-2018-9493 и CVE-2018-9546. Все они затрагивают Download Content Provider, компонент, позволяющий любому приложению запустить загрузку файла из интернета так, чтобы пользователь видел уведомление с прогрессом загрузки.
- CVE-2018-9468. Первая уязвимость заключается в том, что Download Content Provider позволяет увидеть любые другие загрузки, происходящие на устройстве, а не только свои собственные. Используя URL вида content://downloads/public_downloads/# , зловредное приложение может подобрать загрузку по номеру и, например, прочитать загруженный файл или подменить его сразу после загрузки. Причем это относится как к обновлениям ПО, так и к загрузкам из Google Play. Исходный код примера.
- CVE-2018-9493. Вторая уязвимость — SQL-инъекция, позволяющая получить доступ к закрытым столбцам таблицы (например, CookieData). Исходный код примера.
- CVE-2018-9546. Третья уязвимость позволяет извлечь HTTP-заголовки (могут включать аутентификационные данные и кукисы) для любой загрузки. Уязвимость использует тот же трюк, что и первая. Исходный код примера.
Данные уязвимости были исправлены в сентябрьском и ноябрьском security-патчах.
Источник