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
- Always use parameterized queries
- Never concatenate user input into SQL
- Use ORM/Query builders when possible
- Validate and sanitize input
- 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!
Thử thách
Luyện tập ngay điều vừa học. Viết lời giải, mở gợi ý nếu bí.
Đề bài
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.
Code khởi tạo
$email = $_GET['email'];
$sql = "SELECT * FROM users WHERE email = '$email'";
$user = $pdo->query($sql)->fetch();
Lời giải của bạn
$email = $_GET['email'];
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = ?');
$stmt->execute([$email]);
$user = $stmt->fetch();

