Laravel Eloquent ORM secara default mengamankan operasi basis data dari celah SQL Injection melalui penggunaan PDO dan parameter binding pada method pembangun kueri (query builder). Namun, celah keamanan tetap dapat muncul akibat kesalahan implementasi pengembang, seperti penggunaan method whereRaw() yang ceroboh, konfigurasi Mass Assignment yang longgar, atau eksposur data sensitif melalui serialisasi model.
Pengamanan tingkat lanjut pada Eloquent memerlukan pemahaman mendalam mengenai mekanisme internal pengikatan parameter, pembatasan atribut model, serta validasi input secara ketat sebelum data menyentuh lapisan persistensi. Artikel ini membedah teknik mitigasi kerentanan paling krusial dalam penggunaan Eloquent ORM.
Matriks Kerentanan Utama dan Mitigasi dalam Eloquent
| Jenis Kerentanan | Penyebab Utama | Dampak Risiko | Solusi Teknis & Pencegahan |
|---|---|---|---|
| SQL Injection (Raw Queries) | Penggunaan stringinterpolation pada whereRaw() atau DB::raw(). |
Pencurian, modifikasi, atau penghapusan seluruh data basis data. | Gunakan parameter binding: whereRaw('id = ?', [$id]) atau named bindings. |
| Mass Assignment Vulnerability | Properti $guarded = [] atau tidak mendefinisikan $fillable pada model. |
Pengguna tidak berwenang mengubah kolom krusial (misal: is_admin = 1). |
Definisikan secara eksplisit properti protected $fillable = [...] pada setiap model. |
| Insecure Deserialization / Data Exposure | Mengembalikan seluruh atribut model termasuk password atau remember_token ke API response. |
Kebocoran kredensial pengguna dan data privat. | Gunakan properti protected $hidden = ['password', 'remember_token'] atau API Resources. |
| Insecure Direct Object References (IDOR) | Mengambil data via find($id) tanpa validasi kepemilikan sumber daya (ownership). |
Pengguna dapat mengakses data milik pengguna lain dengan memanipulasi parameter ID. | Gunakan auth()->user()->posts()->findOrFail($id) alih-alih kueri global. |
Pencegahan SQL Injection pada Raw Expressions
Meskipun Eloquent otomatis melakukan escape pada argumen standar seperti User::where('name', $name), pengembang sering kali memerlukan kueri kompleks yang memaksa penggunaan ekspresi mentah. Kesalahan fatal terjadi saat variabel mentah langsung digabungkan ke dalam string kueri.
Contoh Implementasi Salah (Rentan):
// JANGAN LAKUKAN INI! Rentan terhadap SQL Injection
$users = User::whereRaw("name = '" . $request->input('name') . "'")->get();
Contoh Implementasi Aman (Binding):
// Aman menggunakan parameter binding posisi
$users = User::whereRaw('name = ?', [$request->input('name')])->get();
// Aman menggunakan named bindings
$users = User::whereRaw('votes > :votes AND status = :status', [
'votes' => 100,
'status' => 'active'
])->get();
Pengamanan Mass Assignment dengan Fillable dan Guarded
Fitur create() dan update() pada Eloquent menerima array input dari pengguna. Jika proteksi tidak diaktifkan, penyerang dapat menyuntikkan parameter tambahan melalui HTTP Request untuk mengubah atribut sensitif seperti peran pengguna atau saldo akun.
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
// HANYA kolom dalam array ini yang diizinkan untuk mass assignment
protected $fillable = [
'name',
'email',
'password',
];
// ATAU gunakan guarded untuk mendaftarkan kolom yang DILARANG diisi massal
// protected $guarded = ['id', 'is_admin', 'created_at', 'updated_at'];
}
Mitigasi IDOR Menggunakan Relasi Model
Kerentanan IDOR (Insecure Direct Object References) terjadi ketika aplikasi mengandalkan parameter ID dari request tanpa memeriksa apakah pengguna yang sedang masuk memiliki hak akses atas data tersebut. Penyelesaian terbaik adalah selalu memanggil kueri melalui relasi autentikasi pengguna.
// RENTAN: Pengguna dapat mengakses post milik pengguna lain dengan mengganti parameter {id}
public function show($id)
{
return Post::findOrFail($id);
}
// AMAN: Memastikan post benar-benar milik pengguna yang sedang terautentikasi
public function show(Request $request, $id)
{
return $request->user()->posts()->findOrFail($id);
}
Troubleshooting & Praktik Terbaik Lapangan
- Global Scopes untuk Soft Deletes & Multi-tenancy: Gunakan Global Scopes atau Trait bawaan Laravel untuk memastikan kueri otomatis memfilter data berdasarkan tenant_id atau status aktif, mencegah kebocoran data antar-organisasi.
- Auditing Kueri: Manfaatkan
DB::listen()pada lingkungan staging untuk memantau apakah ada kueri mentah yang lolos tanpa parameter binding. - Cast Attributes: Gunakan fitur
$castspada model untuk memastikan tipe data yang masuk ke basis data selalu konsisten (misal: casting integer, boolean, atau JSON), menghindari manipulasi tipe data input.