ถึงเวลาคิดเรื่อง SQL INJECTION (php pdo)
หน้าแรก PHP MySQL เกร็ดความรู้ ถึงเวลาคิดเรื่อง SQL INJECTION (php pdo)
วันนี้มีโอกาสให้ได้เรียนรู้เพิ่มเติมเรื่องที่เราไม่คิด แต่จำเป็นคือเรื่อง SQL Injection หาข้อมูลอยู่พักนึงได้เรียนรู้แล้วว่า มันจำเป็นยังไงและควรทำอย่างไร
SQL Injection คืออะไร? SQL Injection ก็คือการยัดโค๊ด SQL เข้าไปตรงๆ จากรูรั่วที่เกิดขึ้น ที่เราสะเพร่า เขียนโค้ดไม่ดี เขียนมีรูรั่ว และอื่นๆ
สาเหตุการเกิด SQL INJECTION
ลองดู Code ตัวอย่างครับ ที่เราเขียนแบบเดิมๆ

ถ้า SQL ไม่มีอะไร มันจะออกมาเป็น
| Code |
| SELECT* FROM tbl_users WHEREid ="1" |
แต่ถ้าลองมองอีกมุมนึง
ให้ $_GET['id'] เป็น " or "1"="1
ผลลัพที่ได้คือ
| Code |
| SELECT * FROM tbl_users WHERE id ="" or "1"="1" |
โดน ยัดโค๊ด SQL เข้าไปล่ะ งานเข้าซะแล้ว ผมไม่เคยอุดรูแบบนี้เลย ต่อไปนี้จะไม่มีอีกละ!!
รู้สาเหตุแล้ว มาดูวิธีป้องกัน
วิธีป้องกัน SQL INJECTION
การป้องกันก็เหมือนเดิม คือ กรอง input ถ้าหากต้องการตัวเลขก็ใช้ intvl($_GET['id']); อะไรแบบนี้
กรอง string ก็ให้ addslashes() ไป หรือใช้ mysql_real_escape_string(); ครอบ เพื่อป้องกันการใส่ หรือ เข้าไป
ตัวอย่าง ซักหน่อยละกัน
| Code |
| include "connection.php"; $id = intval($_GET['id']); $passwd = mysql_real_escape_string($_GET['passwd']); $sql = 'SELECT * FROM wp_users WHERE id = '.$_GET['id'].' AND passwd = "'.$passwd.'"'; echo $sql; //id จะเป็นตัวเลขละ ส่วน $passwd ก็ถูกใส่ slashes เข้าไป |
แต่สำหรับผม ผมชอบใช้ PDO ซึ่งชัวน่าจะ 100% เต็มในการป้อง SQL Injection (ลองแล้วๆ)
โดย PDO จะมี method prepare เพื่อที่จะ bindParam ก่อน execute ได้ ตัวอย่างเช่น
| Code |
| $db = new PDO('mysql:host=localhost;dbname=mydb','root','1234'); $stmt = $db->prepare('SELECT * FROM tbl_users WHERE id = :id AND password = :password LIMIT 1'); $stmt->bindParam(':id',$_GET['id'],PDO::PARAM_INT); $stmt->bindParam(':id',$_GET['passwd'],PDO::PARAM_STR,32); $stmt->execute(); |
PDO จะจัดการให้เรียบร้อย
และสำหรับ PDO ยังมี method quote ไว้ใช้ คล้ายกับ mysql_real_escape_string กรณีที่ต้องการความว่องไว (ขี้เกียจว่างั้น)
| Code |
| $db = new PDO('mysql:host=localhost;dbname=mydb','root','1234'); $stmt = $db->query('SELECT * FROM tbl_user WHERE username = '.$db->quote($_GET['user']).' LIMIT 1'); if($stmt) while($row = $stmt->fetch(PDO::FETCH_ASSOC)) { //.... } |
ขอบคุณ Expert Duck ที่ให้ความรู้ด้านนี้ครับ
ขึ้นไปด้านบน
