How to Fix SQL Injection Vulnerabilities in Laravel

Automated SQL injection detection and testing using SQLMap. Requires domain verification.

application security Hard fix 1-2 hours

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