Мобильные
Android: allowBackup, cleartext-трафик и network security config
Три настройки в AndroidManifest часто становятся находками мобильной экспертизы. Как правильно настроить резервное копирование, незашифрованный трафик и доверие к сертификатам.
· 7 мин. чтения

Многие свойства безопасности Android-приложения задаются не в коде, а в AndroidManifest.xml и нескольких
XML-файлах. Они выглядят мелочами, но на мобильной экспертизе часто выходят отдельными находками. Готовя
Android-приложение нашего собственного продукта к экспертизе, мы пересмотрели три настройки: резервное
копирование (allowBackup), незашифрованный HTTP-трафик и конфигурацию сетевой безопасности.
Эти настройки соответствуют разделам MASVS-STORAGE и MASVS-NETWORK стандарта OWASP MASVS.
1. allowBackup: данные не должны уходить в резервную копию
По умолчанию Android может делать резервную копию данных приложения (SharedPreferences, базы данных, внутренние
файлы) — в облако или на компьютер через adb backup. Если в приложении хранятся токены, сессии или
персональные данные, они покидают устройство и могут быть восстановлены на другом.
Для приложения, работающего с финансовыми или персональными данными, самый безопасный вариант — отключить резервное копирование:
<application
android:allowBackup="false"
android:fullBackupContent="false"
android:dataExtractionRules="@xml/data_extraction_rules"
... >
На Android 12 (API 31) и выше вместе с allowBackup учитывается и dataExtractionRules. Поэтому создайте файл
res/xml/data_extraction_rules.xml и исключите данные как из облачной копии, так и из переноса между
устройствами:
<?xml version="1.0" encoding="utf-8"?>
<data-extraction-rules>
<cloud-backup>
<exclude domain="root" path="." />
<exclude domain="file" path="." />
<exclude domain="database" path="." />
<exclude domain="sharedpref" path="." />
<exclude domain="external" path="." />
</cloud-backup>
<device-transfer>
<exclude domain="root" path="." />
<exclude domain="file" path="." />
<exclude domain="database" path="." />
<exclude domain="sharedpref" path="." />
<exclude domain="external" path="." />
</device-transfer>
</data-extraction-rules>
Отключение резервного копирования — только первый шаг. На экспертизе у нас была отдельная находка высокого
уровня: чувствительные данные хранились во внутренней памяти в незашифрованном виде. Мы закрыли её переходом на
flutter_secure_storage (на Android — шифрование на основе Keystore). То есть даже при отключённом бэкапе данные
на устройстве всё равно должны быть зашифрованы.
2. Cleartext-трафик: только HTTPS
Начиная с Android 9 (API 28), при targetSdkVersion 28 и выше незашифрованный HTTP-трафик по умолчанию
блокируется. Но на практике его часто включают обратно: на время разработки добавляют
usesCleartextTraffic="true" для подключения к локальному серверу и забывают убрать в release.
Укажите это в манифесте явно:
<application
android:usesCleartextTraffic="false"
android:networkSecurityConfig="@xml/network_security_config"
... >
Проверьте и сам код. В нашем отчёте была находка низкого уровня «небезопасные (http) ссылки»: в коде остались
несколько адресов, начинающихся с http://. Даже если они не используются, статический анализ их находит.
Поищите по всему проекту:
grep -rn "http://" lib/ android/app/src/main/ --include=*.dart --include=*.kt --include=*.java --include=*.xml
Пространства имён XML (http://schemas.android.com/...) — это нормально, не путайте их с сетевыми адресами.
3. Network security config: кому мы доверяем
network_security_config.xml определяет, каким сертификатам доверяет приложение и какие правила действуют для
каких доменов. Находка «небезопасная проверка сертификата» была у нас высокого уровня. Чтобы закрыть её, мы
применили такую конфигурацию:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="false">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
<domain-config cleartextTrafficPermitted="false">
<domain includeSubdomains="true">api.example.uz</domain>
<pin-set expiration="2027-06-30">
<pin digest="SHA-256">BASE64_ROOT_CA_PIN_1=</pin>
<pin digest="SHA-256">BASE64_ROOT_CA_PIN_2=</pin>
</pin-set>
</domain-config>
</network-security-config>
Что здесь важно:
- Только
system-сертификаты. Если добавить<certificates src="user" />, приложение будет доверять любому сертификату, установленному пользователем, — а это упрощает перехват трафика через прокси. - Pin-set. Мы закрепили не сертификат сервера, а конкретные корневые CA. Тогда при каждом обновлении серверного сертификата не нужно выпускать новую версию приложения. Ставьте минимум два пина (основной и резервный).
expiration. После этой даты проверка пинов отключается, и приложение продолжает работать. Это защищает старые необновлённые версии от «блокировки». Выбирайте дату в соответствии с планом релизов.debug-overrides. Если для разработки нужен прокси, разрешайте его только внутри<debug-overrides>— в release-сборке это не действует.
В Flutter-приложении есть тонкость: HTTP-клиент Dart не полностью использует сетевую конфигурацию Android.
Поэтому мы сделали pinning в два слоя: на Android — pin-set, в Dart — SecurityContext, в который загружены
только доверенные корневые сертификаты.
Ещё две небольшие, но полезные проверки
android:debuggable— убедитесь, что в манифесте вручную не прописаноtrue. Release-сборка автоматически ставитfalse, но явно заданное значение может это нарушить.android:exported— укажите явно для каждогоactivity,service,receiver. Компоненты, которые не должны вызываться внешними приложениями, должны иметьexported="false".
Как проверить настройки на практике
Написать конфигурацию недостаточно — нужно убедиться, что она работает. Установите на тестовое устройство
пользовательский сертификат и пропустите трафик через прокси: release-сборка должна отказать в соединении. Затем
проверьте, что данные приложения не извлекаются через adb backup или резервную копию устройства. Экспертиза
проводит такие же практические проверки, поэтому полезно знать результат заранее.
Короткий чек-лист
- Настроены
allowBackup="false"иdata_extraction_rules.xml. - Чувствительные данные — в зашифрованном хранилище на основе Keystore.
usesCleartextTraffic="false", в коде не осталось адресовhttp://.network_security_config.xml: толькоsystem-сертификаты, естьpin-setиexpiration.- Отладочные настройки — только внутри
debug-overrides. - Значения
debuggableиexportedпроверены.
Сканирование
Хотите проверить манифест и сетевые настройки до экспертизы? Отправьте APK на сканирование. ИИ-агент Claude просмотрит конфигурацию, а наш специалист подтвердит результат и точно покажет, какие строки нужно изменить.


