Script Injection/SQL Injection ความปลอดภัยพื้นฐานสำหรับเว็บ

by lew
8 April 2013 - 15:08

แม้ปัญหาความปลอดภัยจะเริ่มต้นในยุคแรกๆ ในโลกด้วยปัญหา buffer overflow แต่เมื่อโลกเข้าสู่ยุคของเว็บ และโดยเฉพาะเมื่อเว็บเริ่มไม่ใช่ไฟล์ html เปล่าๆ แต่เป็นเว็บที่สามารถปรับตามผู้ใช้งานได้ เริ่มจากยุคของ CGI ที่เป็นโปรแกรมภาษาต่างๆ เรื่อยมาถึงเว็บเซิร์ฟเวอร์แบบอื่นไม่ว่าจะเป็น J2EE หรือระบบ fastcgi ปัญหาความปลอดภัยของเว็บก็กลายเป็นปัญหาใหญ่ที่โลกเจอกันเรื่อยมาจนทุกวันนี้

ปัญหา script injection หรือการใส่สคริปต์เข้ามาในเซิร์ฟเวอร์นั้นเป็นการโจมตีที่ตรงตัวกับชื่อของมัน เมื่อเซิร์ฟเวอร์เปิดให้อัพโหลดไฟล์เข้าไปยังเซิร์ฟเวอร์ ไม่ว่าจะเป็นการอัพโหลดภาพ หรือการอัพโหลดไฟล์อื่นๆ ในเว็บเซิร์ฟเวอร์ที่รันไฟล์ภาษาสคริปต์นั้น โดยทั่วไปแล้วจะถูกคอนฟิกให้รันทุกไฟล์สคริปต์ เช่น เว็บเซิร์ฟเวอร์ Apache ที่ติดตั้ง PHP ทุกวันนี้จะถูกคอนฟิกให้รันทุกไฟล์ที่ลงท้ายชื่อไฟล์ด้วย ".php"

เว็บแอพพลิเคชั่นที่ไม่ระมัดระวังเพียงพอจะปล่อยให้มีการอัพโหลดชื่อไฟล์ที่ตรงตามเงื่อนไขของสคริปต์ ส่งผลให้แฮกเกอร์สามารถส่งไฟล์ใดๆ ขึ้นมารันบนเครื่อง และเมื่อรันแล้วจะได้สิทธิเท่ากับเว็บเซิร์ฟเวอร์ทุกประการ เช่น การอ่านไฟล์ทั้งหมด, การอ่านฐานข้อมูล (เพราะสามารถอ่านไฟล์คอนฟิกของเว็บแอพพลิเคชั่นได้) จนกระทั่งในเซิร์ฟเวอร์รุ่นเก่าๆ นั้น นิยมตั้งให้เว็บเซิร์ฟเวอร์ทำงานในฐานะผู้ใช้ root จะส่งผลให้การเผอเรอเพียงการปล่อยให้ผู้ใช้อัพโหลดไฟล์โดยไม่ตรวจสอบเพียงจุดเดียวสร้างความเสียหายได้อย่างมาก

ระบบจัดการเนื้อหารุ่นใหม่ๆ เมื่อมีส่วนใดที่ต้องรับไฟล์อัพโหลดจากผู้ใช้ มักจะจัดให้อยู่ในโฟลเดอร์เดียวกันทั้งหมด พร้อมกับตรวจสอบชื่อไฟล์ว่าไม่มีชื่อไฟล์ใดที่จะสามารถรันได้ เช่น การจำกัดชื่อไฟล์ให้รับเฉพาะไฟล์ที่ไม่สามารถรันได้ เช่นไฟล์ PNG, JPG หรือ PDF ใน กระบวนการรักษาความปลอดภัยจึงอาจจะทำได้โดยการคอนฟิกยกเลิกไม่ให้เว็บเซิร์ฟเวอร์รันสคริปต์ใดๆ ในโฟลเดอร์ที่ใช้สำหรับการรับไฟล์อัพโหลด และหากต้องการเพิ่มประเภทไฟล์ที่รับอัพโหลด ควรระวังไม่รับไฟล์ที่สามารถรันบนเซิร์ฟเวอร์ได้ เช่น สคริปต์ภาษาต่างๆ รวมถึงภาษาที่อาจจะไม่ได้ใช้งาน อย่างภาษา Perl (.pl)

นอกจากการอัพโหลดไฟล์แล้ว หลายครั้งสคริปต์ในการรันนั้นมีการนำอินพุตของผู้ใช้ไปเชื่อมกับสตริงเพื่อสร้างคำสั่งใหม่

$myvar = 'somevalue';
$x = $_GET['arg'];
eval('$myvar = ' . $x . ';');

คำสั่งเช่นนี้เปิดโอกาสให้ผู้ที่ใส่อินพุตเพื่อมุ่งร้ายต่อระบบสามารถเพิ่มคำสั่งอื่นๆ เช่น การใส่อินพุตเป็น 10; system('/bin/echo uh-oh') ทำให้อินพุตเช่นนี้สามารถรันคำสั่งใดๆ ก็ได้ตามที่ผู้ใช้ที่มุ่งร้ายต้องการในสิทธิเท่ากับที่เว็บเซิร์ฟเวอร์สามารถทำได้

กระบวนการนี้เจาะผ่านช่องโหว่ที่ซอฟต์แวร์กลั่นกรองอินพุตจากผู้ใช้ไม่ดีพอเช่นนี้เป็นปัญหาที่พบบ่อย โดยเฉพาะการใช้งานกับระบบฐานข้อมูล SQL ที่สคริปต์เว็บต่างๆ ต้องสร้างคำสั่ง SQL ไปยังฐานข้อมูล เราเรียกช่องโหว่เช่นนี้ว่า SQL Injection ตัวอย่างเช่นการสร้าง SQL จากอินพุต

$statement = "SELECT * FROM users WHERE name = '" + userName + "';";

ในคำสั่งเช่นนี้ไม่มีการตรวจสอบตัวแปร userName ที่เป็นอิตพุตก่อนใช้งาน อินพุตที่มุ่งร้ายอาจจะเป็น ' or '1'='1 ทำให้คำสั่ง SQL สุดท้ายกลายเป็นเป็น การเรียกรายชื่อผู้ใช้ทั้งหมดจากฐานข้อมูล

SELECT * FROM users WHERE name = '' OR '1'='1';

คำสั่งที่มุ่งร้ายในการดึงข้อมูลออกมาจากฐานข้อมูลเป็นแหล่งสำคัญที่เว็บต่างๆ ถูกเจาะฐานข้อมูลออกมา ผู้ร้ายบางส่วนอาจจะใช้ช่องโหว่แบบเดียวกันลบฐานข้อมูลออกไปทั้งหมด สร้างความเสียหายให้กับระบบมากยิ่งขึ้น

ระบบจัดการเนื้อหา และเว็บเฟรมเวิร์ครุ่นใหม่ๆ ทั้งหมดล้วนมีกระบวนการกรองอินพุตผู้ใช้ สำหรับคำสั่ง SQL นั้นการพัฒนาเว็บในช่วงหลังจะไม่แนะนำให้สร้างคำสั่ง SQL โดยตรงอีกต่อไป แต่แนะนำให้ครอบคำสั่งด้วยด้วยชั้นซอฟต์แวร์ เช่น ORM (object-relational mapping) ทำให้ผู้ใช้ที่มุ่งร้ายไม่สามารถสร้างโค้ดคำสั่งนอกเหนือจากรูปแบบที่เราต้องการได้อีกต่อไป

สำหรับ PHP ที่นิยมใช้ทำเว็บนั้น ในรุ่นหลังๆ มีการเพิ่มชั้น PHP Data Objects (PDO) ที่กระบวนการทำงานง่ายกว่า ORM แต่มีกระบวนการกรองอินพุตเช่น

$db = new PDO('mysql:host=localhost;dbname=', '', 'PASSWORD');
$stmt = $db->prepare("select contenttype, imagedata from images where id=?");
$stmt->execute(array($_GET['id']));

กระบวนการนี้ทำให้ผู้ใช้ที่มุ่งร้ายไม่สามารถสร้างอินพุตที่ทำงานนอกเหนือจากที่โค้ดกำหนดไว้ได้

กระบวนการเจาะเว็บในยุคหลังมีซอฟต์แวร์สามารถสแกนเว็บเพื่อค้นหาช่องโหว่ต่างๆ ได้อย่างมีประสิทธิภาพ การสร้างเว็บในยุคหลังจึงควรทำตามคำแนะนำของเฟรมเวิร์คต่างๆ อย่างระมัดระวัง แต่กระนั้นแม้แต่ระบบจัดการเนื้อหาชื่อดังจำนวนมากก็มีช่องโหว่ค้นพบใหม่อยู่เป็นระยะ การอัพเดตซอฟต์แวร์ให้ทันสมัยเสมอจึงเป็นเรื่องจำเป็น แม้จะเป็นการใช้เฟรมเวิร์คก็ตาม

ตัวอย่างจากในบทความนี้นำมาจาก Wikipedia: Code Injection, Wikipedia: SQL Injection, และ PHP Manual: PDO

Blognone Jobs Premium