ป้ายกำกับ: Static

CGI Security Best Practices (การป้องกัน Shell Injection, การตั้งสิทธิ์ File Permissions และ Suexec บน CGI)CGI Security Best Practices (การป้องกัน Shell Injection, การตั้งสิทธิ์ File Permissions และ Suexec บน CGI)

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

บทความนี้จะเจาะลึกถึงหลักการป้องกันช่องโหว่หลัก 3 ส่วน ได้แก่ Shell Injection, การจัดการสิทธิ์ไฟล์ (File Permissions) และการจำกัดขอบเขตคำสั่ง (Least Privilege) โดยเน้นการประยุกต์ใช้หลักการเหล่านี้ในสภาพแวดล้อมของ PostgreSQL

🛡️ 1. การป้องกัน Shell Injection และ SQL Injection

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

ในบริบทของ PostgreSQL การป้องกันที่ใกล้เคียงและสำคัญที่สุดคือการป้องกัน SQL Injection ซึ่งต้องยึดหลักการสำคัญคือ ห้ามนำค่าอินพุตของผู้ใช้มาต่อสตริงคำสั่ง SQL โดยตรง แต่ต้องใช้กลไกที่เรียกว่า Parameterized Queries เสมอ

🔑 ตัวอย่างการป้องกันด้วย Parameterized Queries ใน PostgreSQL

แทนที่จะสร้างคำสั่ง SQL ด้วยการเชื่อมสตริง (String Concatenation) ซึ่งเสี่ยงต่อการถูกแทรกโค้ด เราควรใช้ตัวแปร Placeholder (เช่น $1, $2) เพื่อให้ PostgreSQL จัดการการแยกแยะระหว่างคำสั่ง SQL และข้อมูลที่ผู้ใช้ป้อนเข้ามาอย่างถูกต้อง

SQL

-- ❌ ตัวอย่างที่ไม่ปลอดภัย (Vulnerable Code - ห้ามใช้) --
-- SELECT * FROM users WHERE username = ' ' || user_input; 

-- ✅ ตัวอย่างที่ปลอดภัย (Secure Code - ใช้ Parameterized Queries) --
SELECT * FROM products WHERE product_id = $1;

-- การเรียกใช้คำสั่ง (ในโค้ดแอปพลิเคชัน): 
-- SELECT * FROM products WHERE product_id = $1 USING '1,2,3';

🔒 2. หลักการ Least Privilege (การให้สิทธิ์น้อยที่สุด)

ไม่ว่าจะเป็นการตั้งสิทธิ์ไฟล์ (File Permissions) หรือสิทธิ์การเข้าถึงฐานข้อมูล เราต้องยึดหลักการ Least Privilege เสมอ นั่นคือการให้สิทธิ์แก่ไฟล์ ผู้ใช้งาน หรือสคริปต์เฉพาะเท่าที่จำเป็นต่อการทำงานเท่านั้น

⚙️ การจำกัดสิทธิ์ใน PostgreSQL

  • User Roles: สร้าง User Role ที่มีสิทธิ์เฉพาะในการอ่าน/เขียนข้อมูลที่จำเป็นเท่านั้น ห้ามใช้ Superuser สำหรับการเชื่อมต่อจาก CGI โดยเด็ดขาด
  • Schema Separation: แยกข้อมูลและฟังก์ชันที่เกี่ยวข้องออกจากกันใน Schema ต่างๆ และกำหนดสิทธิ์การเข้าถึงในระดับ Schema
  • Function Restriction: หากจำเป็นต้องรันคำสั่งที่ซับซ้อน ควรจำกัดการใช้ภาษา Procedural Language ที่สามารถเชื่อมต่อกับ OS ได้ (เช่น PL/Python) ให้เฉพาะผู้ใช้ที่เชื่อถือได้เท่านั้น

💡 3. การจำกัดขอบเขตคำสั่ง (Analogous to Suexec)

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

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

✅ บทสรุป

ความมั่นคงปลอดภัยของ CGI ไม่ใช่การแก้ไขช่องโหว่เพียงจุดเดียว แต่คือการสร้างแนวป้องกันหลายชั้น (Defense in Depth) ตั้งแต่การใช้ Parameterized Queries ในระดับโค้ด, การจำกัดสิทธิ์ผู้ใช้งานในระดับฐานข้อมูล, ไปจนถึงการกำหนดสิทธิ์การเข้าถึงไฟล์และทรัพยากรภายนอก การทำความเข้าใจและปฏิบัติตามหลักการเหล่านี้อย่างเคร่งครัด จะช่วยยกระดับความปลอดภัยของเว็บแอปพลิเคชันของคุณได้อย่างยั่งยืน