Как протектор мобильных приложений прячет уязвимости от хакеров?

Как протектор мобильных приложений прячет уязвимости от хакеров?
image

Автор - Александр Ананикян, аналитик PT MAZE

Введение

Если вы разрабатываете мобильные приложения и хотите защитить их от реверс-инжиниринга, клонирования и поиска уязвимостей, то вас точно заинтересуют протекторы — инструменты, которые затрудняют статический анализ. Применение различных техник запутывания (обфускации) и упаковки кода способно сделать ваше приложения сложнее для взлома злоумышленниками, а то и вовсе отбить у них всякое желание атаковать.

В исследовании мы проанализировали 95 наиболее популярных Android-приложений магазина RuStore с помощью сканера MobSF — популярного инструмента статического анализа с открытым исходным кодом. В среднем число выявляемых уязвимостей сократилось на 40%. Давайте заглянем за сухую статистику и узнаем, что же дало такой эффект.
В этой статье мы разберем:

  • какие части приложения получают наибольший эффект от протектора?
  • какие области приложения остаются открытыми для статического анализа?
  • как минимизировать недостатки разработки?

Анализ небезопасных мест в приложениях

Для наглядности рассмотрим категории, для которых протектор показал высокую степень эффективности: Code, Secrets, Firebase URLs, Network.


Рисунок 1. Доля приложений, в которых обнаружен конкретный тип угроз

Code

Байт-код и ресурсы — это самые распространенные места, которые содержат риски любого уровня критичности, в том числе высокого. Данные области являются настоящим сокровищем для специалистов по реверс-инжинирингу. Сканер показал, что все приложения выборки содержат уязвимость или недостаток в этих местах.

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

Листинг 1. Пример использования небезопасного алгоритма хеширования паролей в исходном коде

	 hash = bytesToHex(MessageDigest.getInstance("MD5").digest(input.toByteArray(StandardCharsets.UTF_8)))

На рисунках ниже представлены фрагменты декомпилированного кода до и после применения шилдинга. Протектор скрыл упоминание хэш-функции MD5: как в строковых параметрах, так и в названиях классов, методов и полей.

Рисунок 2. Фрагмент декомпилированного кода до шилдинга

Рисунок 3. Фрагмент декомпилированного кода после шилдинга

Firebase URLs

Firebase позволяет хранить данные, собирать аналитику, отправлять push-уведомления и удалённо изменять поведение приложения без его обновления через магазин. На практике не все разработчики правильно настраивают Firebase, из-за чего возникают недостатки безопасности — например, включённый Remote Config или неправильная обработка соединений с базой Firebase Realtime Database, что может привести к утечке данных.

На рисунках ниже продемонстрированы фрагменты использования Remote Config в коде и ресурсах приложения.

Рисунок 4. Импорт классов com.google.firebase.remoteconfig.* до шилдинга

Рисунок 5. Пустой результат поиска классов com.google.firebase.remoteconfig.* в приложении после шилдинга

После применения протектора использование классов com.google.firebase.remoteconfig.* стало заметно менее очевидным для статического анализа. Протектор обфусцировал прямые ссылки на соответствующие классы Firebase, из-за чего декомпилятор больше не отображают вызовы Remote Config в явном виде.

Также шифрование значение ресурсов скрыло потенциальный Remote Config key — google_api_key. Это делает статический анализ ещё сложнее: ключ присутствует, но его значение невозможно получить привычными методами анализа ресурсов APK-файла.

Рисунок 6. Значение google_api_key хранится в открытом виде до применения протектора

Рисунок 7. Обфусцированное значение google_api_key после применения протектора

Network

Одной из частых проблем реализации безопасного соединения становится неверная конфигурация файла network_security_config.xml. Разработчики могут случайно разрешить незашифрованный трафик (cleartext traffic) или доверять всем системным сертификатам без уточнения, какие именно должны использоваться. Такие упрощённые параметры делают соединение уязвимым для перехвата данных и атак типа Man-in-the-Middle (MITM).

В данном разделе представлен пример использования приложением встроенных сертификатов @raw/<имя> в файле network_security_config.xml и фрагмент содержимого одного из них.

Рисунок 8. Использование встроенных сертификатов до шилдинга

Рисунок 9. Фрагмент встроенного сертификата до шилдинга

Для усложнения статического анализа было применено переименование имени сертификатов и шифрование их содержимого.

Рисунок 10. Содержимое файла network_security_config.xml после шилдинга

Рисунок 11. Фрагмент встроенного сертификата после шилдинга

Secrets

В приложениях в открытом виде могут оставаться различные секреты: учетные данные, API-ключи, токены интеграций, строки подключения или криптографические ключи в strings.xml, ресурсах res/raw/, бинарных файлах или прямо в исходном коде. Такие данные легко извлекаются из APK-файла и могут быть использованы для несанкционированного доступа к сервисам.

Одним из примеров является хранение в коде строкового значения, которое может заинтересовать злоумышленника из-за схожести с токеном.

Рисунок 12. Строковое значение в коде приложения

Шифрование строк скрыло данный секрет в коде приложения.

Рисунок 13. Пустой результат поиска

Manifest

В приложении существуют места, искажение которых может нарушить работоспособность приложения, поэтому протектор применяется к ним очень точечно. Например, файл AndroidManifest.xml — «оглавление» всего приложения. И хотя протектор может исказить имена классов, некоторые данные остаются в открытом виде в любом случае. Например, ссылка на assetlinks.json.

Рисунок 14. Хранение домена и схемы, на которые привязан App Link

Ложноположительные результаты

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

Далее мы покажем ложноположительное срабатывание MobSF, связанное с якобы отсутствующим на сервере файлом assetlinks.json. Из-за этого сканер ошибочно считает, что злоумышленник может перехватить deep link.

Проверка существования assetlinks.json на сервере была выполнена по сети. В ответе получены идентификатор приложения и отпечаток сертификата SHA-256, которые совпадают с APK-файлом.

Рисунок 15. Проверка существования assetlinks.json

Другим примером такой ситуации является категория Certificate, которая оказалась малопригодной для анализа из-за большого числа ложноположительных срабатываний. Например, MobSF отмечает использование подписи по схеме v1 и автоматически связывает это с уязвимостью Janus, но ручная проверка приложений не подтвердила наличие данного недостатка.

Рисунок 16. Проверка подписи приложения на уязвимость Janus

Выводы

Теперь вы знаете о том, как работают протекторы и на какие участки мобильного приложения они влияют сильнее всего. Протекторы отлично работают с кодом и ресурсами, так как эта часть приложения хорошо поддается модификациям. Скрывать уязвимости, забытые секреты и интеллектуальную собственность в этих местах можно достаточно серьезными техниками. Но как у любой технологии, у протекторов есть границы применения, и это мы хорошо увидели на примере конфигурации AndroidManifest.xml. И хотя протекторы способны сильно усложнить жизнь хакеру и повысить эффективность аппсек-команды, комплексная безопасность приложения все еще лежит на плечах опытного аппсек-инженера, управляющего такими инструментами.

Кстати, мы намеренно использовали бесплатный открытый сканер MobSF, поэтому Вы можете легко повторить данный эксперимент и проверить, как протектор повлияет именно на ваше приложение.

310K
долларов
до 18 лет
Антипов жжет
Ребёнок как убыточный
актив. Считаем честно.
Почему рожают меньше те, кто умеет считать на десять лет вперёд.