เมื่อ “อัปโหลด” กลายเป็น “แฮก”: แกะรอยช่องโหว่ความปลอดภัยของฟังก์ชันอัปโหลดไฟล์

เมื่อ “อัปโหลด” กลายเป็น “แฮก”: แกะรอยช่องโหว่ความปลอดภัยของฟังก์ชันอัปโหลดไฟล์

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

ลองมาดูกันว่าช่องโหว่นี้ทำงานอย่างไร และเราจะป้องกันมันได้อย่างไรบ้าง จากระดับความเสี่ยงที่ต่างกัน

ระดับความปลอดภัยต่ำ: อัปโหลดได้ทุกอย่าง ทุกนามสกุล

ลองจินตนาการถึงระบบที่แทบไม่มีการป้องกันอะไรเลย เมื่อผู้ใช้งานอัปโหลดไฟล์ ระบบจะรับไฟล์นั้นไปเก็บไว้ทันที โดยไม่สนว่าไฟล์นั้นเป็นอะไร มีนามสกุลแบบไหน หรือมีเนื้อหาอะไรอยู่ข้างใน ในสถานการณ์แบบนี้ ผู้โจมตีสามารถอัปโหลด ไฟล์เว็บเชลล์ (Web Shell) ที่เป็นสคริปต์อันตราย เช่น ไฟล์ PHP หรือ ASP ที่ถูกออกแบบมาเพื่อสั่งงานเซิร์ฟเวอร์โดยเฉพาะ เมื่อไฟล์นี้ถูกอัปโหลดขึ้นไปและเรียกใช้งานได้สำเร็จ ผู้โจมตีก็จะสามารถเข้าถึงข้อมูล สั่งรันคำสั่ง หรือแม้แต่ควบคุมเซิร์ฟเวอร์นั้นได้อย่างสมบูรณ์ ถือเป็นความเสี่ยงที่ร้ายแรงที่สุดและง่ายต่อการเจาะมากที่สุด

ระดับความปลอดภัยปานกลาง: เริ่มมีการตรวจสอบนามสกุลและประเภทไฟล์

เมื่อระบบเริ่มมีการป้องกันมากขึ้น โดยจะตรวจสอบ นามสกุลไฟล์ (เช่น .jpg, .png) หรือ ประเภทไฟล์ (MIME Type) ที่ระบุอยู่ใน HTTP Header ว่าเป็นไฟล์ภาพที่อนุญาตหรือไม่ แต่ถึงอย่างนั้น ก็ยังมีวิธีเลี่ยงการตรวจสอบได้หลายแบบ

  • ปลอมแปลง MIME Type: ผู้โจมตีสามารถใช้เครื่องมือดักจับข้อมูล (Proxy Tool) อย่าง Burp Suite เพื่อแก้ไขค่า Content-Type ใน HTTP Header ให้เป็น image/jpeg หรือ image/png แม้ว่าไฟล์ที่อัปโหลดจะเป็นไฟล์เว็บเชลล์ก็ตาม ระบบก็จะหลงเชื่อและอนุญาตให้อัปโหลด
  • นามสกุลคู่: บางระบบอาจตรวจสอบแค่นามสกุลสุดท้ายของไฟล์ หากผู้โจมตีอัปโหลด shell.php.jpg ระบบอาจมองว่าเป็น .jpg แต่ถ้าเซิร์ฟเวอร์ถูกตั้งค่าไม่ถูกต้อง อาจตีความและรันไฟล์นั้นเป็น PHP ได้
  • หลอกด้วยไฟล์ .htaccess: ในบางกรณี ผู้โจมตีสามารถอัปโหลดไฟล์ .htaccess (สำหรับเซิร์ฟเวอร์ Apache) เพื่อสั่งให้เซิร์ฟเวอร์มองไฟล์นามสกุล .jpg เป็นไฟล์ PHP จากนั้นก็อัปโหลดไฟล์เว็บเชลล์ที่เปลี่ยนนามสกุลเป็น .jpg เพื่อให้ถูกรันได้

ระดับความปลอดภัยสูง: ตรวจสอบเนื้อหาภายในไฟล์ว่าเป็นรูปจริงหรือไม่

ระบบที่ปลอดภัยขึ้นอีกขั้น จะไม่เพียงแค่ตรวจสอบนามสกุลหรือ MIME Type เท่านั้น แต่จะพยายามตรวจสอบ เนื้อหาภายในไฟล์ ว่าเป็นภาพจริงหรือไม่ โดยใช้ฟังก์ชันเฉพาะ (เช่น getimagesize() ใน PHP) เพื่อยืนยันว่าเป็นไฟล์ภาพที่ถูกต้องตามโครงสร้างข้อมูล

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

ระดับความปลอดภัยขั้นสูงสุด: ตรวจสอบ ประมวลผล และสร้างไฟล์ใหม่

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

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