Kategori OWASP: MASVS-NETWORK: Komunikasi Jaringan
Ringkasan
DownloadManager adalah layanan sistem yang diperkenalkan di level API 9. Download HTTP yang berjalan lama ditangani dan aplikasi dapat mendownload file sebagai tugas latar belakang. API-nya menangani interaksi HTTP dan mencoba mendownload kembali setelah mengalami kegagalan atau saat melewati perubahan konektivitas dan reboot sistem.
DownloadManager memiliki kelemahan terkait keamanan yang membuatnya menjadi pilihan yang tidak aman untuk mengelola download di aplikasi Android.
(1) CVE di Penyedia Download
Pada tahun 2018, tiga CVE ditemukan dan di-patch di Download Provider. Berikut ringkasan masing-masing (lihat detail teknis).
- Pelewatan Izin Penyedia Download – Tanpa izin yang diberikan, aplikasi berbahaya dapat mengambil semua entri dari Penyedia Download, yang dapat mencakup informasi yang berpotensi sensitif seperti nama file, deskripsi, judul, jalur, URL, serta izin BACA/TULIS penuh ke semua file yang didownload. Aplikasi berbahaya dapat berjalan di latar belakang, memantau semua download dan membocorkan kontennya dari jarak jauh, atau memodifikasi file secara langsung sebelum diakses oleh pemohon yang sah. Hal ini dapat menyebabkan penolakan layanan bagi pengguna untuk aplikasi inti, termasuk ketidakmampuan untuk mendownload update.
- Injeksi SQL Penyedia Download – Melalui kerentanan injeksi SQL, aplikasi berbahaya tanpa izin dapat mengambil semua entri dari Penyedia Download. Selain itu, aplikasi dengan izin terbatas, seperti
android.permission.INTERNET, juga dapat mengakses semua konten database dari URI yang berbeda. Informasi yang berpotensi sensitif seperti nama file, deskripsi, judul, jalur, URL dapat diambil, dan, bergantung pada izin, akses ke konten yang didownload juga dapat dilakukan. - Pengungkapan Informasi Header Permintaan Penyedia Download – Aplikasi
berbahaya dengan izin
android.permission.INTERNETyang diberikan dapat mengambil semua entri dari tabel header permintaan Penyedia Download. Header ini dapat mencakup informasi sensitif, seperti cookie sesi atau header autentikasi, untuk setiap download yang dimulai dari Browser Android atau Google Chrome, di antara aplikasi lainnya. Hal ini dapat memungkinkan penyerang meniru identitas pengguna di platform mana pun tempat data pengguna sensitif diperoleh.
(2) Izin Berbahaya
DownloadManager di level API yang lebih rendah dari 29 memerlukan izin berbahaya –
android.permission.WRITE_EXTERNAL_STORAGE. Untuk level API 29 dan yang lebih tinggi, izin android.permission.WRITE_EXTERNAL_STORAGE tidak diperlukan, tetapi URI harus merujuk ke jalur dalam direktori yang dimiliki oleh aplikasi atau jalur dalam direktori "Download" level teratas.
(3) Ketergantungan pada Uri.parse()
DownloadManager mengandalkan metode Uri.parse() untuk mengurai lokasi download yang diminta. Untuk kepentingan performa, class Uri menerapkan
sedikit atau tidak ada validasi pada input yang tidak tepercaya.
Dampak
Penggunaan DownloadManager dapat menyebabkan kerentanan melalui eksploitasi izin WRITE ke penyimpanan eksternal. Karena izin android.permission.WRITE_EXTERNAL_STORAGE memungkinkan akses luas ke penyimpanan eksternal, penyerang dapat memodifikasi file dan download secara diam-diam, menginstal aplikasi yang berpotensi berbahaya, menolak layanan ke aplikasi inti, atau menyebabkan aplikasi mengalami error. Pihak-pihak berniat jahat juga dapat memanipulasi apa yang dikirim ke Uri.parse() untuk menyebabkan pengguna mendownload file berbahaya.
Mitigasi
Daripada menggunakan DownloadManager, siapkan download langsung di aplikasi Anda menggunakan klien HTTP (seperti Cronet), penjadwal/pengelola proses, dan cara untuk memastikan pencobaan ulang jika terjadi kehilangan jaringan. Dokumentasi library mencakup link ke aplikasi contoh serta petunjuk tentang cara mengimplementasikannya.
Jika aplikasi Anda memerlukan kemampuan untuk mengelola penjadwalan proses, menjalankan download di latar belakang, atau mencoba lagi membuat download setelah kehilangan jaringan, pertimbangkan untuk menyertakan WorkManager dan ForegroundServices.
Contoh kode untuk menyiapkan download menggunakan Cronet adalah sebagai berikut, yang diambil dari codelab Cronet.
Kotlin
override suspend fun downloadImage(url: String): ImageDownloaderResult {
val startNanoTime = System.nanoTime()
return suspendCoroutine {
cont ->
val request = engine.newUrlRequestBuilder(url, object: ReadToMemoryCronetCallback() {
override fun onSucceeded(
request: UrlRequest,
info: UrlResponseInfo,
bodyBytes: ByteArray) {
cont.resume(ImageDownloaderResult(
successful = true,
blob = bodyBytes,
latency = Duration.ofNanos(System.nanoTime() - startNanoTime),
wasCached = info.wasCached(),
downloaderRef = this@CronetImageDownloader))
}
override fun onFailed(
request: UrlRequest,
info: UrlResponseInfo,
error: CronetException
) {
Log.w(LOGGER_TAG, "Cronet download failed!", error)
cont.resume(ImageDownloaderResult(
successful = false,
blob = ByteArray(0),
latency = Duration.ZERO,
wasCached = info.wasCached(),
downloaderRef = this@CronetImageDownloader))
}
}, executor)
request.build().start()
}
}
Java
@Override
public CompletableFuture<ImageDownloaderResult> downloadImage(String url) {
long startNanoTime = System.nanoTime();
return CompletableFuture.supplyAsync(() -> {
UrlRequest.Builder requestBuilder = engine.newUrlRequestBuilder(url, new ReadToMemoryCronetCallback() {
@Override
public void onSucceeded(UrlRequest request, UrlResponseInfo info, byte[] bodyBytes) {
return ImageDownloaderResult.builder()
.successful(true)
.blob(bodyBytes)
.latency(Duration.ofNanos(System.nanoTime() - startNanoTime))
.wasCached(info.wasCached())
.downloaderRef(CronetImageDownloader.this)
.build();
}
@Override
public void onFailed(UrlRequest request, UrlResponseInfo info, CronetException error) {
Log.w(LOGGER_TAG, "Cronet download failed!", error);
return ImageDownloaderResult.builder()
.successful(false)
.blob(new byte[0])
.latency(Duration.ZERO)
.wasCached(info.wasCached())
.downloaderRef(CronetImageDownloader.this)
.build();
}
}, executor);
UrlRequest urlRequest = requestBuilder.build();
urlRequest.start();
return urlRequest.getResult();
});
}
Resource
- Halaman dokumentasi utama untuk DownloadManager
- Laporan untuk CVE DownloadManager
- Pelewatan Izin Android CVE 2018-9468
- Injeksi SQL Penyedia Download Android CVE-2018-9493
- Pelewatan Izin Penyedia Download Android CVE2018-9468
- Halaman dokumentasi utama untuk Cronet
- Petunjuk penggunaan Cronet dalam aplikasi
- Contoh penerapan Cronet
- Dokumentasi untuk Uri
- Dokumentasi untuk ForegroundService
- Dokumentasi untuk WorkManager