Easy Security

Preventing SQL Injection in PHP

Learn essential techniques to protect your PHP applications from SQL injection attacks.

23 Jun, 2026 2 min 8 Views 5 Code blocks
Diagram
flowchart TD A["Unsafe: input concatenated into SQL"] --> B["email = '' OR '1'='1'"] B --> C[DB returns ALL rows: auth bypass / data leak] D["Safe: input bound to a ? placeholder"] --> E[Driver sends the value as DATA, not SQL] E --> F[Query stays safe] style C fill:#fee2e2,stroke:#ef4444 style F fill:#dcfce7,stroke:#22c55e

Preventing SQL Injection in PHP

SQL injection is one of the most dangerous security vulnerabilities. Here's how to prevent it.

❌ Never Do This

// VULNERABLE CODE - DO NOT USE!
$userId = $_GET['id'];
$query = "SELECT * FROM users WHERE id = $userId";
$result = mysqli_query($conn, $query);

An attacker can inject: ?id=1 OR 1=1 to access all records!

✅ Use Prepared Statements (MySQLi)

$userId = $_GET['id'];
$stmt = $conn->prepare("SELECT * FROM users WHERE id = ?");
$stmt->bind_param("i", $userId);
$stmt->execute();
$result = $stmt->get_result();

✅ Use PDO with Prepared Statements

$userId = $_GET['id'];
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
$stmt->execute(['id' => $userId]);
$user = $stmt->fetch();

✅ Laravel Query Builder (Automatic Protection)

$userId = request('id');
$user = DB::table('users')->where('id', $userId)->first();
// or
$user = User::find($userId);

Warning: Raw Queries

Even in Laravel, be careful with raw queries:

// ❌ Still vulnerable
DB::select("SELECT * FROM users WHERE id = " . $userId);

// ✅ Use bindings
DB::select("SELECT * FROM users WHERE id = ?", [$userId]);

Best Practices

  1. Always use parameterized queries
  2. Never concatenate user input into SQL
  3. Use ORM/Query builders when possible
  4. Validate and sanitize input
  5. Apply principle of least privilege to database users

Real-World Impact

In 2023, SQL injection attacks accounted for 30% of all web application breaches.

Don't be a statistic - protect your applications!

Interactive challenge

Try the challenge

Practice what you just learned. Write your solution, reveal hints if you get stuck.

Instructions

The query below drops raw $_GET input straight into the SQL string — a classic SQL injection hole. Rewrite it to use a PDO prepared statement with a bound parameter, so the user input can never change the query structure.

LanguagePHP

Starter code

php
$email = $_GET['email'];
$sql = "SELECT * FROM users WHERE email = '$email'";
$user = $pdo->query($sql)->fetch();

Your solution

Solution · php
$email = $_GET['email'];
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = ?');
$stmt->execute([$email]);
$user = $stmt->fetch();