Halo teman-teman mahasiswa IT dan developer masa kini! Kalau kamu lagi sibuk ngerjain proyek full-stack, bikin skripsi berbasis web, atau iseng explore keamanan siber, pasti udah nggak asing lagi sama yang namanya JSON Web Tokens alias JWT. Token ini ibarat kartu akses VIP digital yang nongkrong di header Authorization, cookies, atau lalu lintas API layanan mikro kamu. Seringnya, JWT bekerja secara diam-diam tanpa bikin masalah—dan di sinilah letak bahayanya yang sebenarnya. Bayangkan kalau JWT kamu dibuat pakai secret key yang gampang ditebak seperti secret, token itu bakal keliatan sah-sah saja, sampai akhirnya ada pihak tak bertanggung jawab yang nge-run wordlist dan mulai nyetak token admin sesuka jidat.

Sebagai seseorang yang sering ngulik token, gua bakal bedah tuntas tiga cara utama bagaimana sebuah JWT bisa dipalsukan, kenapa celah itu bisa tembus, dan satu kebiasaan defensif mutlak yang bisa nutup semua celah itu sekaligus. Kita bakal pakai tools simpel bikinan gua, yaitu jwt-auditor, buat nunjukin simulasi serangannya ke token asli.

Tapi sebelum itu, yuk kita refresh ingatan kilat dalam 30 detik. JWT itu sebenarnya cuma tiga potongan string berformat base64url yang digabungin sama titik: ada header, payload, dan signature. Header ngasih tahu algoritma apa yang dipakai buat nge-sign token tersebut. Signature dihitung dari gabungan header dan payload. Nah, proses verifikasi itu intinya ngehitung ulang signature tersebut lalu dicocokkan. Semua serangan di bawah ini pada dasarnya adalah cara mengeksploitasi salah satu tahapan dalam proses itu. Dan satu fakta paling krusial yang wajib kamu camkan: payload itu cuma di-encode, BUKAN di-enkripsi! Siapa pun yang megang token kamu bisa baca semua data claim di dalamnya secara mentah-mentah.

Ancaman 1: Nyuruh Server Anggap Token Nggak Punya Signature (alg: none)

Bagian header di JWT mendefinisikan algoritma yang dipakai. Nah, di awal-awal implementasinya dulu, ada satu nilai sah yang diperbolehkan, yaitu none. Artinya apa? Token tersebut diklaim tidak membawa signature sama sekali! Makanya, serangannya tuh terkesan konyol saking gampangnya. Ambil aja token valid yang biasa, terus ubah header-nya jadi {"alg":"none"}, ganti payload-nya biar status kamu jadi "role":"admin", hapus bagian signature-nya, lalu kirim deh ke server. Kalau server verifikatornya naif dan percaya begitu saja sama header serta nurut sama perintah none, ya udah, token palsu itu bakal langsung diterima mentah-mentah sebagai token sah.

Ini bukan teori fiktif dari buku teks kampus ya. Pada tahun 2015, banyak banget library JWT yang kedapatan otomatis menerima algoritma none secara default. Kasus ini dilacak sebagai CVE-2015-9235 buat library Node jsonwebtoken yang populer, dan efeknya menjalar ke berbagai bahasa pemrograman lain. Bahayanya karena faktor default behavior tadi. Seorang developer yang manggil fungsi verify(token) tanpa argumen tambahan bakal langsung terjebak di jalur tidak aman secara cuma-cuma.

Ancaman 2: Tebak Rahasia Server Secara Offline (Offline Brute-Forcing)

Algoritma seperti HS256, HS384, dan HS512 melakukan signing pakai HMAC, di mana mereka menggunakan shared secret yang sama antara pembuat dan verifikator. Keamanan seluruh token ini bertumpu pada satu hal: apakah secret tersebut mustahil ditebak? Masalahnya, kalau manusia yang bikin secret-nya secara manual, biasanya mereka bakal milih kata-kata pasaran kayak secret, changeme, atau nyontek teks placeholder your-256-bit-secret dari situs debugger seperti jwt.io yang tanpa sadar malah ke-deploy ke server production!

Nah, di sinilah bagian yang sering diremehin banyak orang. Karena si penyerang udah megang token valid di tangan mereka, mereka bisa nebak secret tersebut secara offline di laptop sendiri. Nggak ada tuh form login yang bakal nge-rate limit percobaan mereka, atau sistem lockout yang bikin IP mereka ke-banned. Mereka tinggal nyoba kandidat string, ngehitung ulang HMAC dari header dan payload token tersebut, lalu dicocokkan sama signature asli yang sudah nangkring di dalam token. Kalau hasilnya match, artinya mereka sukses nemuin kuncinya, dan sekarang mereka bebas nge-sign token apa aja sesuka hati.

$ jwt-auditor crack <token> --wordlist rockyou.txt
Secret found: 'changeme'
The token can now be forged. Rotate this key.

Simpel kan? Nggak perlu nyolek server target sama sekali. Prosesnya murni jalan di komputer penyerang.

Ancaman 3: Mengubah Public Key Menjadi Secret Key (Algorithm Confusion)

Nah, serangan yang satu ini super menarik dan jarang dipikirkan oleh kebanyakan tim developer. Algoritma RS256 melakukan signing pakai private key, dan diverifikasi pakai public key. Sesuai namanya, public key memang sengaja dibuat publik. Kamu mungkin naruh kuncinya di URL yang bisa diakses siapa aja. Itu wajar dan memang sudah didesain seperti itu.

Tapi, ada celah yang namanya algorithm confusion yang merusak asumsi desain tersebut. Bayangkan skenario di mana server memverifikasi token pakai prinsip "pakai algoritma apa pun yang tertulis di header token". Si penyerang lantas iseng ngeganti header dari RS256 menjadi HS256. Akibatnya, server malah menjalankan verifikasi HMAC alih-alih RSA. Pertanyaannya, apa yang dipakai server sebagai secret HMAC-nya? Jawabannya: satu-satunya kunci yang dia punya, yaitu public key RSA itu sendiri! Padahal, public key kan sifatnya tidak rahasia. Penyerang tinggal download itu public key, bikin token palsu pakai algoritma HS256 dengan memanfaatkan byte dari public key tadi sebagai secret HMAC. Server pun bakal dengan senang hati memvalidasi token palsu tersebut.

Ada satu detail teknis kecil yang sering bikin developer maupun hacker kejebak, dan penting buat kamu tahu. HMAC bekerja berdasarkan byte persis, jadi ada atau tidaknya karakter newline (baris baru) di ujung file public key yang tersimpan bakal ngubah total setiap byte dari output-nya. Token palsu yang di-sign pakai format PEM asli tidak akan lolos verifikasi kalau dibandingkan sama PEM yang karakternya dipangkas newline-nya. Waktu gua bikin fitur cek confusion di jwt-auditor, gua sengaja nambahin skrip buat nyoba berbagai varian byte kunci yang umum demi alasan ini, karena di dunia nyata server sering banget beda pendapat soal urusan enter atau spasi di akhir baris.

$ jwt-auditor audit <token> --public-key server_pub.pem
CRITICAL  Token verifies with the public key as an HMAC secret
public key PEM as stored (verified as HS256)

Kalau kamu nemuin baris log seperti itu saat nge-audit token aplikasi kamu sendiri pakai public key asli, artinya server kalian rentan dipalsukan! Jenis celah ini masuk ke dalam daftar CWE-347, yaitu verifikasi tanda tangan kriptografi yang tidak tepat. Algoritma RS256 sendiri sebenarnya sangat aman. Yang jadi biang kerok adalah perilaku verifikator yang terlalu polos mempercayai header token untuk menentukan algoritma verifikasinya.

Satu Kebiasaan Sakti yang Menutup Ketiga Celah Sekaligus

Coba perhatikan baik-baik, apa sih kesamaan dari ketiga serangan di atas? Serangan alg: none terjadi karena server terlalu percaya pada algoritma pilihan header. Serangan confusion juga terjadi karena alasan yang sama: server percaya mentah-mentah pada algoritma buatan header. Bahkan serangan tebak kunci lemah pun sebenarnya berakar dari kegagalan memperlakukan kunci penandatangan sebagai rahasia yang beneran aman. Akar masalahnya selalu sama: mempercayai data di dalam token untuk memutuskan bagaimana cara memverifikasi token itu sendiri.

Jadi, kebiasaan emas apa yang harus kita terapkan? Jangan pernah biarkan token memilih algoritmanya sendiri. Tentukan secara tegas dari sisi server algoritma apa saja yang boleh kamu terima, masukkan dalam daftar izin (allowlist) yang eksplisit, dan tolak semua hal lain di luar itu—termasuk algoritma none.

# Pola pengamanan yang aman
ALLOWED = {"RS256"}
claims = jwt.decode(token, public_key, algorithms=list(ALLOWED))

Hanya dengan menambahkan satu argumen berupa daftar izin algoritma yang eksplisit, kamu bisa langsung membasmi celah alg: none dan confusion antara RS ke HS dalam sekali pukul! Tambahkan juga kunci acak yang panjang dari generator CSPRNG murni, dan kamu sudah sukses mengunci pintu ketiga. Terakhir, pasang masa kedaluwarsa (expiry) yang pendek, serta jauhkan password atau data sensitif (PII) dari dalam payload, karena sekali lagi: payload itu cuma di-encode, bukan di-enkripsi!

Worth It Gak Buat Mahasiswa?

Buat kamu yang lagi belajar ngembangin aplikasi web, ngerti celah JWT ini hukumnya wajib banget dan super worth it buat dimasukin ke portofolio keamanan siber kamu. Alat seperti jwt-auditor bersifat open-source, berjalan secara offline, dan gratis seratus persen tanpa bikin kantong mahasiswa bolong.

  • Kelebihan: Melatih pola pikir security-first, mendeteksi celah aplikasi lebih dini sebelum dites dosen penguji atau kena pentest jahat, serta memperkuat logika koding backend kamu.
  • Kekurangan: Butuh sedikit waktu buat paham konsep dasar kriptografi dan manajemen kunci di level produksi.

Cara Mendaftar / Mencoba Tools Audit JWT

Nggak usah percaya buta sama teori artikel ini, yuk buktikan sendiri langsung ke aplikasi buatanmu di staging environment yang sah untuk diuji. Jalankan perintah berikut di terminal laptopmu:

  • Pastikan kamu sudah menginstal tool audit token dari repositori resmi: git clone https://github.com/mohelobeid/jwt-auditor
  • Masuk ke direktori tool tersebut dan sinkronkan dependensinya: cd jwt-auditor && uv sync
  • Jalankan perintah audit untuk memeriksa token aplikasimu: uv run jwt-auditor audit <token>

Alat ini bakal ngasih tahu kamu apakah algoritma tokenmu adalah none, apakah kuncinya gampang ditebak, apakah token bisa diverifikasi pakai public key sembarangan, dan apakah token tersebut secara diam-diam membawa data rahasia yang seharusnya tidak disebar.

Yuk, asah terus skill coding dan keamanan sistemmu! Jangan biarkan aplikasi skripsimu jebol gara-gara celah keamanan klasik yang sebenarnya gampang dicegah. Siapkan CV dan portofolio koding terbaikmu sekarang juga, jadilah developer andal yang peduli keamanan siber, dan buktikan kalau mahasiswa Indonesia juga jago dalam hal secure coding!