Ketika RBAC Salah: Studi Kasus Keamanan untuk Full-Stack Developer

I am an enthusiastic researcher and developer with a passion for using technology to innovate in business and education.
Search for a command to run...

I am an enthusiastic researcher and developer with a passion for using technology to innovate in business and education.
No comments yet. Be the first to comment.
Ringkasan: Jika OpenClaw adalah AI Operating System yang menghubungkan berbagai layanan dan agent, maka Hermes adalah AI Worker yang fokus mengerjakan pekerjaan, belajar dari pengalaman, dan semakin p

Ketika membangun aplikasi modern seperti Next.js, Cloudflare Workers, platform AI, microservices, atau real-time dashboard, ada banyak istilah jaringan yang sering muncul: TCP, UDP, HTTP/2, QUIC, WebS

Setiap tahun, ribuan mahasiswa jurusan Teknologi Informasi, Sistem Informasi, dan Teknik Informatika diwisuda. Namun, tidak sedikit di antara mereka yang kemudian menghadapi kenyataan yang cukup berat

Jika Anda menggunakan Next.js, kemungkinan besar Anda pernah mendengar anggapan bahwa: "Next.js = Vercel" Padahal kenyataannya tidak harus demikian. Di sinilah OpenNext hadir. OpenNext adalah proyek

Saat pertama kali mencoba OpenCode Go, saya hampir langsung berlangganan tanpa membaca detail program yang mereka sediakan. Untungnya saya menemukan bahwa OpenCode memiliki program referral yang membe

Beberapa waktu lalu muncul sebuah write-up bug bounty berjudul “How a Simple RBAC Mistake Led to a $20K+ Admin Takeover” yang dipublikasikan oleh seorang security researcher. Kasus ini menunjukkan sesuatu yang sangat menarik: kerentanan yang menyebabkan takeover sistem bukan berasal dari eksploitasi kompleks, melainkan dari kesalahan logika sederhana dalam kontrol akses.
Kesalahan tersebut terjadi pada implementasi Role-Based Access Control (RBAC). Backend hanya memvalidasi bahwa token pengguna valid, tetapi tidak memverifikasi apakah pengguna tersebut memiliki hak akses yang sesuai.
Akibatnya, pengguna biasa dapat memanggil endpoint admin secara langsung dan bahkan mengubah rolenya menjadi Super Admin.
Kasus ini memberikan pelajaran penting bagi para full-stack developer:
Authentication bukanlah Authorization.
Login yang berhasil tidak berarti pengguna boleh melakukan semua aksi dalam sistem.
Dalam artikel ini kita akan membahas:
studi kasus kerentanan RBAC
contoh implementasi yang buruk
contoh implementasi yang aman
contoh mini project API menggunakan Hono
Dalam kasus tersebut, sistem memiliki arsitektur seperti ini:
Mobile App
│
│
Shared API Backend
│
┌───────────────┐
│ Admin Portal │
│ Invoice Portal│
└───────────────┘
Mobile app menyediakan fitur registrasi user.
Setelah user mendaftar, sistem memberikan token autentikasi.
Masalah muncul karena backend hanya melakukan pemeriksaan:
token valid → allow request
tanpa memverifikasi role.
Peneliti keamanan kemudian mencoba mengakses endpoint admin menggunakan token user biasa:
GET /user/v2/users
GET /user/v2/acl
POST /user/v2/acl
Karena tidak ada validasi role, request tersebut berhasil.
Lebih buruk lagi, terdapat endpoint yang memungkinkan perubahan role:
POST /user/v2/acl
Dengan payload sederhana:
{
"role": "super_admin"
}
Pengguna biasa berhasil menaikkan hak aksesnya menjadi Super Admin.
Dari titik ini, ia dapat:
membaca seluruh data pengguna
mengubah role pengguna lain
mengontrol konfigurasi sistem
mengakses beberapa portal admin sekaligus
Kerentanan ini menghasilkan bug bounty lebih dari $20.000.
Beberapa pola kesalahan yang sering muncul pada aplikasi modern:
Developer sering membuat middleware seperti:
if token valid:
allow request
Padahal seharusnya:
if token valid AND role authorized:
allow request
Contoh kesalahan:
menu admin disembunyikan
tombol admin tidak muncul
route admin tidak ditampilkan
Namun endpoint API masih dapat dipanggil langsung menggunakan tools seperti:
Postman
Burp Suite
curl
Backend sering dipakai oleh:
mobile app
admin dashboard
internal tools
Jika RBAC tidak dirancang dengan baik, maka token dari satu aplikasi bisa digunakan untuk mengakses sistem lain.
Berikut contoh mini API menggunakan Hono yang memiliki masalah yang sama seperti studi kasus tadi.
Struktur sederhana project:
src
├─ server.ts
├─ auth.ts
└─ db.ts
import { verify } from "jsonwebtoken"
export const auth = async (c, next) => {
const token = c.req.header("Authorization")
if (!token) {
return c.json({ error: "Unauthorized" }, 401)
}
try {
const payload = verify(token, process.env.JWT_SECRET)
c.set("user", payload)
await next()
} catch {
return c.json({ error: "Invalid token" }, 401)
}
}
Middleware ini hanya memastikan user login.
GET /admin/users
Implementasi:
app.get("/admin/users", auth, async (c) => {
return c.json(await db.users.findMany())
})
Masalahnya:
tidak ada validasi role.
Jika user biasa memiliki token valid, ia tetap bisa mengakses endpoint ini.
POST /admin/role
Implementasi buruk:
app.post("/admin/role", auth, async (c) => {
const body = await c.req.json()
await db.users.update({
where: { id: body.userId },
data: { role: body.role }
})
return c.json({ success: true })
})
Attacker bisa mengirim request:
{
"userId": 15,
"role": "super_admin"
}
Jika backend tidak memverifikasi role:
user → super_admin
Inilah privilege escalation.
Sekarang kita perbaiki implementasinya.
Kita pisahkan antara:
authentication
authorization
export const requireRole = (role) => {
return async (c, next) => {
const user = c.get("user")
if (!user || user.role !== role) {
return c.json({ error: "Forbidden" }, 403)
}
await next()
}
}
Middleware ini memastikan hanya role tertentu yang boleh mengakses endpoint.
GET /admin/users
Implementasi:
app.get(
"/admin/users",
auth,
requireRole("admin"),
async (c) => {
return c.json(await db.users.findMany())
}
)
Sekarang alurnya:
request
↓
auth middleware
↓
role validation
↓
endpoint handler
User biasa akan mendapatkan:
403 Forbidden
Endpoint ini sangat sensitif sehingga hanya boleh diakses oleh super admin.
app.post(
"/admin/role",
auth,
requireRole("super_admin"),
async (c) => {
const body = await c.req.json()
await db.users.update({
where: { id: body.userId },
data: { role: body.role }
})
return c.json({ success: true })
}
)
Sekarang user biasa tidak dapat mengubah role.
Beberapa prinsip penting ketika membangun API:
Frontend tidak boleh dipercaya.
Semua kontrol akses harus dilakukan di backend.
Contoh:
| Endpoint | Role |
|---|---|
| /users/me | user |
| /admin/users | admin |
| /admin/role | super_admin |
User hanya boleh melakukan hal yang benar-benar dibutuhkan.
Cobalah:
akses endpoint admin dengan user biasa
ubah parameter request
gunakan Postman untuk bypass UI
Tes sederhana ini sering menemukan bug besar.
Kasus bug bounty tersebut menunjukkan satu hal yang sangat penting dalam pengembangan aplikasi modern.
Kerentanan terbesar sering kali bukan berasal dari eksploitasi kompleks, tetapi dari kesalahan logika sederhana dalam kontrol akses.
Kesalahan kecil seperti ini:
if token valid → allow
seharusnya ditulis:
if token valid AND role authorized → allow
Perbedaan kecil tersebut dapat menentukan apakah sistem Anda aman atau justru dapat diambil alih oleh attacker.
Sebagai full-stack developer, kita tidak hanya bertanggung jawab membuat aplikasi berjalan dengan baik, tetapi juga memastikan aplikasi tersebut tidak mudah disalahgunakan.
Karena dalam keamanan aplikasi, sering kali:
Bug paling berbahaya adalah bug yang terlihat paling sederhana.
Sumber Inspirasi: https://medium.com/@Seek404/how-a-simple-rbac-mistake-led-to-a-20k-admin-takeover-d196694791dd