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
addJavascriptInterfacemenyuntikkan 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).
- Metode
- 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
- Praktik terbaik postMessage()
- Dokumentasi addJavascriptInterface
- Dokumentasi postMessage()
- Dokumentasi WebMessagePort.postMessage()
- Dokumentasi WebViewClient.shouldInterceptRequest
- Dokumentasi saran keamanan terkait addJavascriptInterface
- Dokumentasi clearCache
- Dokumentasi removeJavascript
- Mengaktifkan JavaScript di WebView