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}%'");