How to Fix SQL Injection Vulnerabilities in Laravel
Automated SQL injection detection and testing using SQLMap. Requires domain verification.
What This Check Detects
Automated SQL injection detection and testing using SQLMap. Requires domain verification.
Full Documentation
What is SQL Injection?
SQL injection (SQLi) is a code injection technique that exploits security vulnerabilities in an application's database layer. Attackers insert malicious SQL statements into input fields to manipulate database queries, potentially gaining unauthorized access to data or modifying it.
Security Impact
Severity: Critical
- Complete database compromise
- Unauthorized data access and exfiltration
- Data modification or deletion
- Authentication bypass
- Remote code execution (in some configurations)
How Laravel Protects Against SQL Injection
Laravel's Eloquent ORM and Query Builder use PDO parameter binding by default, which protects against most SQL injection attacks. However, vulnerabilities can still occur with raw queries.
1. Always Use Eloquent or Query Builder
// SAFE - Eloquent automatically escapes values
$users = User::where('email', $request->email)->get();
// SAFE - Query Builder with parameter binding
$users = DB::table('users')
->where('email', '=', $request->email)
->get();
2. Avoid Raw Queries Without Bindings
// VULNERABLE - Never do this
$users = DB::select("SELECT * FROM users WHERE email = '{$request->email}'");
// SAFE - Use parameter bindings
$users = DB::select('SELECT * FROM users WHERE email = ?', [$request->email]);
// SAFE - Named bindings
$users = DB::select('SELECT * FROM users WHERE email = :email', ['email' => $request->email]);
3. Be Careful with whereRaw and orderByRaw
// VULNERABLE
$users = User::whereRaw("email = '{$request->email}'")->get();
// SAFE - Use bindings
$users = User::whereRaw('email = ?', [$request->email])->get();
// VULNERABLE - Column names in orderBy from user input
$users = User::orderByRaw($request->sort_column)->get();
// SAFE - Whitelist allowed columns
$allowedColumns = ['name', 'email', 'created_at'];
$column = in_array($request->sort_column, $allowedColumns)
? $request->sort_column
: 'created_at';
$users = User::orderBy($column)->get();
4. Validate and Sanitize Input
// Always validate input before using in queries
$validated = $request->validate([
'email' => 'required|email|max:255',
'search' => 'nullable|string|max:100',
'sort' => 'nullable|in:name,email,created_at',
'direction' => 'nullable|in:asc,desc',
]);
5. Use Prepared Statements for Complex Queries
// For complex queries that need raw SQL
$results = DB::statement(
'CALL process_user_data(?, ?)',
[$userId, $action]
);
6. Protect Against Mass Assignment
// In your Model - explicitly define fillable fields
class User extends Model
{
protected $fillable = ['name', 'email'];
// Or use guarded for the inverse
protected $guarded = ['id', 'is_admin'];
}
Verification
After applying fixes, the SQLMap scan should no longer detect injectable parameters. Always test with safe, non-destructive scan options on staging environments.
Related Issues
- Automated OWASP ZAP Scan
- Web Application Vulnerability Scan
- CSRF Protection
Related Security Checks
Check Your Laravel App for This Vulnerability
StackShield runs this check and 30+ others automatically. No code installation required.
Start Free Trial