Webview – Pemuatan URI Tidak Aman

Kategori OWASP: MASVS-CODE: Kualitas Kode

Ringkasan

Pemuatan URI yang Tidak Aman terjadi saat aplikasi Android gagal mengevaluasi validitas URI dengan benar sebelum memuatnya ke WebView.

Alasan yang mendasari jenis kerentanan ini adalah bahwa URI terdiri dari beberapa bagian, yang setidaknya, skema dan host (dari bagian otoritas) harus terverifikasi (misalnya diizinkan) sebelum URI dimuat ke WebView atau digunakan secara internal oleh aplikasi.

Kesalahan yang paling umum meliputi:

  • Memeriksa host, tetapi tidak memeriksa skema sehingga penyerang dapat menggunakan skema seperti http://, content://, atau javascript:// dengan host yang diautentikasi.
  • Gagal mengurai URI dengan benar, terutama ketika URI diterima sebagai string.
  • Memvalidasi skema, tetapi tidak memvalidasi host (validasi host tidak memadai).

Terkait dengan kasus terakhir, hal ini biasanya terjadi saat aplikasi perlu mengizinkan subdomain arbitrer dari domain primer. Jadi, meskipun nama host telah diekstrak dengan benar, aplikasi akan menggunakan metode seperti startsWith, endsWith,, atau contains dari class java.lang.String untuk memvalidasi keberadaan domain primer di bagian string yang diekstrak. Jika tidak digunakan dengan benar, metode ini dapat menyebabkan hasil yang salah dan memaksa aplikasi untuk memercayai host yang berpotensi berbahaya.

Dampak

Dampak dapat bervariasi bergantung pada konteks tempat host digunakan. Memuat URI berbahaya (yaitu yang mengabaikan pemfilteran/daftar yang diizinkan) di WebView berpotensi menyebabkan pengambilalihan akun (mis. menggunakan phishing), eksekusi kode (mis., memuat JavaScript berbahaya), atau pembobolan perangkat (mengeksploitasi kode yang dikirimkan menggunakan hyperlink).

Mitigasi

Saat menangani URI string, sebaiknya urai string sebagai URI serta lakukan validasi skema dan host:

Kotlin

fun isUriTrusted(incomingUri: String, trustedHostName: String): Boolean {
    try {
        val uri = Uri.parse(incomingUri)
        return uri.scheme == "https" && uri.host == trustedHostName
    } catch (e: NullPointerException) {
        throw NullPointerException("incomingUri is null or not well-formed")
    }
}

Java

public static boolean isUriTrusted(String incomingUri, String trustedHostName)
    throws NullPointerException {
        try {
            Uri uri = Uri.parse(incomingUri);
            return uri.getScheme().equals("https") &&
            uri.getHost().equals(trustedHostName);
        } catch (NullPointerException e) {
            throw new NullPointerException(
                "incomingUri is null or not well-formed");
        }
    }

Untuk validasi host, setelah mengisolasi bagian URI yang sesuai, sebaiknya lakukan validasi host sepenuhnya (bukan sebagian) guna mengidentifikasi secara akurat apakah host dipercaya atau tidak. Jika penggunaan metode seperti startsWith atau endsWith tidak dapat dihindari, sebaiknya gunakan sintaksis yang benar dan tidak mengabaikan karakter atau simbol yang diperlukan (misalnya, endsWith memerlukan karakter titik "." sebelum nama domain untuk pencocokan yang akurat). Tidak mencantumkan karakter ini dapat menyebabkan pencocokan yang tidak akurat dan membahayakan keamanan. Karena subdomain dapat disusun bertingkat tanpa batasan, pencocokan ekspresi reguler bukanlah strategi yang direkomendasikan untuk memvalidasi nama host.

Referensi