Это самая невероятная уязвимость, которую я когда-либо видел
и
Удивительно, что даже инженер Google может совершить такую большую ошибку в эпоху искусственного интеллектаХотел рассказать про другое, но как тут про другое, когда такие цитаты. В общем, вот вам очередной наброс от команды LSPosed и, соответственно, очередной проеб от Google. Это действительно интересно, и это нужно знать, если вы хоть немного хотите понимать что за железку держите в руках. Постараюсь максимально просто.
Цепочка эксплойтов состоит из двух CVE - брешь в стеке телефонии 17-го Андроида и пробоина в ядре.
Работает это в три шага:
1. Для начала, нужно оказаться внутри процесса, которому система доверяет.
Если установленное приложение заявляет "я могу обрабатывать звонки", но на самом деле не может, то система лезет к несуществующему классу и падает. В Android 17 добавили проверку: перед обращением убедиться, что класс реально есть. Чтобы узнать, есть ли класс в чужом приложении, нужно взять загрузчик кода этого приложения. Приложение телефонии так и делает, но... Проверяя заодно и исполняет загруженный код. Это тот самый "гугловский инженер" упорол косяк.
Приложение подсовывает свой код, который нужно выполнить для побега из песочницы в процесс которому система доверяет. Обычно чужой код в чужом приложении не смертелен. Но приложение телефонии объявлено как часть системы: оно живёт не отдельно, а прямо в system_server, главном процессе Android, с системным идентификатором. Всё, чужой код внутри.
2. Из системного процесса запустить обычный машинный код нельзя, политики запрещают. Но там же, в этом процессе, лежит список связей со всеми остальными процессами. По этому списку атакующий дотягивается до сетевого процесса и заставляет его загрузить свой код. Сетевой процесс нужен потому, что ему разрешено работать с шифрованными соединениями IPsec, а именно там третья дыра. Самая основная.
3. Телефон держит содержимое открытых файлов в оперативной памяти, чтобы не читать с диска по десять раз. Влез в этот фрагмент памяти - можешь контролировать то что исполняется в текущий момент. Права на файл, разумеется, проверяются, иначе у всего на устройстве был бы root. Но проверяются они только к файлу на диске. К файлу, который открыт в памяти - нет. Поскольку подразумевается что писать туда будет только ядро.
А раз только ядро, то на тебе, ядро, дополнительные плюшки. Например отправка без копирования в отдельный буфер и расшифровка на месте. Атакующий делает так, чтобы эти два фактора встретились. Он собирает пакет, один из кусков которого - это ссылка на память с системным файлом, и скармливает этот пакет ядру как входящий зашифрованный. Ядро его расшифровывает и пишет в файл, на который указывает ссылка. После этого бесполезны все проверки и тд. Устройство скомпроментировано.
Переписанный кусок файла срабатывает, когда его вызывает системный процесс, и дальше по цепочке: исполнение уходит в init, оттуда в ядро грузится чужой модуль, SELinux переводится в разрешающий режим, пиздец вашему устройству и ядерный апокалипсис.
Самый главный момент здесь - не косяки "гугловских инженеров". Они взяли и тупо убрали проверку с которой я начал описание. Просто взяли, откатили то что накосячили, и - ура, мы закрыли уязвимость! Самое главное - это то, что завтра найдут новую дыру, где-нибудь в стеке bluetooth, и она точно так же по цепочке приведет к эскалации в ядре. Ядро на апстриме первый раз пофиксили от DirtyFrag еще в 2017-ом, но фикс тут же обошли. Последняя заплатка на его разновидность Fragnesia показала что сам класс уязвимостей будут юзать всегда, находить новые дыры, составлять новые цепочки.
Нужно помнить главное: ваша безопасность - ваша забота.
То что там где-то что-то пофиксили в апстриме, совершенно не означает что устройство в ваших руках безопасно. Уязвимость оставалась не закрытой три месяца с момента публикации. Флагманский смартфон от Google уязвим спустя три месяца после исправления ядра. Что там на каких-нибудь китайфонах - вообще представить страшно. Фикс ядра доедет до вас спустя еще месяцы или никогда.