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=true di production membocorkan konfigurasi dan isi environment saat terjadi error.
  • Document root yang tidak mengarah ke public/ membuat .env bisa diunduh.
  • Folder storage yang bisa ditelusuri, atau panel debug seperti Telescope yang terbuka tanpa otorisasi.
  • Header keamanan belum diatur: Strict-Transport-Security, X-Content-Type-Options, dan Content-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_KEY ke 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, atau DB::select tanpa binding atau whitelist.
  • APP_DEBUG=false, HTTPS aktif, header keamanan terpasang.
  • Login dan endpoint sensitif diberi rate limit.
  • composer audit bersih.
  • 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.