WebView – Jembatan native

Kategori OWASP: MASVS-PLATFORM: Interaksi Platform

Ringkasan

Bridge native, yang terkadang dikenal sebagai bridge JavaScript, adalah mekanisme yang memfasilitasi komunikasi antara WebView dan kode native Android, yang dicapai dengan menggunakan metode addJavascriptInterface. Hal ini memungkinkan komunikasi dua arah antara kode JavaScript yang berjalan di WebView dan kode Java aplikasi Android. Metode addJavascriptInterface mengekspos objek Java ke semua frame WebView, dan frame apa pun dapat mengakses nama objek dan memanggil metode di dalamnya. Namun, tidak ada mekanisme bagi aplikasi untuk memverifikasi asal frame panggilan dalam WebView, yang menimbulkan masalah keamanan karena kepercayaan konten tetap tidak ditentukan.

Bridge native juga dapat diimplementasikan dengan channel pesan HTML menggunakan WebViewCompat.postWebMessage atau WebMessagePort.postMessage Android untuk berkomunikasi dengan Window.postMessage JavaScript. WebViewCompat.postWebMessage dan WebMessagePort.postMessage dapat menerima pesan JavaScript yang dikirim melalui Window.postMessage yang akan dieksekusi dalam WebView.

Ada beberapa risiko yang terkait dengan bridge native:

  • Bridge berbasis JavascriptInterface:
    • Metode addJavascriptInterface menyuntikkan objek Java yang disediakan ke setiap frame WebView, termasuk iframe, yang berarti rentan terhadap serangan oleh pihak ketiga berbahaya yang menyuntikkan frame ke situs yang sah. Aplikasi yang menargetkan API level 16 atau yang lebih lama sangat berisiko terkena serangan karena metode ini dapat digunakan untuk mengizinkan JavaScript mengontrol aplikasi host.
    • Memantulkan konten yang disediakan pengguna yang tidak tepercaya di WebView yang mendukung bridge native memungkinkan serangan pembuatan skrip lintas situs (XSS).
  • Bridge berbasis MessageChannel:
    • Tidak adanya pemeriksaan asal pada endpoint channel pesan berarti pesan akan diterima dari pengirim mana pun, termasuk yang berisi kode berbahaya.
    • Java dapat diekspos secara tidak sengaja ke JavaScript arbitrer.

Dampak

Metode addJavascriptInterface, postWebMessage, dan postMessage dapat dimanfaatkan oleh pelaku berbahaya untuk mengakses, memanipulasi, atau menyuntikkan kode yang mereka kontrol ke WebView. Hal ini dapat menyebabkan pengguna dialihkan ke situs berbahaya, memuat konten berbahaya, atau menjalankan kode berbahaya di perangkat mereka yang dapat mengekstrak data sensitif atau mencapai peningkatan hak istimewa.

Risiko: risiko addJavascriptInterface

WebView mengimplementasikan fungsi dasar browser, seperti rendering halaman, navigasi, dan eksekusi JavaScript. WebView dapat digunakan di dalam aplikasi untuk menampilkan konten web sebagai bagian dari tata letak aktivitas. Mengimplementasikan bridge native dalam WebView menggunakan metode addJavascriptInterface dapat menimbulkan masalah keamanan seperti pembuatan skrip lintas situs (XSS), atau memungkinkan penyerang memuat konten yang tidak tepercaya melalui injeksi antarmuka dan memanipulasi aplikasi host dengan cara yang tidak diinginkan, menjalankan kode Java dengan izin aplikasi host.

Mitigasi

Nonaktifkan JavaScript

Dalam skenario saat WebView tidak memerlukan JavaScript, jangan panggil setJavaScriptEnabled dalam WebSettings (misalnya, saat menampilkan konten HTML statis). Secara default, eksekusi JavaScript dinonaktifkan di WebView.

Menghapus antarmuka JavaScript saat memuat konten yang tidak tepercaya

Pastikan objek dari antarmuka JavaScript dihapus dengan memanggil removeJavascriptInterface sebelum konten yang tidak tepercaya dimuat oleh WebView. Misalnya, hal ini dapat dilakukan dalam panggilan ke shouldInterceptRequest.

Kotlin

webView.removeJavascriptInterface("myObject")

Java

webView.removeJavascriptInterface("myObject");

Hanya muat konten web melalui HTTPS

Jika Anda perlu memuat konten yang tidak terpercaya, pastikan WebView memuat konten web melalui koneksi yang dienkripsi (lihat juga panduan kami tentang Komunikasi Teks Biasa). Cegah pemuatan halaman awal agar tidak dilakukan pada koneksi yang tidak dienkripsi dengan menetapkan android:usesCleartextTraffic ke false dalam file AndroidManifest atau melarang traffic HTTP dalam konfigurasi keamanan jaringan. Lihat dokumentasi usesCleartextTraffic untuk mengetahui informasi selengkapnya.

Xml

<application
    android:usesCleartextTraffic="false">
    <!-- Other application elements -->
</application>

Untuk memastikan pengalihan dan penjelajahan aplikasi lebih lanjut tidak terjadi pada traffic yang tidak dienkripsi, periksa skema HTTP di loadUrl atau shouldInterceptRequest:

Kotlin

fun loadSecureUrl(webView: WebView?, url: String?) {
    webView?.let { wv ->  // Ensure valid WebView and URL
        url?.let {
            try {
                val uri = URI(url)
                if (uri.scheme.equals("https", ignoreCase = true)) { // Enforce HTTPS scheme for security
                    wv.loadUrl(url)
                } else {
                    // Log an error or handle the case where the URL is not secure
                    System.err.println("Attempted to load a non-HTTPS URL: $url")
                }
            } catch (e: Exception) {
                // Handle exception for improper URL format
                System.err.println("Invalid URL syntax: $url")
            }
        }
    }
}

Java

public void loadSecureUrl(WebView webView, String url) {
    if (webView != null && url != null) { // Ensure valid WebView and URL
        try {
            URI uri = new URI(url);
            String scheme = uri.getScheme();
            if ("https".equalsIgnoreCase(scheme)) { // Enforce HTTPS scheme for security
                webView.loadUrl(url);
            } else {
                // Log an error or handle the case where the URL is not secure
                System.err.println("Attempted to load a non-HTTPS URL: " + url);
            }
        } catch (URISyntaxException e) {
            // Handle exception for improper URL format
            System.err.println("Invalid URL syntax: " + url);
        }
    }
}

Memvalidasi konten yang tidak tepercaya

Jika ada link eksternal yang dimuat di WebView, validasi skema dan host (domain daftar yang diizinkan). Domain apa pun yang tidak ada dalam daftar yang diizinkan harus dibuka oleh browser default.

Jangan muat konten yang tidak tepercaya

Jika memungkinkan, hanya muat URL dan konten yang dicakup dengan ketat yang dimiliki oleh developer aplikasi ke WebView.

Jangan ekspos data sensitif

Jika aplikasi Anda mengakses data sensitif dengan WebView, pertimbangkan untuk menggunakan metode clearCache untuk menghapus file yang disimpan secara lokal, sebelum menggunakan antarmuka JavaScript. Anda juga dapat menggunakan header sisi server, seperti no-store, untuk menunjukkan bahwa aplikasi tidak boleh menyimpan konten tertentu ke dalam cache.

Jangan ekspos fungsi sensitif

Jika aplikasi Anda memerlukan izin sensitif atau mengumpulkan data sensitif, pastikan aplikasi tersebut dipanggil dari kode dalam aplikasi dan pengungkapan yang jelas diberikan kepada pengguna. Hindari penggunaan antarmuka JavaScript untuk operasi sensitif atau data pengguna apa pun.

Menargetkan API level 21 atau yang lebih tinggi

Salah satu cara aman untuk menggunakan metode addJavascriptInterface adalah menargetkan API level 21 atau yang lebih tinggi dengan memastikan metode tersebut hanya dipanggil saat berjalan di API level 21 atau yang lebih tinggi. Sebelum API 21, JavaScript dapat menggunakan refleksi untuk mengakses kolom publik objek yang disuntikkan.


Risiko: risiko MessageChannel

Kurangnya kontrol asal di postWebMessage() dan postMessage() dapat memungkinkan penyerang mencegat pesan atau mengirim pesan ke pengendali native.

Mitigasi

Saat menyiapkan postWebMessage() atau postMessage(), hanya izinkan pesan dari domain tepercaya dengan menghindari penggunaan * sebagai asal target, dan sebagai gantinya, tentukan domain pengiriman yang diharapkan secara eksplisit.


Resource