Pendahuluan
JSON Web Token (JWT) telah menjadi mekanisme autentikasi yang hampir universal dalam aplikasi modern, terutama untuk API dan aplikasi mobile. Kesederhanaannya dalam teori, token yang berisi klaim tentang pengguna yang bisa diverifikasi tanpa state di server, menjadikannya pilihan yang sangat populer.
Tapi popularitas ini disertai dengan masalah yang konsisten: implementasi JWT yang salah sangat umum, dan konsekuensinya bisa sangat serius. Dalam engagement pengujian keamanan API dan aplikasi mobile, JWT yang salah diimplementasikan adalah temuan yang kami temukan secara reguler.
Artikel ini membahas bagaimana JWT bekerja, kerentanan yang paling sering muncul dari implementasi yang tidak tepat, dan bagaimana seharusnya JWT diimplementasikan.
Bagaimana JWT Bekerja
JWT terdiri dari tiga bagian yang dipisahkan oleh titik: header, payload, dan signature. Header menyatakan tipe token dan algoritma yang digunakan untuk signing. Payload berisi klaim, yaitu pernyataan tentang entitas (biasanya pengguna) dan data tambahan. Signature memverifikasi bahwa token tidak diubah sejak diterbitkan.
Keamanan JWT bergantung sepenuhnya pada integritas signature. Jika signature valid, server mempercayai klaim dalam payload. Jika signature bisa dipalsukan atau dimanipulasi, seluruh mekanisme autentikasi runtuh.
Kerentanan yang Paling Sering Ditemukan
1. Algorithm Confusion: none Algorithm
Ini adalah kerentanan klasik yang seharusnya sudah tidak ditemukan di tahun ini, tapi masih muncul. JWT mengizinkan penentuan algoritma signing di dalam header token itu sendiri. Jika library yang digunakan tidak memvalidasi algoritma yang diizinkan, attacker bisa mengubah header untuk menggunakan algoritma none, yang berarti tidak ada signature sama sekali.
Dengan memodifikasi payload token untuk mengubah klaim (misalnya mengubah role: user menjadi role: admin) dan menghilangkan signature, attacker bisa membuat token yang diterima sebagai valid oleh server yang rentan.
Kerentanan none algorithm ini kerap ditemukan dalam engagement nyata. Begitu ditemukan, kerentanan ini bisa dieksploitasi relatif cepat karena termasuk salah satu kerentanan JWT yang paling sederhana untuk dicek dan dieksploitasi. Tidak perlu tooling khusus atau brute force; cukup ubah header, hapus signature, lalu kirim ulang request. Itu sebabnya kerentanan ini tetap layak jadi item pertama yang dicek di setiap assessment, meskipun sudah lama dikenal di komunitas security.
2. Algorithm Confusion: RS256 ke HS256
Kerentanan yang lebih canggih tapi juga cukup sering ditemukan adalah confusion antara algoritma RS256 (asymmetric, menggunakan private key untuk signing dan public key untuk verifikasi) dengan HS256 (symmetric, menggunakan secret yang sama untuk signing dan verifikasi).
Jika server menggunakan RS256 tapi menerima HS256, attacker bisa menggunakan public key (yang memang publik) sebagai HMAC secret untuk membuat token yang diterima sebagai valid. Public key biasanya mudah didapatkan dari endpoint JWKS atau dari sertifikat SSL server.
3. Weak Secret Key
JWT yang menggunakan algoritma HS256 dengan secret key yang lemah rentan terhadap offline brute force. Setelah mendapatkan token yang valid, attacker bisa mencoba ribuan secret key per detik menggunakan tools seperti hashcat atau john the ripper dengan wordlist yang tepat.
Secret key dengan entropy rendah, secret key yang merupakan string yang mudah ditebak, atau secret key yang secara tidak sengaja terekspos di repositori kode adalah skenario yang sering ditemukan.
Salah satu kasus paling ekstrem yang pernah ditemukan dalam engagement adalah JWT yang ditandatangani dengan secret key kosong. Hasilnya adalah authorization bypass penuh: attacker bisa mengakses data pengguna lain secara sembarang dan melakukan aksi atas nama mereka. Kadang kerentanan JWT tidak butuh teknik canggih untuk dieksploitasi, cukup periksa hal paling dasar seperti apakah secret key-nya benar-benar terisi.
4. Missing atau Inadequate Expiration
Token tanpa masa berlaku atau dengan masa berlaku yang sangat panjang adalah token yang, jika dicuri, bisa digunakan oleh attacker untuk jangka waktu yang tidak terbatas. Tidak ada mekanisme built-in dalam JWT untuk melakukan revocation token yang sudah diterbitkan; satu-satunya cara untuk membatasi dampak dari token yang bocor adalah memastikan token memiliki masa berlaku yang singkat.
Dari keempat kerentanan di atas, algorithm confusion dengan none algorithm adalah yang paling ditemukan penulis dalam engagement kami. Frekuensinya jauh lebih tinggi dibanding weak secret key atau masalah expiration, kemungkinan besar karena kerentanan ini paling mudah diperiksa sekaligus paling mudah luput dari perhatian tim development yang berasumsi bahwa "kalau tidak ada signature yang salah, berarti aman".
5. Sensitive Data dalam Payload
Payload JWT hanya di-encode dengan Base64, bukan dienkripsi. Siapa pun yang mendapatkan token bisa membaca seluruh isi payload-nya. Ini berarti informasi sensitif seperti password, data kartu kredit, atau informasi internal sistem tidak seharusnya ada di dalam payload JWT.
Dalam pengujian, kami sering menemukan payload yang mengandung informasi yang lebih banyak dari yang diperlukan, termasuk data yang seharusnya tidak terekspos ke client.
Implementasi yang Benar
Validasi yang Diperlukan di Sisi Server
Setiap request yang menggunakan JWT harus divalidasi dengan benar di sisi server:
Verifikasi signature dengan algoritma yang eksplisit ditentukan di sisi server, bukan berdasarkan header token. Library yang digunakan harus dikonfigurasi untuk hanya menerima algoritma tertentu.
Verifikasi klaim standar: exp (expiration time) untuk memastikan token belum kadaluarsa, iss (issuer) untuk memastikan token diterbitkan oleh server yang benar, aud (audience) untuk memastikan token memang ditujukan untuk service ini.
Verifikasi klaim custom yang relevan dengan logika otorisasi aplikasi.
Pengelolaan Secret Key
Secret key untuk JWT harus memiliki entropy yang cukup, minimal 256 bit untuk HS256. Key harus disimpan dengan aman menggunakan secrets management yang tepat, bukan di environment variable yang bisa ter-ekspos, dan harus dirotasi secara berkala.
Masa Berlaku yang Wajar
Untuk API yang tidak memerlukan session yang sangat panjang, masa berlaku 15 menit hingga 1 jam sudah cukup untuk access token, dikombinasikan dengan refresh token yang masa berlakunya lebih panjang tapi bisa di-revoke.
Penggunaan JWT Refresh Token dengan Benar
Refresh token memungkinkan pembaruan access token tanpa memerlukan login ulang. Tapi implementasi yang tidak tepat menciptakan kerentanan baru.
Refresh token yang disimpan di localStorage browser rentan terhadap XSS. Refresh token yang tidak memiliki binding ke device atau session bisa digunakan dari device mana saja setelah dicuri. Dan refresh token yang tidak di-revoke saat logout menciptakan window yang bisa dieksploitasi.
Kesimpulan
JWT adalah mekanisme yang solid jika diimplementasikan dengan benar, tapi fleksibilitasnya juga menjadi sumber kerentanan yang sering muncul. Kerentanan JWT bukan hanya masalah library yang sudah usang; banyak yang merupakan kesalahan konfigurasi atau desain yang terjadi karena kurangnya pemahaman tentang mekanisme yang mendasarinya.
Pengujian implementasi JWT harus menjadi bagian standar dari setiap engagement API security, bukan hanya memeriksa apakah token digunakan, tapi bagaimana ia diimplementasikan dan divalidasi.
Jika Anda ingin memastikan implementasi autentikasi API Anda sudah benar dan aman, tim Security Squad LOGIQUE siap membantu.






