OWASP Top 10 adalah daftar kategori risiko keamanan aplikasi web yang paling umum, disusun oleh komunitas Open Worldwide Application Security Project. Laravel sudah melindungi banyak hal secara bawaan, seperti CSRF, escaping di Blade, dan query binding di Eloquent. Tapi perlindungan itu bisa jebol karena kebiasaan coding yang keliru. Berikut kategori yang paling sering muncul di aplikasi Laravel, dengan contoh kode rentan dan perbaikannya.
1. Broken Access Control
Kategori paling sering ditemukan: pengguna bisa melihat atau mengubah data milik orang lain hanya dengan mengganti ID di URL.
// RENTAN: siapa pun yang login bisa melihat invoice siapa saja
public function show(Invoice $invoice)
{
return view('invoices.show', compact('invoice'));
}
// AMAN: cek kepemilikan lewat policy
public function show(Invoice $invoice)
{
$this->authorize('view', $invoice);
return view('invoices.show', compact('invoice'));
}
// InvoicePolicy
public function view(User $user, Invoice $invoice): bool
{
return $user->id === $invoice->user_id;
}
Atau batasi query sejak awal: $request->user()->invoices()->findOrFail($id). Terapkan pengecekan yang sama di API, bukan hanya di halaman web.
2. Injection
// RENTAN: input langsung masuk SQL
DB::select("SELECT * FROM products WHERE name LIKE '%{$request->q}%'");
Product::whereRaw("category = '{$request->category}'")->get();
Product::orderBy($request->sort)->get();
// AMAN: parameter binding dan whitelist
Product::where('name', 'like', '%'.$request->q.'%')->get();
Product::whereRaw('category = ?', [$request->category])->get();
$sort = in_array($request->sort, ['name', 'price', 'created_at'], true) ? $request->sort : 'created_at';
Product::orderBy($sort)->get();
Nama kolom tidak bisa di-binding, jadi selalu gunakan daftar kolom yang diizinkan. Injection juga mencakup XSS: di Blade, {{ $value }} aman karena di-escape, sedangkan {!! $value !!} hanya untuk HTML yang sudah disanitasi.
3. Mass Assignment
// RENTAN bila model tidak punya $fillable
$user->update($request->all()); // penyerang mengirim is_admin=1
// AMAN
protected $fillable = ['name', 'email', 'phone'];
$user->update($request->validated());
Selalu pakai $request->validated() dari Form Request, bukan $request->all().
4. Security Misconfiguration
APP_DEBUG=truedi production membocorkan konfigurasi dan isi environment saat terjadi error.- Document root yang tidak mengarah ke
public/membuat.envbisa diunduh. - Folder
storageyang bisa ditelusuri, atau panel debug seperti Telescope yang terbuka tanpa otorisasi. - Header keamanan belum diatur:
Strict-Transport-Security,X-Content-Type-Options, danContent-Security-Policy.
Konfigurasi server yang benar dibahas di deploy Laravel ke VPS Ubuntu.
5. Cryptographic Failures
- Simpan password dengan
Hash::make()(bcrypt atau argon2), jangan MD5 atau SHA1. - Enkripsi data sensitif di database dengan cast
encrypted, misalnya nomor rekening atau NIK. - Paksa HTTPS di production dan jangan pernah commit
APP_KEYke repositori.
protected function casts(): array
{
return ['bank_account' => 'encrypted', 'password' => 'hashed'];
}
6. Identification and Authentication Failures
// batasi percobaan login
RateLimiter::for('login', function (Request $request) {
return Limit::perMinute(5)->by($request->input('email').$request->ip());
});
- Gunakan starter kit resmi atau Fortify yang sudah menangani reset password, verifikasi email, dan 2FA.
- Regenerasi session setelah login:
$request->session()->regenerate(). - Terapkan aturan password minimum dengan
Password::min(8)->uncompromised().
7. Upload File yang Tidak Aman
$request->validate([
'avatar' => ['required', 'image', 'mimes:jpg,png,webp', 'max:2048'],
]);
$path = $request->file('avatar')->store('avatars', 'public'); // nama file acak
Jangan pakai nama file asli dari pengguna, jangan simpan unggahan di folder yang bisa mengeksekusi PHP, dan validasi tipe berdasarkan isi file, bukan hanya ekstensi.
8. Vulnerable and Outdated Components
composer audit
npm audit
Jalankan secara rutin, misalnya di CI. Ikuti rilis keamanan Laravel dan upgrade versi minor secepatnya.
9. Server-Side Request Forgery (SSRF)
Fitur seperti "impor dari URL" atau "pratinjau tautan" bisa disalahgunakan untuk mengakses alamat internal server, seperti http://127.0.0.1 atau endpoint metadata cloud. Validasi URL, izinkan hanya skema https, dan tolak alamat IP privat.
10. Logging dan Monitoring yang Lemah
- Catat login gagal berulang, perubahan hak akses, dan aksi admin.
- Jangan mencatat password, token, atau data kartu di log.
- Kirim error ke layanan pemantauan agar serangan atau bug terdeteksi cepat.
Checklist OWASP Top 10 Sebelum Rilis
- Setiap route yang mengakses data milik pengguna memakai policy atau query yang dibatasi.
- Tidak ada
$request->all()untuk create atau update. - Tidak ada input pengguna di
whereRaw,orderBy, atauDB::selecttanpa binding atau whitelist. APP_DEBUG=false, HTTPS aktif, header keamanan terpasang.- Login dan endpoint sensitif diberi rate limit.
composer auditbersih.- Ada test untuk akses ilegal, misalnya pengguna A membuka invoice pengguna B harus mendapat 403.
Langkah Berikutnya
Terapkan prinsip yang sama di API dengan REST API dengan Laravel Sanctum. Keamanan di sisi pengguna, seperti password dan 2FA, dibahas di keamanan akun digital.