© 2026 Laravel

Prepared Statements – Cách chống SQL Injection trong PHP

3 phút đọc 7 lượt xem

#Nguyên tắc cốt lõi

👉 Không bao giờ nối chuỗi SQL với input từ user

👉 Rule:

  • SQL + input → luôn dùng prepared statement

#Bad Example (Anti-pattern)

$email = $_POST['email'];
$db->query("SELECT * FROM users WHERE email = '$email'");

Vấn đề

Input:

' OR '1'='1

👉 Query trở thành:

SELECT * FROM users WHERE email = '' OR '1'='1'

👉 Leak toàn bộ data

#Good Example (Best Practice)

#1. Named parameters

$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email');
$stmt->execute(['email' => $email]);

#2. Positional parameters

$stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?');
$stmt->execute([$id]);

#3. Bind type

$stmt->bindValue(':limit', $limit, PDO::PARAM_INT);

#4. Insert safe

$stmt = $pdo->prepare(
    'INSERT INTO users (name, email) VALUES (:name, :email)'
);

#5. PDO config

PDO::ATTR_EMULATE_PREPARES => false

👉 Bắt buộc dùng real prepared

#6. Dynamic column (whitelist)

$allowed = ['id', 'name'];
$col = in_array($sort, $allowed, true) ? $sort : 'id';

#Giải thích sâu (Senior mindset)

#1. SQL Injection là gì?

👉 Inject SQL vào query

'; DROP TABLE users; --

#2. Prepared statement hoạt động thế nào?

👉 Query và data tách riêng:

  • SQL: template
  • Data: bind sau

👉 DB không parse data như SQL

#3. Tại sao escape string không đủ?

👉 Escape thủ công dễ sai

👉 Prepared statement = chuẩn nhất

#4. Emulated vs real prepared

  • Emulated: PHP xử lý
  • Real: DB xử lý

👉 Real an toàn hơn

#5. Không bind được column/table

ORDER BY :column 

👉 Phải whitelist

#Tips & Tricks (Senior level)

#1. Luôn dùng PDO hoặc ORM

#2. Disable emulate prepares

#3. Log query lỗi

#4. Combine với validation

#5. ORM không phải lúc nào cũng an toàn

👉 Raw query vẫn cần prepared

#Interview Questions

1. SQL Injection là gì?

Summary:

  • Inject SQL

Deep: User control query → leak data

2. Prepared statement giúp gì?

Summary:

  • Tách data khỏi SQL

Deep: DB không parse data thành SQL

3. Có thể bind column name không?

Summary:

  • Không

Deep: Phải whitelist

4. PDO::ATTR_EMULATE_PREPARES là gì?

Summary:

  • Fake prepared

Deep: Nên tắt để dùng real prepared

5. ORM có chống SQL injection không?

Summary:

  • Có nhưng không hoàn toàn

Deep: Raw query vẫn nguy hiểm

#Kết luận

👉 Prepared statement là cách duy nhất để chống SQL Injection đúng chuẩn

👉 Nếu không dùng → hệ thống có thể bị hack ngay lập tức

👉 Luôn:

  • Prepare
  • Bind
  • Whitelist