ข้ามไปเนื้อหาหลัก
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 อย่างเดียว
แชร์บทความ: