![](https://habrastorage.org/webt/ly/57/en/ly57en9wbdeewi4iplpsr7javqs.png)
Мы делаем все, чтобы платформа Android была безопасной для всех пользователей на всех устройствах. Каждый месяц выходят обновления системы безопасности с исправлениями уязвимости, найденными участниками программы Vulnerability Rewards Program (VRP). Однако мы также стараемся защищать платформу от других потенциальных уязвимостей, например используя компилятор и улучшая тестовую среду. Экосистема Android включает в себя устройства с самыми разными возможностями, поэтому все решения должны быть взвешенными и должны учитывать доступные данные.
В этой статье рассказано о том, как мы выбираем средства безопасности для конкретных обстоятельств и как они реализуются.
Обеспечение безопасности Android подразумевает комплексный подход. Чтобы затруднить потенциальное использование уязвимостей, мы принимаем решения на основе данных, руководствуясь сразу несколькими принципами и методами. Когда речь идет об усилении защиты платформы, необходимо ответить на следующие вопросы:
- Какие у нас есть данные и как они могут помочь в принятии решений?
- Какие средства предотвращения атак доступны? Как их можно улучшить? В каких ситуациях их следует применять?
- Какие проблемы могут возникнуть при использовании тех или иных средств безопасности? Какие возможные расклады следует принять во внимание?
Принципы, на которые мы опираемся при выборе средств безопасности, отражают наш общий подход к защите пользователей платформы Android.
Принятие решений по обеспечению безопасности на основе данных
Чтобы выяснить, для каких компонентов платформы будут эффективны те или иные решения, мы обращаемся к различным источникам. Программа Android Vulnerability Rewards Program (VRP) – едва ли не самый информативный из них. Наши инженеры по безопасности анализируют все уязвимости, обнаруженные участниками программы, определяя их первопричины и уровень серьезности (на основе этих рекомендаций). Кроме того, есть внутренние и внешние отчеты об ошибках. Они помогают выявлять уязвимые компоненты, а также фрагменты кода, которые часто вызывают сбои. Зная, как выглядят такие фрагменты, и представляя себе серьезность и частоту ошибок, возникающих из-за них, мы можем принимать взвешенные решения о том, какие средства безопасности будут наиболее эффективными.
![](https://habrastorage.org/getpro/habr/post_images/9b5/9cb/4a5/9b59cb4a57116a1ce748e89b555ad922.png)
Уязвимости с высоким и критическим уровнем серьезности, исправленные в бюллетенях по безопасности Android в 2019 г.
Однако не стоит полагаться только на отчеты об уязвимостях. Они изначально дают искаженную картину, так как специалисты по безопасности часто обращают внимание на «горячие» зоны, то есть на те области, где ранее уже были найдены уязвимости (например, Stagefright). Или они могут искать уязвимости там, где их проще обнаружить с помощью готовых решений. Например, если на платформе GitHub будет опубликован какой-нибудь аналитический инструмент безопасности, многие специалисты будут им пользоваться.
Мы стараемся равномерно распределять усилия по укреплению безопасности. Наши команды обращают внимание на менее изученные и более сложные компоненты платформы. Кроме того, на виртуальных машинах и физических устройствах Android постоянно выполняется автоматическое фаззинг-тестирование, что позволяет находить и исправлять ошибки на самых ранних стадиях разработки. При принятии решений о том, какие инструменты использовать, мы также анализируем исходные причины и уровень серьезности обнаруженных проблем.
В рамках программы Android VRP мы поощряем разработчиков, которые добавляют полные цепочки уязвимостей, позволяющие проследить весь процесс атаки от начала до конца. Как правило, злоумышленники используют сразу несколько уязвимостей, и в подобных цепочках эти «связки» хорошо видны, поэтому они очень информативные. Наши инженеры по безопасности анализируют как цепочки целиком, так и их отдельные звенья и пытаются обнаружить в них новые стратегии атак. Такой анализ помогает определить стратегии, помогающие предотвратить последовательное использование уязвимостей (например, случайное распределение адресного пространства и методы Control Flow Integrity), а также понять, можно ли уменьшить масштабы атаки, если процесса получил нежелательный доступ к ресурсам.
Очевидно, что некоторые уязвимости могут входить сразу в несколько цепочек и располагаться в разном порядке. Поэтому лучше использовать «углубленную защиту», снижая эффективность отдельных уязвимостей и удлиняя цепочки эксплотов. В этом случае злоумышленнику будет сложнее построить эффективную цепочку и провести атаку.
Чтобы понимать текущие угрозы безопасности и прогнозировать будущие тенденции, нужно постоянно держать руку на пульсе сообщества специалистов безопасности, в частности:
- тесно сотрудничать со сторонними специалистами по вопросам безопасности;
- читать тематические издания и посещать конференции;
- изучать технологии, используемые вредоносным ПО;
- отслеживать последние разработки в сфере безопасности;
- принимать участие в сторонних проектах, таких как KSPP, syzbot, LLVM, Rust и т. д.
В результате у вас будет более полное понимание общей стратегии безопасности, эффективности существующих решений и возможностей для их улучшения.
Почему усиление защиты необходимо
Усиление защиты и предотвращение атак
Анализ данных помогает выявлять области, в которых эффективные средства предотвращения атак могут устранить целые классы уязвимостей. Например, если в некоторых компонентах платформы появляется много уязвимостей из-за ошибок целочисленного переполнения, следует использовать санитайзер неопределенного поведения (UBSan), например Integer Overflow Sanitizer. Если часто наблюдаются уязвимости, связанные с доступом к памяти, необходимо использовать программы распределения памяти с усиленной защитой (в Android 11 они включены по умолчанию) и средства предотвращения атак (например, Control Flow Integrity), устойчивые к переполнению памяти и уязвимостям Use-After-Free.
Прежде чем поговорить об использовании данных, мы предложим классификацию инструментов для усиления защиты платформы. Вот основные сегменты, на которые можно разбить все эти инструменты (хотя некоторые средства и методы могут относиться сразу к нескольким из них):
- Средства устранения эксплойтов
- Средства детерминированного устранения уязвимостей в среде выполнения выявляют неопределенное или нежелательное поведение и прерывают выполнение программы. Это исключает повреждение данных в памяти, при этом сохраняется вероятность лишь менее серьезных сбоев. Часто такие средства можно применять точечно, и они все равно будут эффективными, так как рассчитаны на отдельные ошибки. Примеры: санитайзер для целочисленного переполнения и BoundsSanitizer.
- Средства снижения воздействия эксплойтов предотвращают переход от одной уязвимости к другой или получение возможности выполнения кода. В теории эти средства могут полностью устранять некоторые уязвимости. Однако чаще всего они ограничивают возможности их использования. В результате злоумышленникам приходится тратить больше времени и ресурсов на разработку эксплойта. Часто эти средства задействуют весь объем памяти, занимаемый процессом. Примеры: случайное распределение адресного пространства, Control Flow Integrity (CFI), стековый индикатор, добавление тегов к памяти.
- Преобразование компилятора , изменяющие неопределенного поведения в определенное на этапе компиляции. В результате злоумышленники не могут воспользоваться неопределенным поведением, например неинициализированной областью памяти. Пример: инициализация стека.
- Декомпозиция архитектуры
- Отдельные блоки разделяются на мелкие компоненты с меньшими привилегиями. В результате воздействие уязвимостей в этих компонентах уменьшается, так как злоумышленник не получает прежнего доступа к системе. Этот метод удлиняет цепочки уязвимостей, а также усложняет доступ к конфиденциальным данным и дополнительным путям повышения привилегий.
- Песочницы и изоляция
- Здесь действует принцип, схожий с декомпозицией. Процессу выделяется минимальный набор разрешений и возможностей, необходимых для нормальной работы (часто с помощью обязательного и/или избирательного контроля доступа). Как и в случае с декомпозицией, песочница ограничивает возможности злоумышленников и делает уязвимости в этих процессах менее значимыми благодаря принципу минимальных привилегий. Примеры: разрешения в Android, разрешения в Unix, возможности Linux, SELinux и Seccomp.
- Использование языков с безопасной обработкой памяти
- Языки программирования C и C++, в отличие от Java, Kotlin и Rust, не обеспечивают достаточный уровень безопасности памяти. Учитывая, что большинство уязвимостей в Android связаны с памятью, мы применяем двусторонний подход: улучшаем безопасность языков C/C++ и одновременно рекомендуем использовать более надежные языки программирования.
Реализация этих инструментов
В зависимости от конкретной проблемы мы решаем, какие из описанных средств следует использовать и каким образом. Например, каждое из них подойдет, если мы имеем дело с большим процессом, предусматривающим обработку ненадежных данных и сложный синтаксический анализ. Мультимедийные платформы стали отличной демонстрацией того, как с помощью декомпозиции архитектуры можно более эффективно устранять эксплойты и предотвращать повышение привилегий.
![](https://habrastorage.org/getpro/habr/post_images/e3f/e8c/6f1/e3fe8c6f1542abe35c1d67d8a8b44c1b.png)
Декомпозиция архитектуры и изоляция медиа фреймворков в историческом контексте
Объекты удаленных атак (NFC, Bluetooth, Wi-Fi и медиаконтент) традиционно сопряжены с самыми серьезными уязвимостями, поэтому усиление их безопасности должно стать приоритетной задачей. Как правило, появление этих уязвимостей вызвано самыми распространенными первопричинами, которые выявляют в рамках программы VRP, и недавно мы добавили для всех них санитайзеры.
Средства предотвращения атак удобно использовать для библиотек и процессов, которые задают границы безопасности или находятся в них (например, libbinder, а также стандартные библиотеки libui, libcore и libcutils), так как они не привязаны к конкретным процессам. Однако эти библиотеки отвечают за эффективную и стабильную работу систем, поэтому перед тем как применять тот или иной метод, необходима серьезная гарантия того, что он усилит безопасность.
Наконец, важно обеспечить защиту ядра, учитывая высокий уровень его привилегий. У всех кодовых баз разные характеристики и функциональность, поэтому и вероятность появления уязвимостей в них отличается. Главные критерии здесь – стабильность и производительность. Следует применять только эффективные средства безопасности, которые не будут мешать пользователям работать. Поэтому прежде чем выбрать оптимальную стратегию усиления защиты, мы тщательно анализируем все доступные данные, связанные с ядром.
Подход, основанный на данных, дал ощутимые результаты. После обнаружения уязвимости Stagefright в 2015 году мы стали получать сообщения о большом количестве других критических уязвимостей мультимедийной платформы Android. Ситуацию усложняло то, что многие из них были доступны удаленно. Мы провели масштабную декомпозицию системы Android Nougat и ускорили исправление уязвимостей в мультимедийных компонентах. Благодаря этим изменениям в 2020 году не было ни одного сообщения о критических уязвимостях в мультимедийных платформах, к которым можно получить доступ через Интернет.
Как принимается решение о развертывании
Естественно, есть смысл сосредоточиться на тех средствах предотвращения атак, которые работают лучше всего. Чтобы выявить их, мы смотрим, как каждое средство влияет на производительность, какой объем работ необходим для его развертывания и поддержки, не будет ли оно негативно влиять на стабильность системы.
Производительность
При выборе средства предотвращения атак необходимо понять, как оно влияет на производительность устройства. Если некоторые компоненты или система в целом не будут справляться с нагрузкой, время работы от батареи и общая скорость работы устройства может снизиться. Особенно это касается устройств начального уровня, которым также необходимо усиление безопасности. Таким образом, мы отдаем предпочтение наиболее эффективным решениям, которые не сказываются на производительности устройств.
При оценке производительности мы обращаем внимание не только на процессорное время, но и на использование памяти, длину кода, время работы от батареи и случаи зависания интерфейса. Чтобы убедиться в эффективной работе того или иного средства во всей экосистеме Android, особенно важно проверить перечисленные параметры на устройствах начального уровня.
Очень важно то, для какого именно компонента применяются меры защиты. Например, для межпроцессного взаимодействия чаще всего используется привязка. Поэтому любая чрезмерная нагрузка мгновенно отразится на работе устройства. В случае с медиапроигрывателем, который всего лишь обрабатывает кадры с исходной частотой, ситуация иная. Если скорость видео намного превышает скорость показа, дополнительная нагрузка не будет настолько критичной.
Чтобы определить влияние того или иного решения на производительность, мы используем эталонные тесты. Если результаты эталонных тестов для компонента отсутствуют, их необходимо получить, например вызвав код затронутого кодека для декодирования медиафайла. Если тестирование укажет на недопустимую нагрузку, существует несколько вариантов:
- Выборочно отключить средства предотвращения атак для функций, существенно влияющих на производительность. Как правило, только некоторые функции потребляют ресурсы в среде выполнения. Если не применять к ним средства предотвращения атак, можно сохранить производительность и максимально усилить влияние на безопасность. Вот пример такого подхода для одного из медиакодеков. Чтобы исключить риски, упомянутые функции следует предварительно проверить на наличие ошибок.
- Оптимизировать использование средства предотвращения атак. Часто для этого необходимо внести изменения в компилятор. Например, наша команда перешла на использование Integer Overflow Sanitizer и Bounds Sanitizer.
- Параметры некоторых средств предотвращения атак, таких как встроенная устойчивость распределителя Scudo к уязвимостям в динамической памяти, можно настраивать для повышения производительности.
Для многих из этих улучшений необходимы изменения в проекте LLVM. В результате выигрывает не только платформа Android, но и другие участники сообщества LLVM.
Развертывание и поддержка
При выборе средств предотвращения атак необходимо учитывать не только аспекты безопасности и производительности, но и затраты на развертывание и долгосрочную поддержку.
Влияние средств безопасности на стабильную работу системы
Важно понимать, возможно ли ложное срабатывание того или иного средства предотвращения атак. Например, если санитайзер Bounds выдает ошибку, речь точно идет о запрещенном доступе (хотя его могли и не использовать). В случае с санитайзером Integer Overflow возможны ложные срабатывания, так как целочисленное переполнение часто бывает абсолютно нормальным и безвредным процессом.
Поэтому важно учитывать влияние средств предотвращения атак на стабильность системы. Неважно, произошло ли ложное срабатывание или была реальная угроза безопасности, – в любом случае пользователь испытывает неудобства. И здесь мы снова отмечаем, что необходимо четко понимать, для каких компонентов следует использовать те или иные средства безопасности. Потому что сбои в некоторых компонентах сильнее сказываются на стабильности системы. Если средство предотвращения атак вызывает сбой в медиакодеке, видео просто перестанет воспроизводиться. Однако в случае ошибки в процессе
netd
при установке обновления устройство может больше не включиться. Даже если для некоторых средств предотвращения атак ложное срабатывание не вызывает проблемы (например, как в случае с санитайзером Bounds), мы все равно проводим подробное тестирование, чтобы убедиться в стабильной работе устройства. Например, ошибки смещения на единицу могут не приводить к сбоям в обычном режиме, а санитайзер Bounds прерывает выполнение процесса и нарушает стабильную работу системы.Также важно понимать, можно ли заранее выявить все компоненты, которые средство предотвращения атак может вывести из строя. Например, в случае с санитайзером Integer Overflow очень сложно предсказать риски, не проводя масштабного тестирования, потому что трудно определить, какие целочисленные переполнения являются намеренными (разрешенными), а какие – могут вызвать уязвимости.
Поддержка
Необходимо рассматривать не только возможные проблемы при развертывании средств предотвращения атак, но и особенности их поддержки в долгосрочной перспективе. Мы оцениваем время, необходимое, чтобы интегрировать средство с существующими системами, активировать и отладить его, развернуть на устройствах, а затем обслуживать после запуска. Технология SELinux – это хороший пример. Чтобы создать набор правил, требуется много времени и сил. И этот набор нужно поддерживать годами, невзирая на изменения кода, а также добавление или удаление отдельных функций.
Мы стремимся к тому, чтобы средства предотвращения атак минимально влияли на стабильность работы и чтобы у разработчиков была вся необходимая информация. Для реализации этих целей мы улучшаем текущие алгоритмы, чтобы уменьшить число ложных срабатываний, и публикуем документацию на странице source.android.com. Упростив отладку в случае сбоев, можно снизить нагрузку на разработчиков при обслуживании. Например, чтобы было проще обнаружить ошибки санитайзера UBSan, мы по умолчанию добавили в систему сборки Android поддержку минимального времени выполнения UBSan. Изначально минимальное время выполнения было добавлено другими разработчиками Google специально для этой цели. При сбое программы из-за санитайзера Integer Overflow в сообщение об ошибке SIGABRT добавляется следующий фрагмент:
Abort message: 'ubsan: sub-overflow'
Увидев это сообщение, разработчики поймут, что необходимо включить режим диагностики, чтобы распечатать информацию о сбое:
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:2188:32: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'size_t' (aka 'unsigned long')
При этом в SELinux есть инструмент audit2allow, который позволяет предлагать правила, разрешающие те или иные заблокированные операции:
adb logcat -d | audit2allow -p policy
#============= rmt ==============
allow rmt kmem_device:chr_file { read write };
И пусть audit2allow не всегда предлагает правильные варианты, он сильно помогает разработчикам, плохо знакомым с SELinux.
Заключение
В каждом выпуске Android мы предлагаем вам новые инструменты, которые защищают всю экосистему, обеспечивая необходимую производительность и стабильную работу. Важную роль в этом играет анализ данных. Надеемся, что эта статья помогла вам лучше понять, какие сложности возникают при внедрении новых средств предотвращения атак и как мы с ними справляемся.
Благодарим наших коллег и авторов: Кевин Деус, Джоэл Галенсон, Билли Лау, Иван Лосано – специалистов по вопросам безопасности и конфиденциальности данных Android. Отдельная благодарность Звиаду Кардава и Джеффа Ван Дер Ступа за помощь в подготовке статьи.