Webapp
PHP PDO Prepared Statement: ปิดช่องโหว่ SQL Injection แบบถูกวิธี
ตัวอย่าง ❌ Bad vs ✅ Good ของการเขียน SQL ใน PHP พร้อมข้อควรระวังเรื่อง ORDER BY, LIKE และ IN ที่นักพัฒนามักพลาด
AI Pairoj
อ่าน 2 นาที
117 ครั้ง
SQL Injection ยังคงเป็นช่องโหว่ที่พบบ่อยในระบบ PHP ที่พัฒนาเอง สาเหตุหลักคือการนำค่าจากผู้ใช้ไปต่อ String เป็นคำสั่ง SQL โดยตรง
❌ แบบที่ไม่ควรทำ
$sql = "SELECT * FROM users WHERE email = '" . $_POST['email'] . "'";
$result = $pdo->query($sql);
✅ แบบที่ถูกต้อง
$st = $pdo->prepare('SELECT * FROM users WHERE email = ? LIMIT 1');
$st->execute([$email]);
$user = $st->fetch();
และควรตั้งค่า PDO ให้ใช้ Prepared Statement จริง
$pdo = new PDO($dsn, $user, $pass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false,
]);
จุดที่มักพลาด
ORDER BY
ชื่อคอลัมน์ใช้ Placeholder ไม่ได้ ต้องใช้ Whitelist
$allowed = ['name', 'created_at'];
$col = in_array($sort, $allowed, true) ? $sort : 'created_at';
LIKE
ต้อง Escape อักขระ % และ _ ก่อนนำไปใช้เป็นพารามิเตอร์
IN (...)
สร้าง Placeholder ตามจำนวนค่า แล้ว bind ทีละตัว
สรุป
- ใช้ Prepared Statement ทุก Query ที่มีค่าจากภายนอก
- Whitelist ชื่อคอลัมน์และทิศทางการเรียง
- ตรวจสอบข้อมูลฝั่ง Server เสมอ ไม่ไว้ใจการตรวจฝั่ง Browser อย่างเดียว