Как обеспечить безопасность при обмене данными через ContentProvider в Android
Что проверяют
Знаете ли вы, какие рычаги у ContentProvider есть в манифесте и в коде, и понимаете ли, что главная защита это закрытый по умолчанию провайдер, а не шифрование. Следом обычно спрашивают, как отдать другому приложению один файл, не открывая провайдер целиком.
Как отвечать
Идите от манифеста к коду:
android:exported: если провайдер не нужен другим приложениям, ставьтеfalse. ПриtargetSdkVersion17 и выше это и так дефолт, но лучше писать явно;- разрешения:
android:readPermissionиandroid:writePermissionотдельно на чтение и запись или общийandroid:permission. Своё разрешение объявляйте сandroid:protectionLevel="signature", тогда доступ получат только приложения, подписанные вашим ключом; <path-permission>: отдельные разрешения для отдельных путей URI;- временные гранты:
android:grantUriPermissions="true"и флагFLAG_GRANT_READ_URI_PERMISSIONв интенте дают доступ к одному URI без постоянного разрешения. Для файлов готовое решение этоFileProviderиз AndroidX: ссылкаfile://наружу начиная с Android 7 вызываетFileUriExposedException; - проверки в коде:
getCallingPackage(),Binder.getCallingUid()иcheckCallingPermission()внутриquery(),insert()иopenFile(); - защита от инъекций:
selectionс плейсхолдерами?и массивомselectionArgs, никакой конкатенации строк в SQL. Проекцию и сортировку сверяйте с белым списком, уSQLiteQueryBuilderвключайтеsetStrict(true)иsetProjectionMap().
Шифрование данных на диске это отдельная задача: от приложения, которому вы сами выдали разрешение, оно не спасает.
Где спотыкаются
Экспортируют провайдер «на всякий случай» без разрешений. Любое приложение на устройстве читает и пишет данные через ContentResolver.
Объявляют своё разрешение с уровнем normal. Такое разрешение система выдаёт любому приложению, которое просто указало его в манифесте, то есть защиты нет.
В openFile() строят путь к файлу из сегмента URI без нормализации. Запрос с ../ выводит за пределы разрешённого каталога, поэтому канонический путь нужно сравнивать с корневым каталогом провайдера.