
Mayoritas aplikasi React Native yang berupaya menerapkan mekanisme keamanan sering kali memulai dengan pendekatan seragam: mengintegrasikan pustaka seperti jail-monkey, membaca status boolean, dan memblokir akses pengguna apabila perangkat terindikasi memiliki risiko.
Meskipun tampak sebagai bentuk perlindungan, pada praktiknya, mekanisme ini tidak lebih dari sekadar pencatatan log (glorified logging). Penyerang yang memiliki determinasi tinggi dapat memanfaatkan alat seperti Frida, Magisk, atau memodifikasi paket aplikasi (APK) untuk memanipulasi nilai-nilai boolean tersebut sesuai kehendak mereka. Apabila logika bisnis aplikasi Anda bergantung sepenuhnya pada data sisi klien ini, maka integritas keamanan sistem Anda telah terkompromi.
Artikel ini memosisikan sisi klien (perangkat pengguna) sebagai lingkungan yang tidak dapat dipercaya (hostile environment) dan menguraikan mengapa deteksi root dan hook merupakan kontrol keamanan yang lemah dalam konteks tersebut.
Mulai dengan Model Ancaman (Threat Model)
React Native beroperasi di dalam proses yang sepenuhnya berada di bawah kendali pengguna. Seorang penyerang yang kompeten memiliki kapabilitas untuk:
Diagram alur yang menunjukkan kontrol penyerang terhadap aplikasi
Apabila asumsi ini tidak dijadikan landasan, maka upaya yang dilakukan bukanlah pembangunan keamanan sistem, melainkan sekadar “teater keamanan” (security theater).
Dari premis tersebut, beberapa prinsip fundamental harus ditegakkan:
- Indikator apa pun seperti isRooted, isHooked, atau isDebugged hanyalah data yang berada dalam proses yang tidak tepercaya.
- Logika kondisional apa pun dalam JavaScript yang mengatur akses terhadap aset finansial atau hak istimewa dapat diabaikan atau dimodifikasi.
- Aset yang sesungguhnya berada di sisi backend: akun pengguna, transaksi pembayaran, promosi, tindakan istimewa, dan API.
Mengapa Validasi Sisi Klien Tidak Otoritatif
Pola tipikal yang sering diterapkan: menginstal jail-monkey, mengumpulkan objek risiko, dan melakukan percabangan logika berdasarkan data tersebut.
import JailMonkey from "jail-monkey";
export function getDeviceRiskSignal() {
return {
isJailBroken: JailMonkey.isJailBroken(),
isDebuggedMode: JailMonkey.isDebuggedMode(),
canMockLocation: JailMonkey.canMockLocation(),
isOnExternalStorage: JailMonkey.isOnExternalStorage(),
hookDetected: JailMonkey.hookDetected(),
};
}
Di bagian lain kode:
const risk = getDeviceRiskSignal();
if (risk.isJailBroken || risk.hookDetected || risk.isDebuggedMode) {
// Blokir login, pembayaran, atau tampilkan peringatan
}
Pada perangkat standar, pendekatan ini berfungsi. Namun, pada perangkat yang dikuasai penyerang, ini hanyalah antarmuka pemrograman (API) yang dikendalikan oleh penyerang.
Sebuah hook Frida sederhana pada Android dapat memanipulasi hasil tersebut:
Java.perform(function () {
const JailMonkey = Java.use("com.gantix.JailMonkey.JailMonkeyModule");
JailMonkey.getConstants.implementation = function () {
const original = this.getConstants();
original.put("isJailBroken", false);
original.put("isDebuggedMode", false);
original.put("canMockLocation", false);
original.put("isOnExternalStorage", false);
original.put("hookDetected", false);
return original;
};
});
Untuk demonstrasi lebih mendalam mengenai bagaimana Frida dapat melewati seluruh pemeriksaan tersebut, referensi dapat dilihat pada skrip ini.
Apabila skrip tersebut dijalankan pada aplikasi, setiap pemanggilan fungsi ke JailMonkey akan memberikan informasi palsu yang menguntungkan penyerang. Aplikasi akan menganggap perangkat dalam kondisi aman, padahal sedang dalam instrumentasi penuh.
Segala sesuatu yang dikomputasi murni pada perangkat klien merupakan input yang tidak tepercaya (untrusted input). Data tersebut dapat bermanfaat sebagai sinyal awal, namun tidak boleh dijadikan otoritas final untuk tindakan yang bernilai tinggi.
Pindahkan Penegakan Keamanan ke Backend
Mengingat klien tidak dapat dipercaya, maka penegakan aturan keamanan harus dipindahkan ke backend. Pemeriksaan di sisi klien beralih fungsi dari penentu keputusan menjadi sekadar indikator.
Untuk alur proses yang berisiko tinggi, backend harus memvalidasi tiga aspek krusial sebelum menyetujui permintaan:
- Identitas Perangkat dan Aplikasi: Dari perangkat dan instansi aplikasi mana permintaan ini diklaim berasal?
- Keamanan Saluran Komunikasi: Apakah saluran jaringan terlindungi secara memadai dari intersepsi dan manipulasi?
- Integritas Permintaan (Replay Protection): Apakah permintaan spesifik ini telah digunakan sebelumnya?
Hal ini memetakan pada tiga area strategis:
- Sinyal integritas perangkat dan aplikasi yang sulit dipalsukan (Device Attestation).
- Konfigurasi keamanan transport yang kuat (seperti TLS Pinning).
- Desain protokol permintaan yang resisten terhadap serangan replay.
Detail implementasi teknis bervariasi antar platform, namun prinsip dasarnya tetap konsisten: Server mengambil keputusan berdasarkan bukti yang diverifikasi secara independen oleh server, bukan berdasarkan klaim boolean yang dikirimkan oleh klien.
Validasi Empiris (Red Team Sanity Check)
Pengujian mandiri secara empiris jauh lebih valid dibandingkan presentasi teoretis mana pun.
Lakukan pengujian pada build produksi Anda dengan langkah-langkah berikut:
- Instalasi pada perangkat atau emulator yang telah di-root atau di-jailbreak.
- Lampirkan Frida dan manipulasi seluruh indikator “risiko” menjadi nilai aman (false).
- Lakukan percobaan login, transaksi finansial, atau klaim voucher.
Apabila seluruh proses tersebut masih dapat berjalan tanpa hambatan, hal ini mengindikasikan bahwa backend Anda tidak menegakkan validasi substantif selain mempercayai klaim keamanan dari klien.
Selanjutnya, simulasikan serangan Man-in-the-Middle (MITM) dasar menggunakan alat proksi seperti Burp Suite:
- Instal sertifikat root kustom pada perangkat.
- Lakukan proksi lalu lintas data dan observasi apakah Anda dapat membaca serta memodifikasi permintaan HTTPS dari aplikasi.
Apabila lalu lintas data terlihat jelas dan dapat dimodifikasi, maka keamanan transport sistem Anda lemah dan rentan terhadap intersepsi.
Terakhir:
- Tangkap satu permintaan istimewa yang berhasil (contoh: transfer dana).
- Lakukan replay (pengiriman ulang) permintaan tersebut tanpa melalui antarmuka pengguna (UI) aplikasi.
Apabila backend menerima permintaan tersebut kembali, maka sistem Anda tidak memiliki perlindungan replay yang efektif. Siapa pun yang mampu menangkap satu permintaan valid memiliki kemampuan untuk mengulangi tindakan tersebut.
Kesimpulan
Artikel ini mengadvokasi penghentian kepercayaan implisit terhadap klien dan penyerahan keputusan keamanan kepada klien. Pemeriksaan root, deteksi hook, dan pustaka sejenis dapat tetap dipertahankan, namun hanya berfungsi sebagai sensor data (noisy sensors) yang mengirimkan sinyal ke backend, bukan sebagai gerbang keamanan utama untuk aset finansial atau hak istimewa.
Pekerjaan keamanan yang substantif berada di sisi server: memverifikasi integritas perangkat dan aplikasi melalui attestation, melindungi saluran komunikasi dengan TLS pinning, dan merancang alur sensitif menggunakan perlindungan replay berbasis nonce sehingga permintaan yang tertangkap tidak dapat digunakan kembali.
Tidak ada sistem yang memiliki keamanan absolut, namun penerapan lapisan kontrol ini menjadikan upaya serangan jauh lebih sulit, kompleks, dan memakan biaya tinggi dibandingkan sekadar memanipulasi nilai boolean pada klien yang telah diinstrumentasi.