ทำไม File Extension ถึงหลอกเราได้ง่ายๆ
เวลาเราเห็นไฟล์ชื่อ document.pdf เรามักจะเชื่อทันทีว่าเป็นเอกสาร PDF ใช่ไหมครับ แต่ในโลกของโปรแกรมเมอร์และระบบความปลอดภัย ชื่อไฟล์ (File Extension) เป็นเพียงแค่ป้ายชื่อที่แปะไว้ข้างหน้าเท่านั้น ซึ่งใครจะเขียนชื่ออะไรลงไปก็ได้โดยไม่มีข้อจำกัดทางเทคนิคใดๆ เลย
ลองจินตนาการว่าคุณซื้อกล่องขนมมากล่องหนึ่ง ข้างกล่องเขียนว่า "คุกกี้" แต่ข้างในอาจจะเป็นเข็มกับด้ายก็ได้ ไฟล์คอมพิวเตอร์ก็เช่นกันครับ การที่ไฟล์ลงท้ายด้วย .jpg หรือ .exe ไม่ได้การันตีว่าเนื้อหาข้างในเป็นรูปภาพหรือโปรแกรมจริงๆ เสมอไป
นี่คือเหตุผลที่ Fileprobe ถูกสร้างขึ้นมาเพื่อเป็นเครื่องมือการเรียนรู้ด้านการรักษาความปลอดภัย (Defensive Security) โดยเน้นไปที่การตรวจสอบ File Signatures (ลายเซ็นของไฟล์ หรือรหัสชุดแรกที่ระบุประเภทไฟล์จริงๆ) เพื่อให้มือใหม่เข้าใจว่าเราต้องตรวจสอบเนื้อหาข้างใน ไม่ใช่แค่ดูชื่อเรียกภายนอกครับ
รู้จักกับ Fileprobe เครื่องมือตรวจสอบไฟล์เบื้องต้น
Fileprobe คือโปรเจกต์โอเพนซอร์ส (Open Source - ซอฟต์แวร์ที่เปิดเผยโค้ดให้ทุกคนเข้ามาศึกษาหรือพัฒนาต่อได้) ที่เขียนด้วยภาษา C++ (ภาษาโปรแกรมระดับล่างที่ทำงานได้รวดเร็วและจัดการหน่วยความจำได้ละเอียด) โดยมีเป้าหมายเพื่อเป็นสื่อการสอนในโรงเรียนให้เข้าใจเรื่องความปลอดภัย
เครื่องมือนี้ทำหน้าที่อ่านค่า Metadata (ข้อมูลที่อธิบายรายละเอียดเกี่ยวกับตัวไฟล์ เช่น วันที่สร้าง หรือประเภทของข้อมูล) และตรวจสอบลายเซ็นไฟล์ เพื่อยืนยันว่าสิ่งที่เห็นกับสิ่งที่เป็นนั้นตรงกันหรือไม่ มันถูกออกแบบมาให้เรียบง่าย เพื่อให้คนหัดเขียนโค้ดอ่านทำความเข้าใจโครงสร้างโปรแกรมได้ไม่ยากครับ
การใช้เครื่องมือนี้จะช่วยให้เราเห็นกระบวนการทำงานของคอมพิวเตอร์ตอนที่มันพยายามเปิดไฟล์ขึ้นมา มันไม่ได้ดูแค่ชื่อไฟล์ แต่มันจะมองหาค่า Magic Bytes (ไบต์พิเศษที่คอมพิวเตอร์ใช้ระบุประเภทไฟล์) ที่ซ่อนอยู่ต้นไฟล์เสมอ ซึ่งเป็นหัวใจสำคัญของการป้องกันการหลอกลวงด้วยการเปลี่ยนนามสกุลไฟล์ครับ
// ตัวอย่างการอ่านไฟล์แบบเบื้องต้นใน C++
#include <iostream>
#include <fstream>
int main() {
std::ifstream file("test.txt", std::ios::binary); // เปิดไฟล์ในโหมดไบนารี
if (file.is_open()) {
char buffer[4]; // เตรียมที่เก็บข้อมูล 4 ไบต์แรก
file.read(buffer, 4); // อ่านข้อมูลจากไฟล์
std::cout < "Header: " < buffer < std::endl;
file.close();
}
return 0;
}
โค้ดด้านบนใช้ ifstream (คลาสสำหรับอ่านไฟล์) เพื่อเปิดไฟล์ขึ้นมา จากนั้นเรากำหนด buffer (ที่พักข้อมูลชั่วคราว) ขนาด 4 ไบต์เพื่ออ่านข้อมูลชุดแรกของไฟล์ออกมาดู ซึ่งถ้าเป็นไฟล์รูปภาพหรือไฟล์เอกสาร ค่าที่ได้จะแสดงเป็นรหัสเฉพาะที่ต่างกันไปครับ
ผลลัพธ์ที่ได้จากการรันโค้ดนี้ หากไฟล์ test.txt ของคุณมีข้อความข้างใน คุณจะเห็นตัวอักษร 4 ตัวแรกที่อยู่ในไฟล์นั้นปรากฏออกมาบนหน้าจอ ซึ่งนี่คือจุดเริ่มต้นของการทำความเข้าใจว่าคอมพิวเตอร์ "อ่าน" ไฟล์อย่างไรครับ
โครงสร้างของโปรเจกต์ที่มือใหม่ควรรู้
ในการพัฒนาโปรเจกต์ Fileprobe ผู้พัฒนาได้วางโครงสร้างให้เป็นมิตรกับผู้เรียนมากที่สุด โดยหลีกเลี่ยงการใช้คำสั่งที่ซับซ้อนเกินจำเป็น เพื่อให้มือใหม่สามารถไล่เรียง Control Flow (ลำดับการทำงานของโปรแกรมตั้งแต่ต้นจนจบ) ได้อย่างเป็นธรรมชาติครับ
โปรเจกต์นี้ไม่ได้มีไว้เพื่อเจาะระบบหรือทำลายข้อมูล แต่มีไว้เพื่อการศึกษาเท่านั้น ดังนั้นการอ่านโค้ดของโปรเจกต์นี้จะทำให้คุณเห็นแนวปฏิบัติที่ดีในการจัดการกับ Input (ข้อมูลที่รับเข้ามาจากผู้ใช้) และการทำ Error Handling (การจัดการข้อผิดพลาดเมื่อโปรแกรมทำงานไม่เป็นไปตามเป้าหมาย) อย่างถูกต้อง
ถ้าคุณอยากเก่งขึ้น ให้ลองโหลดโค้ดจาก Repository (ที่เก็บโค้ดของโปรเจกต์) ไปลองเปิดดูในโปรแกรมแก้ไขโค้ดของคุณ แล้วลองตั้งคำถามว่า "ถ้าฉันใส่ไฟล์ที่ไม่มีอยู่จริงเข้าไป โปรแกรมจะพังไหม" หรือ "โปรแกรมจะแจ้งเตือนอย่างไร" ซึ่งนี่คือทักษะสำคัญของโปรแกรมเมอร์ที่เก่งครับ
ตัวอย่างการตรวจสอบความถูกต้องของไฟล์
หัวใจสำคัญของ Fileprobe คือการเปรียบเทียบค่าที่อ่านได้กับตารางข้อมูลอ้างอิง หากค่าที่อ่านได้ไม่ตรงกับนามสกุลไฟล์ โปรแกรมจะแจ้งเตือนทันที ซึ่งเป็นหลักการเดียวกับที่ซอฟต์แวร์แอนตี้ไวรัสใช้ตรวจสอบไฟล์ที่น่าสงสัยในเครื่องคอมพิวเตอร์ของเรา
ลองดูตัวอย่างการเขียนเงื่อนไขเพื่อตรวจสอบประเภทไฟล์กันครับ เราจะใช้คำสั่ง if เพื่อเปรียบเทียบค่าที่อ่านมาได้กับค่ามาตรฐานที่เรารู้จัก หากค่าไม่ตรงกัน เราจะให้โปรแกรมแสดงข้อความแจ้งเตือนผู้ใช้ว่าอาจมีความผิดปกติเกิดขึ้นกับไฟล์นี้
// ตรวจสอบลายเซ็นไฟล์ง่ายๆ
if (buffer[0] == 'P' && buffer[1] == 'K') {
std::cout << "นี่คือไฟล์ ZIP ครับ";
} else {
std::cout << "ไฟล์นี้ไม่ตรงกับประเภทที่ควรจะเป็น";
}
ในโค้ดนี้ เราตรวจสอบว่าไบต์แรกและไบต์ที่สองเป็นตัวอักษร P และ K หรือไม่ ซึ่งเป็นสัญลักษณ์มาตรฐานของไฟล์ประเภท .zip ถ้าใช่โปรแกรมจะบอกว่าเป็นไฟล์บีบอัด แต่ถ้าไม่ใช่ โปรแกรมจะแจ้งเตือนว่าไฟล์อาจถูกแก้ไขหรือมีปัญหาครับ
ผลลัพธ์ที่ได้จะแสดงข้อความเตือนออกมาหากคุณนำไฟล์ที่ไม่ใช่ไฟล์ ZIP มาทดสอบ การเขียนโปรแกรมแบบนี้ช่วยให้เราสร้างระบบที่ปลอดภัยและลดความเสี่ยงจากการใช้งานไฟล์ที่ผิดประเภทโดยไม่ตั้งใจได้ดีมากครับ
ฝึกฝนด้วยการลงมือทำจริง
วิธีเรียนรู้ที่ดีที่สุดไม่ใช่การอ่านหนังสือไปเรื่อยๆ แต่คือการหยิบโปรเจกต์อย่าง Fileprobe มาลองรันบนเครื่องตัวเอง ลองสร้างไฟล์ธรรมดาๆ ขึ้นมา แล้วลองใช้โปรแกรมตรวจสอบดูว่ามันอ่านค่าอะไรออกมาได้บ้าง หลังจากนั้นลองเปลี่ยนนามสกุลไฟล์เล่นๆ เพื่อดูว่าโปรแกรมตอบสนองอย่างไร
การลองผิดลองถูกในสภาพแวดล้อมที่ปลอดภัย (Local Machine) จะทำให้คุณเข้าใจเรื่อง Binary Data (ข้อมูลดิบในรูปแบบเลขฐานสอง) ได้ดีกว่าการอ่านทฤษฎีหลายเท่าตัว อย่าลืมจดบันทึกสิ่งที่คุณค้นพบลงในสมุดหรือบล็อกส่วนตัวของคุณด้วยนะครับ
เมื่อคุณเริ่มเข้าใจแล้วว่าคอมพิวเตอร์มองเห็นไฟล์อย่างไร คุณจะเริ่มมองเห็นช่องโหว่เล็กๆ น้อยๆ ในซอฟต์แวร์ทั่วไป และนั่นแหละครับคือจุดเริ่มต้นของนักพัฒนาที่ใส่ใจในเรื่องความปลอดภัย ซึ่งเป็นทักษะที่บริษัทซอฟต์แวร์ชั้นนำต้องการตัวมากที่สุดในปัจจุบันครับ
สรุปบทเรียนจาก Fileprobe
Fileprobe สอนให้เราเห็นว่าความปลอดภัยไม่ใช่เรื่องไกลตัว และการเขียนโปรแกรมที่ดีต้องคำนึงถึงความถูกต้องของข้อมูลเสมอ แม้จะเป็นเพียงโปรเจกต์เพื่อการศึกษา แต่แนวคิดเรื่องการตรวจสอบ File Signatures นั้นเป็นพื้นฐานที่สำคัญมากสำหรับนักพัฒนาทุกคนที่อยากก้าวเข้าสู่สายงานความปลอดภัยไซเบอร์
จำไว้ว่าในฐานะโปรแกรมเมอร์ อย่าเชื่อถือข้อมูลที่รับเข้ามาจากภายนอกโดยเด็ดขาด ไม่ว่าจะเป็นชื่อไฟล์ หรือข้อมูลที่ผู้ใช้กรอกเข้ามา การฝึกตรวจสอบข้อมูลให้ละเอียดตั้งแต่ต้นคือวินัยที่จะทำให้คุณเป็นโปรแกรมเมอร์ที่เขียนโค้ดได้อย่างมีคุณภาพและปลอดภัยครับ
หากคุณอยากเริ่มต้น ให้ลองไปที่หน้า GitHub ของโปรเจกต์ แล้วลองอ่านโค้ดส่วนที่จัดการไฟล์ดูครับ ถ้าติดขัดตรงไหน ลองหาข้อมูลเพิ่มเติมเกี่ยวกับ std::ifstream หรืออ่านเอกสารเรื่อง File Headers เพิ่มเติม แล้วคุณจะพบว่าโลกของการเขียนโปรแกรมนั้นยังมีอะไรให้สนุกอีกเยอะเลยครับ
ที่มา: Fileprobe - Educational Defensive Security Tool — DEV Community