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

Как протектор мобильных приложений прячет уязвимости от хакеров?
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, поэтому Вы можете легко повторить данный эксперимент и проверить, как протектор повлияет именно на ваше приложение.

Записи всех вебинаров марафона PT NGFW теперь онлайн

Реклама. 18+ АО «Позитив Текнолоджиз», ИНН 7718668887