ПОЧЕМУ БЕЗОПАСНОСТЬ ТАК ТРУДНО ПОСТРОИТЬ
Реализация безопасности в проектах Android
Помните: невозможно обеспечить полную безопасность. Цель не в том, чтобы сделать приложение «пуленепробиваемым», а в том, чтобы максимально замедлить работу хакеров и сделать недействительными все их действия при каждом выпуске.
Тип атак и меры противодействия
Человек посередине - это прокси между вашим приложением и сервером. Перехват всех запросов и изменение данных в обоих направлениях. Примеры: замена сертификатов TLS / SSL на пользовательские, управляемые кодом прокси, и шифрование / дешифрование / повторная упаковка всех данных на стороне сервера. HTTPS может поднять планку для этих сценариев.
Как предотвратить:
- Привязка сертификатов (проверка сертификатов подключения к серверу). Используйте сертификаты от «известных» поставщиков, например Amazon.
- Прозрачность сертификатов (https://github.com/babylonhealth/certificate-transparency-android или https://github.com/google/conscrypt)
- Включать использованный отпечаток сертификата в тело каждого запроса (позволяет серверной стороне также проверять, что клиент не находится под контролем хакеров)
- Протокол динамической безопасности (в процессе связи сервер может запросить переход на новый тип шифрования / подписи / секрета / вызова)
Пропущенные компоненты:
- Довольно часто разработчик забывает, что атака может быть начата с уровня DNS, поэтому разрешение доменного имени также должно быть защищено. Разработчики должны подумать об использовании TlsDNS или HttpsDNS с закреплением сертификатов.
- Проверьте всю цепочку сертификатов, а не только последний (проверьте от корневого сертификата до сертификата вашей компании). Если возможно, время от времени «меняйте» сертификаты (или используйте ограниченные по времени сертификаты, действительные только в течение короткого периода времени).
Изменения структуры данных - хакеры фактически перехватывают ваше общение и теперь пытаются ввести данные, которые могут вам навредить.
Как предотвратить:
- Зашифровать тело всех запросов (усложнить хакерам обнаружение структур данных, используемых в вызовах API)
- Включать в код подтверждения тела (также известный как подписывание), который позволяет обнаруживать изменения в данных на стороне сервера (общий для oAuth1)
- Используйте динамические структуры данных, которые переключаются на основе ответа протокола «рукопожатия» сервера. Самый простой способ - ввести в каждую используемую структуру данных несколько необязательных полей / свойств, которые мы начинаем заполнять чем-то, вычисленным во время выполнения, и это можно легко проверить на стороне сервера.
- Используйте динамическое шифрование / преобразование, которое контролируется сервером, сервер в любой момент может запросить переключатель шифрования, кроме того, для переключения на другую точку входа. (Расшифровка для хакеров - очень трудоемкий процесс)
Пропущенные компоненты:
- Защита структур данных довольно сложна, обратный инжиниринг или общедоступный API могут легко уничтожить эти меры, вы можете создавать структуры данных со многими «зарезервированными» полями, использование которых довольно скрыто в логике кода.
- Как можно чаще используйте этапы обфускации и оптимизации, proguard может значительно изменить структуру классов и усложнить извлечение логики. Вы также можете рассмотреть dexguard, платную версию, эквивалентную proguard.
Человек против бота - хакеры автоматизируют свою работу, им нужно сделать тысячи попыток, прежде чем они найдут решение, которое преодолеет все наши «стены безопасности». Делать вещи вручную - это не способ для них.
Как предотвратить:
- Записывайте сеансы каждого пользователя и сравнивайте сеансы друг с другом. Если мы видим абсолютно идентичные сеансы / действия со стороны пользователя - велика вероятность, что мы увидим «бота» в действии. Человек не может повторять действия одинаково. Есть несколько компаний, которые могут помочь вашему приложению обнаруживать трафик ботов.
- Re-captcha. Убедитесь, что вы взаимодействуете с человеком, а не с роботом.
- Убедитесь, что вы действительно общаетесь с реальным устройством, а не с эмулятором. (Идентификаторы: рутированное устройство, обнаружена виртуализация, странный мобильный оператор или нет). Проверка может быть основана на протоколе OTP (One Time Pass). SMS / Push-сообщение / токен аутентификации и т. Д. С одноразовым кодом доступа.
- Запросы на замедление с IP-адресов, которые не принадлежат интересующим вас странам (рынки, которые вы не поддерживаете). Зачем замедляться вместо того, чтобы отрицать? Ответ короткий - люди любят путешествовать.
- Биометрия - используйте биометрические данные для подтверждения того, что «перед вами» находится человек, а не робот. Отпечаток пальца, собственноручная подпись и т. Д.
- Случайные проверки безопасности с откатом к взаимодействию с пользователем (покажите картинку с простым математическим действием и попросите пользователя решить ее)
- Kill-переключение на конкретного пользователя, конкретное устройство, конкретный IP-адрес страны
- Старайтесь избегать любых операций автоматического входа в систему. Сделать возможным отключение автоматического входа для конкретного пользователя.
Пропущенные компоненты:
- Ложное обнаружение. Иногда пользователей принимают за роботов. Проверки добавляют трение, поэтому всегда помните о простоте. В худшем случае не разрывайте соединение, дайте пользователю возможность доказать, что это человеческое взаимодействие, откат к reCaptcha.
Спуфинг API - можно рассматривать как подтип DDoS-атаки. Хакеры пытаются создать проблемы, «съедая» ваши ресурсы / бюджеты масштабирования ИЛИ рассылая ваш API неверными данными. Под атакой могут быть ваши точки входа в API: ваш серверный API, ваши аналитические сервисы, SDK сторонних поставщиков.
Как предотвратить:
1. Скройте API client_id в коде (это должно быть секретом, но на самом деле их довольно легко найти в большинстве приложений). Лучшим подходом на сегодняшний день является использование методов «обфускации», извлекающих секрет в последний момент перед его использованием. Это предотвратит автоматическое извлечение этих секретов из вашего кода и замедлит хакеров, а также заставит их прочитать код, подвергнутый обратному проектированию.
2. Разрешить звонки только от «доверенных» клиентов. Проверяйте вызовы API на нескольких уровнях: включайте отпечаток сертификата двоичной подписи в запросы (заголовок или тело. Помните, что заголовки HTTP-запросов не зашифрованы, могут быть только значения полей). Убедитесь, что у всех вызовов есть действительный client_id.
3. Секретное вращение. Для каждого выпуска делайте ротацию / замену секрета на новое значение. Если сам секрет нельзя заменить новым, вам следует обновить методы / константы обфускации.
4. Переключатель Kill - устаревшие версии и принудительное использование клиентами последней наиболее защищенной версии приложения. (Рекомендуемое время - 90 дней)
5. Скройте весь аналитический трафик, лучший подход - направить трафик на собственный сервер, а на стороне сервера перенаправить трафик на необходимый аналитический сервер (-ы).
Пропущенные компоненты:
- Спуфинг API - это сложнее всего предотвратить, он всегда основан на обратной инженерии кода приложения. Лучшее из того, что вы, как разработчик, можете сделать - это усложнить чтение и понимание кода.
- React Native может иметь собственный код на нескольких уровнях: код JavaScript, Java / Kotlin и C / C ++. Внедрение шифрования / дешифрования, которое затрагивает все три уровня, сделает работу хакера чрезвычайно сложной и увеличит сложность (техническую глубину) до экстремальных уровней.
- Ротация секретов всегда связана с «паролями» и собственными «секретами API». Разработчики довольно часто забывают о сторонних API из-за использования SDK этих сторонних поставщиков. Правда в том, что сторонние библиотеки SDK имеют абсолютно те же риски безопасности, что и ваше собственное приложение. Потеря аналитики сделает «бизнес слепым», а это может стоить больше денег, чем что-либо другое. Хакер может подделать API вашего поставщика аналитики и повредить ваши данные или даже вызвать чрезмерную реакцию со стороны поставщика (например, заблокировать проект / учетную запись на панели инструментов поставщика). Хороший подход - разделить данные аналитики между несколькими учетными записями / проектами по некоторым критериям - по платформам, по годам… что позволит минимизировать потери, если это произойдет.
- Сохраните разные настройки тайм-аута для операций входа и выборки (доступа к данным) после аутентификации. API входа / регистрации являются наиболее частыми объектами атак.
- Не используйте «динамические запросы» со стороны приложения. Все схемы данных запросов должны быть предопределены. Не позволяйте хакерам свободу действий (если они дошли до этой точки).
Backend защита
- Обнаруживать аномалии в трафике, атаки методом «грубой силы», регулировать время отклика для разных IP-адресов (стран). Сохраните экземпляры с высоким уровнем ресурсов для основных стран и один экземпляр с низким уровнем ресурсов для «не приоритетных» вещей. Атаки часто выполняются с нескольких IP-адресов, расположенных в разных странах, в худшем случае они будут DDoS-атакой только на «малоресурсный» экземпляр. Другой интересный подход - вместо 403 возврата к «источнику атаки» - «таймаутам» TCP сокет часто имеет таймауты от 30 секунд до 10 минут. Динамические таймауты позволят снизить нагрузку на серверы.
- Брандмауэр все запросы, которые не соответствуют вашему «отпечатку пальца» (версия приложения, заголовки, сертификаты и т. Д.)
- Проверьте конфигурацию на стороне сервера, удалите все СЛАБЫЕ шифры из списка разрешенных.
Защита от обратного проектирования
- Запутать код на максимально возможном уровне (что может усложнить тестирование приложения)
- Используйте все три уровня кода: JavaScript, Java / Kotlin и C / C ++. Сделайте техническую глубину очень высокой для хакеров. (я говорю о проектах React Native!)
- Исключить из двоичных файлов все ненужные файлы (* .properties, * .version). Не давайте хакерам никаких подсказок о том, какие версии библиотек используются.
- Используйте GuardedStrings для хранения «секретной» информации в памяти, скрывайте информацию от любого инструмента поиска в памяти.
- Используйте обфускации для кода React Native, сделайте несколько преобразований (uglify, obfuscate, randomize)
- Внедрить автоматическую проверку уязвимостей (https://medium.com/@appmattus/android-security-scanning-your-app-for-known-vulnerabilities-421384603fc5)
Послесловие
Реализация всех этих подходов в вашем проекте - довольно сложная задача. Поэтому, даже если у вас нет ресурсов / возможностей для реализации всех из них, помните о них при определении архитектуры и дизайна. Это сэкономит вам много времени и позволит уберечь бизнес от «неотложных» кризисов. Спасибо, что прочитали это.