อะไรคือ SQL Injection ?
สมมุติหน้าเว็บใช้ชื่อไฟล์ว่า articles_view.php?id=1 และในไฟล์ articles_view.php มี code เขียนว่า
$sql = "select * from articles where id = '$id' ";
ผู้ไม่หวังดีแอบส่งค่าเป็น articles_view.php?id=1'or'1=1 ก็จะสามารถเรียกดูข้อมูลใน database ของเราได้ทั้งหมด (รายละเอียดวิธีทำ ไปหาอ่านใน google เองนะครับ)
วิธีป้องกัน ผมใช้ code นี้ แปะไว้ส่วนบนของไฟล์ php ทุกไฟล์
# ป้องกัน sql injection จาก $_GET
foreach ($_GET as $key => $value) {
$_GET[$key]=addslashes(strip_tags(trim($value)));
}
if ($_GET['id'] !='') { $_GET['id']=(int) $_GET['id']; }
extract($_GET);
บรรทัดที่ 2 หมายความว่า ทุกๆค่าที่ถูกส่งมาด้วยการ GET ให้ตัดช่องว่างด้านหน้าและด้านหลัง แล้วตัดเครื่องหมาย html ออก
คำสั่ง strip_tags นี้ช่วยให้ การแทรก code javascipt ทำงานผิดพลาด เช่นมีคนแทรก javascript มาว่า <script>alert('555');</script> คำสั่ง strip_tags จะทำเหลือแต่ข้อความ alert('555') ซึ่งทำงานไม่ได้ เพราะไม่ได้ระบุว่าเป็น javascript หลังจากนั้นก็ addslashes เข้าไปอีกชั้นนึง ถ้ามีคนส่งค่า 1'or'1=1 เข้ามา จะถูกแปลงเป็น 1'or'1=1 ทำให้คำสั่ง SQL ล้มเหลว ประมวลผลผิด
และตบท้ายด้วยการเช็คค่า id ถ้าไม่ใช่ช่องว่าง ให้แปลง id เป็น integer เท่านั้น และปิดด้วยคำสั่ง extract($_GET) เพื่อรับค่าจากการ GET ทั้งหมด
วิธีนี้ป้องกัน SQL Injection จากทุกหน้าที่รับค่าด้วยการ GET ส่วนหน้าไหนที่มี form submit รับค่าจากการ POST ก็ใช้หลักการเดียวกัน
ยังมีอีกส่วนที่เราต้องป้องกัน คือ การกรอก user, password ตัวแปรที่รับค่าจะต้อง addslashes เข้าไปด้วย เช่น
$username = addslashes(trim($_POST['user']));
$password= addslashes(trim($_POST['pwd']));
ถึงตรงนี้ เราคิดว่าเราป้องกันดีแล้วทั้งจาก GET และ POST แต่ยังมีอีกส่วนหนึ่ง สมมติเรามี webboard ที่อนุญาติให้คนทั่วไปอัพรูปเข้ามาได้ แล้วเรามีหน้า admin ซึ่งตั้งค่าได้ว่า จะอนุญาติให้อัพไฟล์ชนิดใดได้บ้าง แล้วแฮ็กเกอร์เก่งมาก เดา user, password ถูก เข้าสู่หน้า admin ของเราได้ แล้วไปแก้การอนุญาติอัพโหลดไฟล์ ให้อนุญาติไฟล์ .php ด้วย จากนั้นก็อัพไฟล์ .php ของแฮ็คเกอร์ขึ้นเว็บเรา หลังจากนั้น แฮ็กเกอร์ก็จะสามารถจัดการ อัพโหลด ดาวโหลด สั่งลบ ทุกไฟล์ในเว็บเราได้
การป้องกันอีกชั้นนึง คือ ต้องไม่อนุญาติให้อัพโหลดไฟล์ .php อย่างเด็ดขาด ผมใช้ code นี้ในการตรวจสอบการอัพโหลดไฟล์ผ่าน webboard
$filename=$_FILES[$namefile]['name'];
$u1=substr($filename, -3); $u1=strtolower($u1);
// รายชื่อชนิดไฟล์ที่อนุญาติ ที่บันทึกไว้ในฐานข้อมูล
$allowfile=' '.$setting["allow_file"];
// แม้ว่าในฐานข้อมูลจะอนุญาติไฟล์ .php แต่ในขั้นตอนอัพโหลด เราจะยกเลิกไฟล์ php
$u3='php,htm,.pl,cgi,js,asp,swf,com,bat,cmd';
$t1=explode(',', $u3); $len=count($t1);
for ($i=0; $i<$len; $i++) {
$allowfile=str_replace($t1[$i], '', $allowfile);
}
if (strpos($allowfile, $u1) == 0 ) alertBack("ไม่อนุญาติให้อัพโหลดไฟล์ชนิดนี้");