Secret Token Rb: Fungsi, Bahaya Bocor, dan Migrasi Rails

secret_token.rb adalah file inisialisasi di Ruby on Rails (terletak di config/initializers/secret_token.rb) yang bertugas menyimpan kunci kriptografi rahasia untuk menandatangani (sign) dan mengenkripsi cookie sesi HTTP. Kunci ini memastikan bahwa data sesi yang disimpan di browser pengguna tidak dapat dimanipulasi atau dipalsukan oleh pihak ketiga.

Jika file ini bocor ke repositori publik (seperti GitHub), penyerang dapat memalsukan cookie sesi, memalsukan identitas pengguna (termasuk akun administrator), hingga mengeksekusi kode berbahaya secara jarak jauh (Remote Code Execution/RCE) melalui deserialisasi objek Ruby Marshal. Mulai Rails 4 dan versi modern (Rails 5 hingga Rails 8), implementasi secret_token telah ditinggalkan dan digantikan oleh secret_key_base serta sistem Encrypted Credentials.

Fungsi Utama dan Cara Kerja secret_token.rb

Saat aplikasi Rails menggunakan modul ActionDispatch::Session::CookieStore, status sesi pengguna disimpan langsung di sisi klien dalam bentuk cookie terenkripsi atau bertanda tangan digital. secret_token bertindak sebagai HMAC secret key untuk memvalidasi integritas data tersebut.

# Contoh isi config/initializers/secret_token.rb (Rails 3.x / Rails 4 legacy)
MyApp::Application.config.secret_token = '9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0f9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0f'

Jika nilai token ini diubah di server, seluruh sesi pengguna aktif akan otomatis menjadi tidak valid (invalidated), memaksa seluruh pengguna untuk melakukan login ulang karena tanda tangan verifikasi cookie tidak lagi cocok.

Evolusi Manajemen Rahasia Session di Ruby on Rails

Arsitektur keamanan Rails telah berkembang pesat untuk mencegah pengembang menyematkan kunci rahasia langsung dalam kode sumber (hardcoded secret). Tabel berikut merangkum evolusi penanganan token sesi dari masa ke masa:

Versi RailsMekanisme PenyimpananLokasi File KonfigurasiTingkat Keamanan Default
Rails 3.xconfig.secret_tokenconfig/initializers/secret_token.rbRentan jika di-commit ke Git (Plaintext)
Rails 4.0 - 4.1config.secret_key_baseconfig/initializers/secret_token.rbMendukung enkripsi cookie AES-256
Rails 4.2 - 5.1secrets.ymlconfig/secrets.ymlMulai memisahkan token dev/prod via ENV
Rails 5.2 - 7.xEncrypted Credentialsconfig/credentials.yml.encKredensial terenkripsi dengan master.key
Rails 8.xCredentials / ENV Hybridconfig/credentials/*.yml.encZero plain secrets di repositori kode

Risiko Keamanan Fatal: Dari Bocornya Token ke Remote Code Execution (RCE)

Pada Rails versi lama, data cookie diserialisasi menggunakan modul bawaan Ruby, yaitu Marshal. Jika seorang peretas mengetahui nilai secret_token atau secret_key_base aplikasi, langkah eksploitasi berlangsung sangat cepat:

  1. Cookie Forgery: Peretas membuat payload sesi palsu di mesin lokal, misalnya mengubah parameter user_id: 1 untuk langsung mengambil alih akun Superadmin tanpa kata sandi.
  2. Deserialization Attack: Peretas menyusun gadget chain objek Ruby (misalnya memanfaatkan class ERB atau objek universal Ruby lainnya) ke dalam payload sesi yang ditandatangani menggunakan token curian.
  3. Arbitrary Command Execution: Saat request dikirim ke server, Rails mendeteksi tanda tangan HMAC cocok dan langsung mendeserialisasi data dengan Marshal.load, memicu eksekusi perintah shell langsung di server target.

Cara Migrasi Aman dari secret_token.rb ke Rails Modern

Bagi proyek yang masih memiliki residu file config/initializers/secret_token.rb atau sedang melakukan modernisasi aplikasi, ikuti langkah-langkah standardisasi industri berikut:

1. Pindahkan Kunci ke Environment Variable (Jika Menggunakan Rails 4/5)

Hapus nilai string plaintext dari repository dan baca langsung dari variabel lingkungan server produksi:

# config/initializers/secret_token.rb
Rails.application.config.secret_key_base = ENV['SECRET_KEY_BASE'] || begin
  if Rails.env.production?
    raise 'SECRET_KEY_BASE environment variable is missing in production!'
  else
    'development_secret_key_base_fallback_for_local_testing_only_1234567890'
  end
end

2. Migrasi ke Rails Encrypted Credentials (Rails 5.2 ke Atas)

Hapus file config/initializers/secret_token.rb secara permanen, lalu manfaatkan sistem enkripsi bawaan Rails:

# Hapus initializer usang
git rm config/initializers/secret_token.rb

-- Generate kunci credentials baru jika belum ada
EDITOR="nano" bin/rails credentials:edit

Di dalam editor yang terbuka, pastikan secret_key_base terkonfigurasi:

# config/credentials.yml.enc
secret_key_base: c894d0e91f1a547b744031a0e0e0ab72d7f8d6f021ad5e8c1b3f94e9f7823ab498c812d38f...

Menghasilkan Token Baru dan Troubleshooting Error

Untuk men-generate string token acak dengan entropi tinggi (64-byte hex string), jalankan perintah Rake/Rails berikut di terminal:

bundle exec rake secret
# Atau pada Rails versi baru:
bin/rails secret

Solusi Error: "ArgumentError: A secret is required to generate an integrity hash for cookie session data"

Pesan kesalahan ini muncul saat aplikasi Rails melakukan booting di environment production namun tidak menemukan nilai secret_key_base atau secret_token. Langkah penanganannya:

  1. Jalankan bin/rails secret di terminal lokal untuk mendapatkan string 128 karakter acak.
  2. Tambahkan string tersebut ke environment server Anda: export SECRET_KEY_BASE="string_dari_langkah_1".
  3. Jika menggunakan Heroku: heroku config:set SECRET_KEY_BASE="$(bundle exec rake secret)".
  4. Jika menggunakan Docker, masukkan ke dalam file .env.production atau secret manager container runner.

Tindakan Tanggap Darurat Jika secret_token Terlanjur Masuk Git

Jika file secret_token.rb berisi token asli sempat ter-push ke GitHub atau repositori publik, token tersebut wajib dianggap telah terkompromi. Langkah pembersihan yang harus dilakukan:

  • Rotasi Token Seketika: Segera generate token baru dan terapkan di server produksi. Seluruh user akan log out otomatis, namun akses penyusup menggunakan token lama langsung tertutup.
  • Bersihkan Riwayat Git: Gunakan tool seperti git-filter-repo atau BFG Repo-Cleaner untuk menghapus commit historis yang memuat token tersebut sebelum repositori diakses publik kembali. Menghapus file di commit terbaru saja tidak cukup karena riwayat lama masih dapat dibaca penyerang.
  • Audit Log Server: Periksa log akses HTTP pada jam-jam token terekspos untuk mendeteksi anomali request dengan cookie berukuran besar yang mencurigakan.