SQL - การฉีด
หากคุณป้อนข้อมูลผู้ใช้ผ่านหน้าเว็บและแทรกลงในฐานข้อมูล SQL มีโอกาสที่คุณจะเปิดกว้างสำหรับปัญหาด้านความปลอดภัยที่เรียกว่า SQL Injection. บทนี้จะสอนวิธีช่วยป้องกันไม่ให้สิ่งนี้เกิดขึ้นและช่วยให้คุณรักษาความปลอดภัยสคริปต์และคำสั่ง SQL ในสคริปต์ฝั่งเซิร์ฟเวอร์ของคุณเช่นสคริปต์ PERL
การฉีดมักเกิดขึ้นเมื่อคุณขอให้ผู้ใช้ป้อนข้อมูลเช่นชื่อของพวกเขาและแทนที่จะเป็นชื่อที่พวกเขาให้คำสั่ง SQL กับคุณซึ่งคุณจะเรียกใช้ฐานข้อมูลโดยไม่รู้ตัว อย่าเชื่อถือข้อมูลที่ผู้ใช้ให้มาประมวลผลข้อมูลนี้หลังจากการตรวจสอบแล้วเท่านั้น ตามกฎแล้วสิ่งนี้ทำได้โดยPattern Matching.
ในตัวอย่างด้านล่างไฟล์ name ถูก จำกัด ไว้ที่อักขระที่เป็นตัวอักษรและตัวเลขคละกันและขีดล่างและมีความยาวระหว่าง 8 ถึง 20 อักขระ (แก้ไขกฎเหล่านี้ตามต้องการ)
if (preg_match("/^\w{8,20}$/", $_GET['username'], $matches)) {
$result = mysql_query("SELECT * FROM CUSTOMERS
WHERE name = $matches[0]");
} else {
echo "user name not accepted";
}
เพื่อแสดงให้เห็นถึงปัญหาให้พิจารณาข้อความที่ตัดตอนมานี้ -
// supposed input
$name = "Qadir'; DELETE FROM CUSTOMERS;";
mysql_query("SELECT * FROM CUSTOMSRS WHERE name='{$name}'");
การเรียกใช้ฟังก์ชันควรดึงข้อมูลจากตาราง CUSTOMERS โดยที่คอลัมน์ชื่อตรงกับชื่อที่ผู้ใช้ระบุ ภายใต้สถานการณ์ปกติ$nameจะมีเพียงอักขระที่เป็นตัวเลขและตัวอักษรและอาจเว้นวรรคเช่นสตริง ilia แต่ที่นี่การต่อท้ายคำค้นหาใหม่ทั้งหมดกับ $ name การเรียกฐานข้อมูลกลายเป็นหายนะ แบบสอบถาม DELETE ที่ฉีดจะลบระเบียนทั้งหมดออกจากตาราง CUSTOMERS
โชคดีถ้าคุณใช้ MySQL ไฟล์ mysql_query()ฟังก์ชันไม่อนุญาตให้มีการซ้อนคิวรีหรือเรียกใช้การสืบค้น SQL หลายรายการในการเรียกใช้ฟังก์ชันเดียว หากคุณพยายามซ้อนคิวรีการโทรล้มเหลว
อย่างไรก็ตามส่วนขยายฐานข้อมูล PHP อื่น ๆ เช่น SQLite และ PostgreSQL ดำเนินการค้นหาแบบเรียงซ้อนอย่างมีความสุขดำเนินการค้นหาทั้งหมดที่มีให้ในสตริงเดียวและสร้างปัญหาด้านความปลอดภัยที่ร้ายแรง
การป้องกัน SQL Injection
คุณสามารถจัดการอักขระ Escape ทั้งหมดได้อย่างชาญฉลาดในภาษาสคริปต์เช่น PERL และ PHP ส่วนขยาย MySQL สำหรับ PHP มีฟังก์ชันmysql_real_escape_string() เพื่อหลีกเลี่ยงอักขระอินพุตที่พิเศษสำหรับ MySQL
if (get_magic_quotes_gpc()) {
$name = stripslashes($name);
}
$name = mysql_real_escape_string($name);
mysql_query("SELECT * FROM CUSTOMERS WHERE name='{$name}'");
ชอบความไม่แน่ใจ
ในการจัดการกับปัญหา LIKE กลไกการหลีกเลี่ยงที่กำหนดเองต้องแปลงอักขระ '%' และ '_' ที่ผู้ใช้จัดหาให้เป็นตัวอักษร ใช้addcslashes()ซึ่งเป็นฟังก์ชันที่ให้คุณระบุช่วงอักขระที่จะหลบหนี
$sub = addcslashes(mysql_real_escape_string("%str"), "%_");
// $sub == \%str\_
mysql_query("SELECT * FROM messages
WHERE subject LIKE '{$sub}%'");