Lewati ke konten
← Semua catatan

WRITE-UP / BOLA

Login bukan izin membaca semua objek.

Menelusuri batas otorisasi pada API invoice multi-tenant: fixture dua akun, matriks akses, perbaikan query, dan uji regresi.

HEXPLOIT / Catatan edukasi sintetis · 22 Oktober 2026 · 2 mnt baca

Ilustrasi konseptual jalur akses yang dipisahkan oleh batas tenant.
Ilustrasi editorial dibuat dengan AI. Bukan bukti pengujian atau insiden nyata.

Materi edukasi sintetis, bukan laporan kerentanan produk. Kode adalah ilustrasi, bukan implementasi siap produksi. Pengujian hanya pada data dan sistem yang kamu kuasai atau diizinkan secara tertulis.

Ruang lingkup & hipotesis

Studi kasus ini sintetis, bukan insiden HEXPLOIT atau kerentanan produk tertentu. Bayangkan layanan invoice lokal dengan pengguna A di tenant Merah dan pengguna B di tenant Putih. Keduanya memakai akun serta data uji yang kita kendalikan.

Hipotesisnya: handler memeriksa sesi, tetapi mengambil invoice hanya berdasarkan ID. Bukti yang dicari bukan error atau respons 200 semata, melainkan apakah data yang dikembalikan benar-benar berada di luar hak baca aktor.

Matriks bukti yang dapat diulang

Buat invoice A-01 dan B-01 dengan isi penanda yang berbeda. Jalankan hanya permintaan baca pada fixture. Catat aktor, tenant, objek, hasil yang diharapkan, status respons, dan apakah isi objek keluar. Jangan memasukkan token sesi ke laporan.

text
Actor  Object  Expected result
A      A-01    allow own-tenant read
A      B-01    deny, no invoice content
B      A-01    deny, no invoice content
B      B-01    allow own-tenant read
guest  A-01    require authentication

Akar masalah: identitas tanpa kebijakan objek

Pemeriksaan login menjawab siapa aktornya, bukan objek mana yang boleh diakses. Pada contoh ini, lookup berdasarkan ID melewati hubungan tenant. Mengganti ID menjadi UUID tidak menghilangkan kebutuhan otorisasi objek.

Perbaikan pada batas pengambilan data

Contoh pseudocode berikut mengikat objek ke tenant dari sesi tepercaya, bukan dari parameter klien. Aplikasi yang mendukung berbagi lintas tenant memerlukan kebijakan izin yang lebih lengkap. Pilih 403 atau 404 sesuai kebijakan kebocoran keberadaan objek, lalu konsisten.

pseudocode
actor = requireSession(request)
invoice = repository.findOne({
  id: request.params.invoiceId,
  tenantId: actor.tenantId
})
if invoice is absent: return notFound()
requirePermission(actor, "invoice:read", invoice)
return serializeAllowedFields(invoice)

Regresi & batas kesimpulan

Tambahkan matriks ini ke pengujian terotomasi. Ulangi pada endpoint ekspor dan unduhan, bukan hanya tampilan detail. Verifikasi juga isi respons penolakan dan tidak adanya perubahan data. Bukti pada endpoint baca ini tidak membuktikan semua operasi lain aman.

  • Tenant berbeda ditolak walaupun aktor mengetahui ID yang valid.
  • Akses yang memang diizinkan tetap bekerja setelah perbaikan.
  • Log penolakan cukup untuk investigasi tanpa menyimpan token atau isi invoice.

Referensi & pembacaan lanjutan

Tulisan ini merupakan sintesis edukasi, bukan salinan atau afiliasi dengan sumber berikut. Gunakan dokumentasi primer untuk keputusan implementasi.