#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