Wawasan Ahli
26 August 2025

Kerentanan Komunikasi Client-side Android (Part 2)

Kerentanan Komunikasi Client-side Android (Part 2)

Halo semuanya! Pada artikel sebelumnya (Part 1), kita sudah membahas bagaimana komunikasi client-side yang tidak aman antar komponen Android dapat membuka celah serius, khususnya lewat kerentanan Direct Return of Intent Result pada Exported Component. Nah, di Part 2 ini kita akan melanjutkan pembahasan dengan studi kasus baru yang tak kalah berbahaya, yaitu mengenai Mutable Pending Intent — sebuah celah yang sering diremehkan, tetapi bisa dimanfaatkan untuk mengambil alih kontrol aplikasi secara diam-diam. Mari kita bahas bersama!

Kerentanan Komunikasi Client-side Android: Mutable Pending Intent

Static Analysis

Kami menemukan kode menarik pada metode sendIntentToWhatsApp(), di mana sebuah pending intent dengan empty flag (ditandai dengan nilai 0 pada variabel flags) digunakan untuk mengirim sebuah empty base intent, sehingga intent tersebut menjadi mutable jika aplikasi diinstal pada perangkat Android dengan SDK versi kurang dari 31 (< Android 12). Pending intent ini juga diteruskan ke metode sendIntentToWhatsAppForBusiness(). Dengan demikian, mutable pending intent tersebut dikirim ke aplikasi WhatsApp (com.whatsapp) dan WhatsApp for Business (com.whatsapp.w4b) melalui sebuah broadcast intent.

PENTEST 1.JPG

Verifikasi Kerentanan

Hasil static analysis ini cukup jelas: aplikasi mengirimkan mutable pending intent ke WhatsApp dan WhatsApp for Business pada perangkat dengan Android < 12 melalui broadcast intent. Perlu dicatat bahwa pending intent ini dikirim secara spesifik ke kedua aplikasi tersebut; sehingga untuk mengeksploitasi kerentanan ini, kami harus membuat sebuah aplikasi trojan WhatsApp atau WhatsApp for Business dengan mengonfigurasi aplikasi trojan tersebut agar memiliki package name yang sama dengan WhatsApp (com.whatsapp) atau WhatsApp for Business (com.whatsapp.w4b).

PENTEST 2.JPG

Selanjutnya, kami mengembangkan kode untuk aplikasi trojan kami. Kami mendaftarkan sebuah malicious broadcast receiver untuk mendengarkan target broadcast intent dan mengambil pending intent yang dikirim dengan cara menentukan action name yang sama seperti yang dikirimkan ke receiver kami. Kami kemudian mengatur receiver ini agar memiliki prioritas tertinggi untuk menangani broadcast intent pada aplikasi non-privileged, dengan mengonfigurasinya menggunakan priority value 999. Dengan begitu, jika ada aplikasi non-privileged lain yang juga mendengarkan broadcast yang sama, receiver kami akan selalu mendapatkan prioritas untuk menanganinya. Setelah itu, aplikasi trojan ini kami build dan distribusikan ke perangkat Android 11 yang juga telah terinstal aplikasi target. Potongan kode (code snippet) dari aplikasi trojan kami ditampilkan pada gambar di bawah ini.

PENTEST 3.JPG

Agar broadcast intent yang berisi vulnerable pending intent dapat terkirim, pertama-tama kami perlu mempelajari bagaimana cara mengeksekusi metode sendIntentToWhatsapp() dan sendIntentToWhatsAppForBusiness(). Selanjutnya, kami memanfaatkan objection untuk memastikan bahwa kedua metode tersebut benar-benar terpicu dengan cara melakukan hooking pada method yang relevan.

Setelah itu, kami mengakses aplikasi trojan kami untuk mendaftarkan malicious receiver, lalu menjalankan aksi tertentu pada aplikasi target yang memicu terkirimnya broadcast intent oleh aplikasi tersebut. Setelah menemukan aksi yang diperlukan, kami berhasil memahami cara men-trigger potongan kode rentan ini, ditandai dengan metode sendIntentToWhatsAppForBusiness() yang dipanggil (terlihat dari output objection), serta malicious receiver kami yang berhasil menerima vulnerable pending intent dari aplikasi target, ditandai dengan output pada log aplikasi kami.

Mutable Pending Intent
PENTEST 5.JPG

Eksploitasi

Oke, semua sudah siap! Kami berhasil menerima mutable pending intent! Selanjutnya, kami masuk ke tahap eksploitasi dengan melakukan file theft pada file yang sama melalui file provider yang sebelumnya telah dijelaskan.

Kami kemudian memperluas kode pada malicious register untuk membajak pending intent yang diterima dengan cara memodifikasi base intent, menentukan content:// URI dari file target pada objek clipdata, serta menambahkan flag Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION pada intent kami agar dapat memperoleh akses sementara ke file internal aplikasi target.

Setelah itu, kami membuat sebuah malicious activity baru dan memodifikasi base intent untuk mengirimkan implicit intent ke malicious activity kami, dengan menyertakan URI file target beserta permission yang diperlukan. Dari sana, kami berhasil mengambil informasi file yang dicuri, membaca isi file, dan membuang seluruh kontennya ke dalam log aplikasi kami.

Potongan kode akhir dari trojan application kami dapat dilihat pada gambar di bawah ini.

Mutable Pending Intent
Mutable Pending Intent

Setelah melakukan rebuild dan mendistribusikan ulang trojan application ke perangkat, kami mendaftarkan malicious receiver dan menjalankan kembali aksi-aksi yang sebelumnya telah diidentifikasi untuk memicu metode rentan pada aplikasi target. Akhirnya, kami berhasil melakukan file theft pada file yang berada di dalam sandboxed directory aplikasi target melalui trojan application kami, yang ditandai dengan informasi file dan konten yang berhasil dibuang ke application log.LET’S GOO!

Mutable Pending Intent

 

Mitigasi

Bagaimana serangan ini bisa terjadi? Pertama, kita perlu memahami apa itu pending intent dan apa fungsinya. Secara singkat, pending intent adalah sebuah wrapper di sekitar objek Intent yang digunakan untuk memberikan izin kepada aplikasi lain agar bisa menggunakan intent tersebut seolah-olah dijalankan langsung dari proses aplikasi asal.

Mekanisme ini memungkinkan aplikasi pihak ketiga menggunakan intent tanpa aplikasi asal harus membuat exported component. Dengan kondisi tersebut, base intent yang dikirim dari aplikasi target bisa dimodifikasi (mutated) untuk mengirimkan implicit intent ke aplikasi berbahaya seolah-olah berasal dari aplikasi target. Akibatnya, akses sementara ke internal file melalui file provider diberikan karena dijalankan dalam konteks aplikasi target.

Oleh karena itu, mengimplementasikan pending intent dengan konfigurasi immutable flag sangatlah penting setiap kali memungkinkan. Hal ini mencegah base intent dimodifikasi jika berhasil dibajak oleh aplikasi berbahaya, sehingga mampu menggagalkan serangan seperti yang telah didemonstrasikan.

PendingIntent pi = PendingIntent.getActivity(getApplicationContext(), 0, new Intent(), PendingIntent.FLAG_IMMUTABLE);

Namun demikian, jika FLAG_MUTABLE digunakan untuk menghasilkan pending intent yang dapat dioverride, maka explicit intent sebaiknya digunakan untuk base intent guna mencegah pengalihan ke komponen pihak ketiga berbahaya secara sembarangan. Akan tetapi, implementasi ini harus dilakukan dengan sangat hati-hati karena dapat menimbulkan implikasi keamanan lain melalui field base intent yang dimodifikasi (mutated) namun tidak terisi dengan benar. Oleh karena itu, setiap implementasi mutable pending intent harus selalu ditinjau dan dievaluasi secara cermat. 

Intent base = new Intent();

base.setClass(getApplicationContext(), [target_class]);

PendingIntent pi = PendingIntent.getActivity(getApplicationContext(), 0, base, PendingIntent.FLAG_MUTABLE);

Dampak

Kerentanan ini (Direct Return of Intent Result pada Exported Component &  Mutable Pending Intent) memiliki konsekuensi serius terhadap kerahasiaan data korban. Malicious actor yang memperoleh akses tanpa batas ke file sandboxed yang berada di dalam direktori yang diizinkan oleh file provider berpotensi mendapatkan informasi sensitif yang tidak terlindungi dengan membaca isi file, kemudian membuang (dump) konten tersebut ke remote endpoint yang mereka kendalikan. Hal ini dapat menyebabkan kebocoran informasi seperti PII (Personally Identifiable Information), informasi sesi, dan lain sebagainya. Namun, ancamannya tidak berhenti di situ! Malicious actor juga dapat mengakses informasi kontak korban melalui aplikasi yang terdampak jika aplikasi tersebut sudah diberikan izin contacts permission. Dengan begitu, pelaku tidak perlu lagi meminta izin kontak secara langsung dari aplikasi berbahaya mereka sendiri, yang bisa saja menimbulkan kecurigaan pada pengguna.

PENTEST 9.JPG

Selain itu, kedua kerentanan ini juga memungkinkan aplikasi berbahaya mengeksekusi aksi-aksi sensitif dengan menyalahgunakan konfigurasi content providers, seperti yang ditunjukkan dalam referensi berikut: Overscured Blog. Hal ini berpotensi mengganggu integritas dan ketersediaan data. Lebih parahnya lagi, eksploitasi dari kedua kerentanan ini tidak membutuhkan perangkat korban untuk memiliki hak istimewa khusus (rooted), sehingga meningkatkan tingkat keparahan risiko dan kemungkinan serangan berhasil.

Kesimpulan

Studi kasus ini menunjukkan bagaimana komunikasi yang tidak aman antar komponen aplikasi Android dapat menimbulkan konsekuensi serius terhadap security posture aplikasi di sisi client. Serangan yang dilakukan tidak memerlukan perangkat dengan privilege khusus (rooted), sehingga membuatnya semakin relevan dalam lingkungan produksi. Beberapa hal penting yang dapat dipetik baik untuk developer maupun security practitioner adalah sebagai berikut:

Developer

Kerentanan yang ditunjukkan menegaskan kembali pentingnya praktik secure coding seperti melakukan validasi dan sanitasi pada intent data untuk memastikan data yang diterima sesuai harapan serta meminimalkan perilaku yang tidak diinginkan, sekaligus mengimplementasikan pending intent sesuai praktik keamanan terbaik. Selain itu, studi kasus ini juga menekankan pentingnya melindungi data lokal dengan enkripsi guna mengurangi potensi penyalahgunaan data oleh malicious actor.

Security Practitioner

Selalu lakukan analisis mendalam terhadap exported components, karena sering kali terdapat potongan kode menarik yang dapat dimanfaatkan untuk serangan. Exported components memungkinkan sistem operasi maupun aplikasi pihak ketiga memanggil komponen terkait, yang artinya juga memberi peluang bagi malicious actor—dan Anda sebagai tester—untuk menguji seluruh entry point dan perilaku aplikasi guna mengidentifikasi potensi kerentanan. Selain itu, jadilah lebih proaktif; meskipun komponen tidak diekspos, tetap ada kemungkinan kerentanan tersembunyi seperti transmisi mutable pending intent. Intinya: read, read, read! Ada banyak "hidden gems" yang mungkin menunggu untuk ditemukan. Dan terakhir, jangan ragu untuk sedikit berurusan dengan kode.

Current State

Kedua kerentanan yang dibahas telah dilaporkan dan diperbaiki oleh pihak terkait, serta versi patch sudah dipublikasikan di Google Play Store. Apresiasi besar untuk platform dan tim developer Android yang terlibat atas kecepatan dan efektivitas penanganannya.

Referensi:

https://developer.android.com/reference/android/app/PendingIntent

https://developer.android.com/reference/android/app/Activity#setResult(int,%20android.content.Intent)

https://developer.android.com/privacy-and-security/risks/android-exported

https://developer.android.com/privacy-and-security/risks/pending-intent

https://blog.oversecured.com/Gaining-access-to-arbitrary-Content-Providers/

https://blog.oversecured.com/Content-Providers-and-the-potential-weak-spots-they-can-have/#executing-sensitive-actions-in-content-provider

https://segmentfault.com/a/1190000041550819/en

https://nikkoenggaliano.my.id/read.php?id=8