Что нужно знать о безопасности мобильных приложений
TL;DR для быстрой проверки
- API и сеть
- Хранение и шифрование данных
- Аутентификация и авторизация
- Безопасность приложения и кода
- WebView и ввод
- Разрешения устройства и чувствительные функции
- Зависимости и обновления
- Мониторинг и обнаружение угроз
Ниже — подробности и практические фрагменты, которые мы реально применяем в Инстадев на коммерческих проектах.
1) API и сеть
Секреты и ключи
- Не хардкодим секреты в репозитории.
- Для локальной разработки используем .env с загрузкой при старте.
- На проде — только удалённые секреты (remote config, KMS, Vault) или инжекция через CI/CD.
Пример инициализации .env:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await dotenv.load(fileName: ".env"); // dev/test только локально
runApp(const App());
}
Важно: .env помогает на деве, но не «прячет» ключи в релизе. Любые встроенные ресурсы можно извлечь. Критичные секреты держим вне клиента.
TLS и SSL-pinning
- Минимум — принудительно https, запрет cleartext.
- Лучше — certificate pinning по SHA-256 отпечатку публичного ключа.
- При несоответствии пина — жёстко останавливаем сетевую активность и показываем экран с причиной.
Серверная часть обязана регулярно обновлять сертификаты; при ротации — готовим запасной пин.
Токены и сессии
- Access-токен живёт коротко. Refresh-токен защищённо хранится, обновление — строго по 401/403 или явному флагу истечения.
- Реализуем контролируемый рефреш и одноразовость refresh-токенов на бэке.
- Анти-брутфорс с Rate-Limit на сервере. Клиентское «дросселирование» запросов допустимо как доп. мера UX/защиты.
WebSocket
- Только wss://.
- Авторизация заголовком или query-параметром с короткоживущим токеном.
- Контроль переподключений, таймаутов и бэк-офф.
2) Данные и шифрование
Хранение чувствительных значений
- Ключи, токены, идентификаторы — через flutter_secure_storage.
- Если пишем что-то в локальную БД/файлы — шифруем содержимое на уровне приложения.
Пример службы хранения с шифрованием:class SecureStore {
static const _storage = FlutterSecureStorage();
static final _aes = Encrypter(AES(Key.fromUtf8("16characterslong!")));
static final _iv = IV.fromLength(16);
static Future save(String key, String value) async {
final enc = _aes.encrypt(value, iv: _iv).base64;
await _storage.write(key: key, value: enc);
}
static Future read(String key) async {
final enc = await _storage.read(key: key);
if (enc == null) return null;
return _aes.decrypt64(enc, iv: _iv);
}
static Future remove(String key) => _storage.delete(key: key);
static Future clear() => _storage.deleteAll();
}
Локальные БД
- Для SQLite — используем SQLCipher (шифрование на уровне файла).
- Ключ шифрования не храним открыто; защищаем через безопасное хранилище, ротация по событиям безопасности.
3) Аутентификация и авторизация
Базовые правила
- Политика паролей: длина 8–12+, цифры, спецсимвол, заглавная, проверка частых паролей.
- MFA на чувствительных операциях: пароль + одноразовый код или биометрия.
- OAuth2/OIDC с проверкой nonce и state для Web-потоков.
Биометрия
- local_auth как второй фактор.
- Опционально: «быстрый вход» биометрией после первичной авторизации.
Привязка к устройству
- Идентификатор устройства передаём на бэк и связываем с сессией, но не делаем его единственным фактором доверия.
- Учитываем смену устройства и процедуры отвязки.
4) Приложение и код
Обфускация и ужимка
- В релизных сборках включаем minifyEnabled true, shrinkResources true.
- Обновляем правила ProGuard/R8, удаляем логи на проде.
- Для Flutter — используем —obfuscate и —split-debug-info.
Контроль целостности
- Сверка подписи приложения на Android, проверка источника установки.
- На iOS — проверка сред выполнения, отклонение при джейлбрейке.
RASP
- Подключаем RASP-библиотеку, чтобы:
- ловить отладчик
- определять рут/джейл
- фиксировать эмулятор
- отслеживать неофициальные сторы и попытки хука
- На инцидент — телеметрия и безопасное завершение сессии.
5) WebView и ввод
WebView
- Если JavaScript не нужен — отключаем.
- Разрешаем переходы только на доверенные домены.
- Запрещаем отладку WebView в продакшене.
XSS и инъекции
- Санитизируем ввод, особенно если рендерим HTML.
- Запрещаем опасные методы, если включён JS.
- Проверяем схемы ссылок и внешний переход.
Поля ввода
- Для чувствительных полей можно отключить копипаст, автозаполнение, буфер обмена.
- Форматтеры для числовых полей и валидаторы длины/масок.
6) Разрешения и функции устройства
Разумные разрешения
- Просим только то, без чего функционал не работает.
- Пересматриваем перечень на каждом релизе.
- Для Android — android:usesCleartextTraffic="false", сеть через networkSecurityConfig.
Защита экрана
- Блокируем скриншоты/запись экрана на экранах с чувствительными данными (Android — FLAG_SECURE).
- На iOS — минимизируем утечки через превью/мультизадачность.
Оверлеи и tapjacking
- Отслеживаем системные оверлеи.
- Блокируем взаимодействие при подозрительных индикаторах.
7) Зависимости и обновления
Контроль уязвимостей
- Регулярно запускаем проверку устаревших пакетов (flutter pub outdated) и обновляем.
- В CI подключаем анализ уязвимостей зависимостей (Snyk, OWASP Dependency-Check для Android-части).
- Избегаем малоизвестных пакетов без поддержки и комьюнити.
Политика обновлений
- Плановые минорные апдейты раз в спринт или месяц.
- Срочные патчи — сразу после публикации критичных CVE.
8) Мониторинг и обнаружение угроз
Краш-репорты и логи
- Crashlytics/Sentry для сборки фатальных и нефатальных ошибок.
- Для событий безопасности — отдельные маркеры и алерты.
- Логи без PII. Никаких токенов, паролей и полных запросов в прод-логах.
Поведенческие сигналы
- Аномальное число неудачных входов, подозрительные регионы, массовые попытки восстановления — отправляем на антифрод/блокировку.
- Для финансовых операций — требуем повторную проверку фактора.
Типовые ошибки, которые мы чаще всего видим
- Хардкод секретов и «тестовых» ключей в релизе.
- Долгоживущие access-токены без refresh и отзыва.
- Включённый JavaScript в WebView «по умолчанию».
- Открытые http-эндпоинты и разрешённый cleartext.
- Отсутствие RASP и проверок среды выполнения.
- Необновлённые зависимости с известными CVE.
Мини-чек-лист перед релизом
- Сеть: https, pinning, обработка истёкших токенов.
- Данные: secure storage, шифрование БД, очистка при логауте.
- Логин: политика паролей, MFA, биометрия как доп. фактор.
- Код: обфускация, удаление логов, проверка подписи.
- WebView: JS off, вайтлист доменов, запрет отладки.
- Устройство: минимум разрешений, FLAG_SECURE, защита от оверлеев.
- Зависимости: апдейты, проверка уязвимостей.
- Мониторинг: Crashlytics/Sentry, алерты по инцидентам.
Что делает Инстадев на проектах
- Внедряем безопасную архитектуру сразу — это дешевле, чем «чинить безопасность в конце».
- Настраиваем CI/CD с проверками уязвимостей и статическим анализом.
- Подключаем RASP и сценарии реакции на угрозы.
- Готовим «план Б» для ротации ключей и принудительных логаутов.
- Проводим внутренний аудит и, при необходимости, внешний пентест.
Если нужно, подготовим под ваш продукт чек-лист внедрения с приоритизацией задач, оценкой трудозатрат и рисков. Это повышает шанс прохождения модерации стора и снижает операционные инциденты после релиза.