В iOS 18 появилась новая функция безопасности: перезагрузка бездействия (inactivity reboot). От чего она защищает и как работает? В этом посте мы рассмотрим все подробности вплоть до расширения ядра и Secure Enclave Processor.
Безопасность до и после первой разблокировки
А вы знали, что первый ввод пароля после включения телефона сильно отличается от его дальнейшего ввода для разблокировки телефона?
При первом вводе пароля разблокируется хранилище ключей в Secure Enclave Processor (SEP), шифрующем пользовательские данные на iPhone.
Состояние до первого ввода пароля называется Before First Unlock (BFU). Из-за шифрования пользовательских данных iPhone ведёт себя немного иначе при последующих разблокировках. Вы увидите, что Face ID и Touch ID не работают, и требуется ввод пароля. Но можно заметить и более тонкие отличия: поскольку пароли Wi-Fi зашифрованы, iPhone не будет подключаться к сетям Wi-Fi. Если SIM не защищена PIN-кодом, то iPhone сможет подключаться к сотовым сетям. Это означает, что вы сможете получать телефонные вызовы. Однако при получении вызова, даже если номер есть в контактах, имя контакта не будет отображаться, потому что контакты ещё не дешифрованы. Аналогично, при получении уведомлений о новых сообщениях вы увидите, что получили сообщения, но их предпросмотр будет недоступен. Можете попробовать сами!
В состоянии After First Unlock (AFU) пользовательские данные уже дешифрованы. Даже когда вы видите экран блокировки, некоторые ключи остаются доступными операционной системе. Благодаря этому сохраняется подключение к сетям Wi-Fi, и можно видеть предпросмотр сообщений в уведомлениях даже при заблокированном iPhone.
Хоть это и удобно, состояние AFU более подвержено атакам. Нападающий, который каким-то образом сможет обойти экран блокировки, сможет и получить доступ к дешифрованным данным. Для обхода экрана блокировки нападающему необязательно знать пароль. Уязвимости безопасности внутри iOS могут позволить нападающим добиться исполнения кода и извлечения данных из iPhone, даже когда он кажется «заблокированным».
Нападающие с физическим доступом к iPhone имеют больший выбор уязвимостей безопасности. Поверхность атаки больше, а потому нападающие могут использовать уязвимости в стеке USB или внутри беспроводных протоколов, например, Wi-Fi, Bluetooth или сотовой связи, или даже использовать более инвазивные аппаратные атаки, требующие вскрытия устройства. Такое увеличение поверхности атаки обычно удешевляет эксплойты этих уязвимостей на сером рынке, поскольку потенциально увеличивает предложение. Ещё один удешевляющий атаки фактор — это время: уязвимости, публично известные поставщику и пропатченные в новых версиях ПО, не разблокируют новые iPhone, но могут разблокировать iPhone, находившиеся в состоянии AFU так долго, что не смогли обновить ПО.
Слухи о перезапусках iPhone
В сценариях с участием правоохранительных органов многие важные данные доступны экспертам по цифровой криминалистике в состоянии AFU. Правоохранительные органы пользуются этим и часто отставляют изъятые iPhone включёнными, но изолированными от Интернета до момента извлечения данных. Это время может быть необходимо для того, чтобы подождать появления эксплойта или по юридическим причинам, например, для получения ордера.
Однако воры и другие преступники тоже заинтересованы в получении такого доступа после кражи устройства. Он даёт им доступ к банковским счетам и другой ценной информации, намного превосходящей по стоимости цену самого iPhone, или данных, которые можно использовать для шантажа. Люди часто используют один и тот же пароль многократно, и доступ к аккаунту iCloud может позволить вору сбросить блокировку активации устройства, что повысит стоимость его перепродажи.
В недавней новостной статье 404 media (доступ к ней платный, но самая важная информация также содержится в твите) сообщается о документе правоохранительных органов США про подозрительные перезагрузки iPhone. В этом документе присутствуют два интересных утверждения:
- iPhone с iOS 18 перезапускаются даже при полной изоляции от беспроводных сетей.
- iPhone с iOS 18 приказывают другим iPhone с более старыми версиями iOS перезагружаться по беспроводному соединению!
Особенно важным было бы второе утверждение, если бы оно оказалось правдой. Если бы кто-то разобрался, как это работает, то это стало бы «универсальным телевизионным пультом» для iPhone, беспроводным образом вызывающим перезагрузку одновременно сотен iPhone. Действительно ли Apple могла встроить такую функцию в iPhone?
Я немного знаю о беспроводной экосистеме Apple, поэтому крайне заинтересовался этим и решил исследовать вопрос!
Обнаружение Inactivity Reboot
Когда Apple добавляет новые функции, она обычно не очень хорошо их прячет. ПО Apple содержит множество отладочных строк, которые могут намекать о новой функциональности. Blacktop ведёт репозиторий git найденных в iOS строк; в этом репозитории есть очень удобная история версий. Я решил сделать самое ленивое, что мог придумать: просто поискал текст «reboot».
Бинго, кажется, нам нужно третье вхождение: «inactivity_reboot». Любопытно, что оно находится в keybagd
: этот демон связан с хранилищем ключей, которое разблокируется при первой разблокировке.
Второй поиск только inactivity reboot показал, что эта строка начала встречаться в iOS 18.1 и iOS 18.2. В iOS 18.2 строку «inactivity_reboot» сменили на «inactivity_reboot_enabled», что намекает о дополнительных потенциальных изменениях в новых бетах iOS 18.2.
Пока мне было непонятно только одно: через какое время срабатывает inactivity reboot? В новой статье 404 media утверждается, что через 3-4 дня. Я обновил свой SRD до последней беты и снял таймлапс.
Оказалось, что inactivity reboot срабатывает ровно через три дня (72 часа). iPhone выполняет её вне зависимости от подключения к Wi-Fi. Это подтверждает мои подозрения о том, что эта функция никак не связана с беспроводной связью.
Реверс-инжиниринг Inactivity Reboot
Давайте выполним реверс-инжиниринг изменений! Какие гарантии безопасности они обеспечивают?
Вот краткое описание обнаруженного мной:
- Secure Enclave Processor (SEP) отслеживает время последней разблокировки телефона. Если это время последней разблокировки превышает три дня, SEP сообщает модулю ядра
AppleSEPKeyStore
, что время исчерпано. - Модуль ядра
AppleSEPKeyStore
приказывает пользовательскому пространству инициировать перезапуск. ДалееSpringBoard
надлежащим образом завершает все процессы пользовательского пространства. Это предотвращает потенциальную потерю данных при перезапуске. - Если модуль ядра
AppleSEPKeyStore
обнаруживает, что iPhone по-прежнему включён после того, как должна была выполниться перезагрузка, возникает паника ядра. Такое может происходить, только если кто-нибудь пытается вмешаться в inactivity reboot. - Модуль ядра
AppleSEPKeyStore
записывает переменную NVRAMaks-inactivity
. После перезапуска iPhonekeybagd
считывает эту переменную и если она установлена, отправляет Apple событие аналитики, включив в него информацию о том, как долго iPhone не разблокировался.
В оставшейся части поста я расскажу, как выяснил всё это, и какие последствия для безопасности это несёт.
Индикаторы в Sysdiagnose
После поиска в ipsw-diffs я знал, что при перезапуске выводятся какие-то сообщения лога. Начав изучать их статически, я уже знал, что мне самому придётся выполнять их логгинг.
После того, как мой телефон перезагрузился спустя три дня, я запустил sysdiagnose и поискал эти сообщения. Если будете делать это сами, разблокируйте устройство перед выполнением sysdiagnose. В противном случае события до перезапуска будут отсутствовать.
В сообщениях AppleSEPKeyStore
рядом с моментом inactivity reboot присутствуют следующие записи:
Для дополнительного контекста приведу неотфильтрованные сообщения лога до инициации перезапуска:
Реверс-инжиниринг расширения ядра SEPKeyStore
Самое новое ядро iOS можно скачать при помощи следующей команды ipsw:
ipsw download appledb --device iPhone17,3 --os iOS --version '18.2 beta 2' --kernel
После неё ядро скачается и распакуется. Для дальнейшего анализа я загрузил весь кэш ядра в Binary Ninja. ipsw
также поддерживает разбиение ядра на его модули (называемые в iOS «расширениями»). В последней версии Ghidra тоже есть хорошая поддержка ядра iOS, так что для этого анализа есть большой выбор инструментов. Также я скачал старое ядро, в которое Apple случайно включила символы, и вручную выполнил diff этих версий с особым вниманием к коду, связанному с inactivity reboot. В ядре есть три строки, связанные с этой функцией:
Строка «notifying user space of inactivity reboot» уже известна нам из sysdiagnose. Она принадлежит функции AppleKeyStore::handle_events
, которая в фоновом режиме опрашивает события SEPevents. На скриншоте ниже показан более широкий контекст после реверс-инжиниринга и переименования функций.
Первая строка «max inactivity window expired, failed to reboot the device» — это паника ядра в случае, когда iPhone не удалось выполнить перезапуск.
Для дополнительного контекста скажу, что паника вызывается функцией AppleKeyStore::handle_device_state_return
. Есть несколько путей, вызывающих этот обработчик через множество слоёв абстракции, связанных с UserClient, но также и с состояниями SEP.
При помощи плагина calltree мы можем увидеть все входящие вызовы к этой функции.
Теперь рассмотрим последнюю строку, «aks-inactivity». Можно заметить, что это свойство, задаваемое в IORegistry.
Её аналог находится в keybagd
в пользовательском пространстве. При инициализации keybagd
она проверяет эту переменную, создаёт событие аналитики, а затем удаляет её. Вероятно, это событие аналитики помогает Apple оптимизировать временное окно, но мы можем игнорировать его, потому что оно не касается основной функциональности.
Мне не удалось найти конкретное временное окно, несмотря на знание о том, что оно равно 72 часам. Я не смог найти никаких чисел, соответствующих 72 часам. Как же телефон узнаёт, когда перезагружаться?
Хотя в расширении ядра SEPKeyStore
есть какие-то отсылки на функциональность, связанную со временем, ни одна из них не похожа на значение, равное 72 часам. Эти отсылки было достаточно легко найти, они не особо отличаются от старых версий ядра без функции inactivity reboot, так что непохоже, чтобы эта функциональность была добавлена сюда.
Однако SEPKeyStore
общается с сопроцессором SEP. В найденных мной функциях перезагрузки связаны с какими-то состояниями SEP. Может ли быть так, что сам SEP проверяет время?
Реверс-инжиниринг Secure Enclave Processor
SEP — один из самых сильно защищаемых секретов Apple. В отличие от большинства основных прошивок iPhone, прошивка SEP зашифрована.
К счастью, @nyan_satan недавно устроил утечку ключей шифрования прошивки SEP для iOS 18.1 beta 6, приблизительно в которой Apple как раз добавила inactivity reboot. (Спасибо! Люди из Apple, если вы читаете это: почему бы вам не поставлять SEP без шифрования?) При помощи ipsw
мы можем скачать прошивку SEP следующим образом:
ipsw download appledb --device iPhone16,1 --os iOS --version '18.1 beta 6' --pattern "sep-firmware.d83.RELEASE.im4p"
Благодаря утёкшим ключам мы можем расшифровать прошивку:
pyimg4 im4p extract --iv 6705fb216080e19667dbcf71f532ae73 --key 4ea9db4c2e63a316a6854c83e2f5c81fd102ad40160b8998b5f9b16838b7116e -i sep-firmware.d83.RELEASE.im4p -o sep-firmware.d83.RELEASE.im4p.e
Загрузить её в Binary Ninja оказалось не так просто. Мы можем предположить, что архитектура SEP — это 64-битный ARM little endian. Но отсутствуют метаданные о том, куда должна загружаться прошивка. Мне было лениво, и я не хотел тратить время на написание загрузчика прошивки, поэтому воспользовался функцией Triage Binary Ninja, чтобы автоматически определить наиболее вероятные адреса. Стоит отметить, что прошивка, похоже, имеет несколько сегментов и существует несколько потенциальных адресов загрузки. Я выбрал 0x80090000ffc80000, и он сработал.
О SEP известно очень мало. Лучшая информация, которую мне удалось найти — это презентация 2016 года, но это всё равно лучше, чем ничего! Полезно знать, что прошивка SEP структурирована в приложения, так что я предполагаю, что другие базовые адреса, найденные triage, могут соответствовать адресным пространствам других приложений. Приложение, общающееся с SEPKeyStore, называется sks
(см. слайд 86 презентации). Не так уж много информации, но достаточно, чтобы начать реверс-инжиниринг!
После изучения строк можно прийти к выводу, что архитектура работающих внутри SEP приложений с 2016 года особо не поменялась. Связанное с SEPKeyStore
приложение по-прежнему называется sks
:
В SEP почти нет отладочных строк, что усложняет его реверс-инжиниринг. Вот, как выглядит функция инициализации SEPKeyStore
после ручного добавления аннотаций («sth» обозначает «что-то», «something», я не особо вдавался здесь в разбор специфики):
В основной функции можно найти множество других функций, исполняемых до запуска рабочего цикла сервиса. Однако здесь очень много кода. Как нам выделить то, что связано с inactivity reboot?
Вспомним, что мы искали что-нибудь, напоминающее 72 часа. В ядре время обычно измеряется в секундах или микросекундах. Например, 72 часа — это 259200 секунд (0x3f480). Но поиск этого числа (или 259200000000 для микросекунд, или любых других подходящих единиц измерения) в двоичном виде не вернул никаких совпадений.
Благодаря compiler explorer мы можем понять, почему: оптимизации…
Вместо того, чтобы искать полное время в байтах в обратном порядке байтов, мы ищем ассемблерные команды, загружающие части временного интервала в регистр.
Binary Ninja знает, как откатить эту оптимизацию, и позволяет выполнять поиск в их промежуточных представлениях вместо поиска сырых байтов. В данном случае мы знаем, что ищем константу.
Нашлось только два совпадения:
И вот она — функция, сравнивающая разное время, в том числе три дня, которая связана с основной функцией приложения sks
. Результат этого сравнения времени используется для создания сообщения, которое, скорее всего, отправляется расширению ядра SEPKeyStore
. Если создать новый enum, то код будет более читаемым:
enum times : uint32_t
{
_3_days = 0x3f480,
_2_days = 0x2a301,
_1_days = 0x15181,
`_2.5h` = 0xe11
};
Эта функция используется в контексте для инициализации struct, которое, вероятно, представляет собой сообщение, отправляемое из SEP расширению ядра.
Дальше я особо не углублялся в реверс-инжиниринг SEP, но, похоже, это подтверждает, что именно SEP отслеживает, как долго телефон не разблокировали. Такая логика имеет смысл, ведь SEP задействуется при каждой разблокировке и к тому же защищён от вмешательства, даже если будет использован эксплойт против основного ядра, поэтому это подходящее место для такой меры безопасности.
Эта мера нужна только против полицейских?
Хотя в СМИ утверждалось, что эта мера в основном направлена против правоохранительных органов, она стала ещё и огромным улучшением безопасности для защиты от воров. Устаревшее полицейское оборудование часто оказывается на eBay и других подобных платформах и продаётся по достаточно низким ценам. Однако у воров не будет финансовых и юридических средств для получения актуальных эксплойтов для разблокировки iPhone за три дня после кражи. Это ещё одна причина важности обновления устройств!
С другой стороны, правоохранители могут и будут видоизменять свои рабочие процессы, чтобы действовать быстрее, чем раньше. Первые компании, производящие инструментарий для цифровой криминалистики, уже объявили, что способны координировать эти шаги в течение 24 часов! (Это также говорит нам о том, что у них есть эксплойты только состояния AFU...)
Основные выводы
Эта функция совершенно не связана с беспроводной активностью. Вывод из документа правоохранительных органов о том, что перезагрузка вызвана беспроводным общением телефонов друг с другом, неправдоподобен. Старые iPhone с iOS версий старше 18, вероятно, перезагружались по другой причине, например, из-за программного бага.
Измерение времени и запуск перезагрузки выполняются в SEP, который для выполнения перезагрузки обменивается данными с расширением ядра SEPKeyStore
. Высока вероятность того, что использование внешнего источника времени по Интернету или сотовым сетям, позволяющее вмешиваться в измерение времени, не повлияет на трёхдневный таймер.
С точки зрения безопасности это очень мощная мера защиты. Чтобы предотвратить inactivity reboot, нападающий должен получить возможность исполнения кода ядра. Это значит, что криминалист-аналитик может отложить перезагрузку для извлечения данных, но первоначальный эксплойт должен быть запущен в пределах первых трёх дней.
Inactivity reboot изменит ситуацию с угрозами и для воров, и для цифровых криминалистов, но асимметричным образом: правоохранители будут вынуждены будут действовать быстрее, а преступники полностью потеряют возможность доступа к банковским счетам пользователей и другой ценной информации, хранящейся на iPhone.
Вопросы и ответы
Ниже представлены ответы на самые частые вопросы, которые мне задавали.
▍ Когда появилась эта функция?
ipsw-diffs показали только событие аналитики в keybagd
. Они не показывают, когда функция была добавлена в ядро или в прошивку SEP (зашифрованную). Согласно данным других исследователей, она была добавлена в iOS 18.0 и в iPadOS 18.0, изначально имея таймер на семь дней, который потом был снижен до трёх дней.
▍ Я не хочу, чтобы мой iPhone перезапускался каждые три дня!
Не беспокойтесь, у большинства людей такого никогда не будет происходить. Таймер сбрасывается при каждой разблокировке iPhone.
▍ Удалит ли эта функция мои данные?
Нет. Inactivity reboot похожа на обычную перезагрузку. Она не удаляет никаких данных. Она просто блокирует защищённые SEP ключи до тех пор, пока вы не введёте пароль.
▍ Работают ли после перезагрузки будильники?
Да. Если вы установите будильник и ваш iPhone перезагрузится, будильник всё равно сработает. Всё остальное будет довольно серьёзной проблемой, потому что многие люди включают автоматические обновления ПО, которые тоже перезагружают iPhone ночью.
▍ Перестанет ли из-за этого работать функция Локатор (Find My)?
По всей видимости, в состоянии BFU даже в случае наличия подключения к сотовой сети ваши друзья больше не смогут получать ваше текущее местоположение. Причина может заключаться в том, что ключ для передачи местоположения контактам всё ещё заблокирован.
При использовании другого устройства Apple или iCloud под своим аккаунтом для просмотра местоположения устройства вы увидите менее точное, но более новое местоположение. Хотя это похоже на магию, существует второй механизм Локатора (Find My), который продолжает работать после перезагрузки, даже в режиме BFU: Find My через оповещения Bluetooth Low Energy (BLE). Любое находящееся поблизости устройство Apple, увидевшее эти оповещения, передаст информацию о них с их местоположением в Apple; данные будут зашифрованы ключом, содержащимся в оповещении и относящимся к вашему аккаунту iCloud. В предыдущих исследованиях мы выяснили, что ключи оповещений, сгенерированные до перезагрузки, валидны только в течение 24 часов.
Если вы потеряли свой iPhone и он меняет своё местоположение, то у вас остаётся четыре дня, чтобы найти его. Это достаточно много, учитывая, что iPhone нужно постоянно заряжать. Если уж терять его, то сразу с большим пауэрбанком!
После этого временного промежутка Локатор продолжит показывать последнее местоположение iPhone.
▍ Почему при запуске в видео на экране телефона есть белый текст?
Для записи видео я использовал устройство Security Research Device с подробным выводом при запуске. Он никак не меняет ничего, связанного с inactivity reboot.
▍ Повлияет ли эта функция на джейлбрейкинг?
Едва ли.
Автор: ru_vds