- 20
- กุมภาพันธ์
SQL Injection เป็นช่องโหว่ด้านความปลอดภัยที่ถูกจัดอันดับ อันดับ 1 ใน OWASP Top 10 มาอย่างต่อเนื่อง — เป็นการโจมตีที่ผู้ไม่หวังดีส่งคำสั่ง SQL แทรกเข้าไปในช่องกรอกข้อมูลของแอปพลิเคชัน เพื่อเข้าถึง แก้ไข หรือลบข้อมูลในฐานข้อมูลโดยไม่ได้รับอนุญาต บทความนี้จะอธิบายว่า SQL Injection อันตรายอย่างไร และทำไม ORM (Object-Relational Mapping) กับ Parameterized Query ถึงเป็นแนวทางป้องกันที่ดีที่สุด — รวมถึงหลักการออกแบบที่ Saeree ERP ใช้ป้องกันช่องโหว่นี้ตั้งแต่สถาปัตยกรรม
SQL Injection คืออะไร?
SQL Injection คือเทคนิคที่ผู้โจมตี แทรกคำสั่ง SQL เข้าไปในข้อมูลที่ผู้ใช้ป้อน (เช่น ช่อง Login, ช่องค้นหา) เพื่อให้ระบบประมวลผลคำสั่ง SQL ที่ไม่ได้ตั้งใจ
ปัญหาเกิดจากอะไร?
ต้นเหตุคือการที่นักพัฒนา นำข้อมูลจากผู้ใช้ไปต่อรวมกับคำสั่ง SQL โดยตรง — ทำให้ผู้โจมตีสามารถ "หลอก" ระบบให้เข้าใจผิดว่าข้อมูลที่ส่งมาเป็นส่วนหนึ่งของคำสั่ง SQL ไม่ใช่แค่ข้อมูลธรรมดา
หลักการโจมตี (แบบย่อ):
ผู้โจมตีป้อนข้อมูลพิเศษในช่อง Login หรือช่องค้นหา ที่ทำให้เงื่อนไข SQL เป็นจริงเสมอ → เข้าระบบได้โดยไม่ต้องมี password หรือสามารถดึง/แก้ไข/ลบข้อมูลในฐานข้อมูลทั้งหมดได้
ความเสียหายที่เกิดขึ้นได้
| ประเภทการโจมตี | ผลกระทบ |
|---|---|
| Bypass Authentication | เข้าระบบโดยไม่ต้องรู้ password |
| Data Exfiltration | ดึงข้อมูลผู้ใช้, ข้อมูลการเงิน, ข้อมูลลูกค้าทั้งหมดออกมา |
| Data Destruction | ลบตาราง หรือแก้ไขข้อมูลในฐานข้อมูลทั้งระบบ |
| Privilege Escalation | เปลี่ยนสิทธิ์ผู้ใช้ธรรมดาให้เป็น admin |
ทำไมระบบ ERP ถึงเป็นเป้าหมายหลัก?
ระบบ ERP เก็บข้อมูลสำคัญที่สุดขององค์กร:
- ข้อมูลการเงิน — รายรับ-รายจ่าย, งบดุล, บัญชีธนาคาร
- ข้อมูลบุคลากร — เงินเดือน, เลขบัตรประชาชน, เลขบัญชีธนาคาร
- ข้อมูลลูกค้า — ที่อยู่, เลขประจำตัวผู้เสียภาษี, ยอดสั่งซื้อ
- ข้อมูลสต็อก — ราคาต้นทุน, ปริมาณสินค้า, supplier
ถ้าระบบ ERP มีช่องโหว่ SQL Injection ผู้โจมตีสามารถเข้าถึงข้อมูลทั้งหมดนี้ได้ — ทั้งยังเสี่ยงต่อการละเมิด พ.ร.บ. คุ้มครองข้อมูลส่วนบุคคล (PDPA) อีกด้วย
วิธีป้องกัน SQL Injection
มี 2 แนวทางหลักที่ถือเป็นมาตรฐานสากล:
แนวทางที่ 1: Parameterized Query (Prepared Statement)
แทนที่จะ "ต่อ String" เป็น SQL ตรงๆ — ให้ใช้ ตัวยึดตำแหน่ง (Placeholder) ? แล้วส่งค่าแยกต่างหาก:
หลักการ:
แทนที่จะเขียน WHERE name = '(ค่าจาก user)' ตรงๆ
ให้เขียน WHERE name = ? แล้ว bind ค่าแยกต่างหาก
Database Driver จะแยก "โครงสร้าง SQL" ออกจาก "ค่าข้อมูล" — ถึงผู้โจมตีจะส่งข้อมูลอันตรายมา ระบบก็จะมองเป็นข้อความธรรมดา ไม่ใช่คำสั่ง SQL
แนวทางที่ 2: ORM (Object-Relational Mapping)
ORM คือ เลเยอร์ที่อยู่ระหว่างโค้ดกับฐานข้อมูล — นักพัฒนาทำงานกับ Object แทนการเขียน SQL ตรงๆ เช่น การสร้างข้อมูลใหม่ แค่สร้าง Object → set ค่า → สั่ง save → Framework จะสร้างคำสั่ง INSERT ให้โดยอัตโนมัติในรูปแบบ Parameterized Query
ORM ป้องกัน SQL Injection ได้เพราะ:
- ไม่มีการเขียน SQL ด้วยมือ — Framework สร้าง SQL ให้
- ใช้ Parameterized Query ภายใน — ค่าทุกตัวถูก bind แยกจาก SQL
- Type-safe — ตัวแปร int ก็ต้องเป็น int, String ก็ต้องเป็น String ป้องกันการส่งข้อมูลผิดประเภท
Saeree ERP ป้องกัน SQL Injection อย่างไร
Saeree ERP ถูกออกแบบสถาปัตยกรรมทั้งระบบให้ ไม่มีการต่อ SQL String จากข้อมูลผู้ใช้โดยตรง ตั้งแต่ระดับ Framework โดยใช้หลักการดังนี้:
1. ORM Pattern สำหรับทุกการเขียนข้อมูล
การ INSERT, UPDATE, DELETE ข้อมูลทั้งหมดใน Saeree ERP ใช้ ORM (Object-Relational Mapping) — นักพัฒนาทำงานกับ Object โดยไม่ต้องเขียน SQL เลย Framework จะสร้างคำสั่ง SQL ให้โดยอัตโนมัติในรูปแบบ Parameterized Query
ตัวอย่างแนวคิด: การสร้างข้อมูลในระบบ
แนวทางของ Saeree ERP:
- สร้าง Object ตาม Business Entity (เช่น คู่ค้า, พนักงาน, ใบสั่งซื้อ)
- กำหนดค่าผ่าน setter method (เช่น
setName(),setTaxID()) - สั่ง
save()→ Framework สร้าง INSERT/UPDATE แบบ Parameterized ให้อัตโนมัติ - ทุกอย่างอยู่ใน Transaction — ถ้าผิดพลาดก็ rollback ทั้งหมด
ตัวอย่างแนวคิด: การลงทะเบียนพนักงานใหม่
กระบวนการ:
- เปิด Transaction
- สร้าง Object ข้อมูลบุคคล → set ชื่อ, นามสกุล, เลขประจำตัว → save
- สร้าง Object ข้อมูล HR → เชื่อมกับข้อมูลบุคคล → save
- สร้าง Object บัญชีผู้ใช้ → set อีเมล → save
- Commit Transaction — ทั้ง 3 รายการสำเร็จพร้อมกัน หรือยกเลิกทั้งหมด
ไม่มี SQL Statement แม้แต่บรรทัดเดียวในโค้ด — ORM Framework จัดการให้ทั้งหมด
2. Parameterized Query สำหรับทุกการอ่านข้อมูล
สำหรับการดึงข้อมูล (SELECT) ที่จำเป็นต้องเขียน SQL — Saeree ERP ใช้ Prepared Statement + Placeholder ? ทุกจุด ค่าจากผู้ใช้จะถูก bind แยกต่างหากเสมอ ไม่เคยถูกนำไปต่อกับ SQL String โดยตรง
หลักการ:
- SQL ใช้
?เป็น placeholder ทุกที่ที่มีค่าจากผู้ใช้ - ค่าจริงถูก bind ผ่าน
setInt(),setString(),setTimestamp()แยกต่างหาก - แม้แต่การค้นหาแบบ Dynamic (หลายเงื่อนไข) ก็เพิ่มเฉพาะ
?ไม่เคยเอาค่ามาต่อใน SQL
3. แยกชั้นข้อมูลชัดเจน (Layered Architecture)
Saeree ERP แบ่งสถาปัตยกรรมเป็น 3 ชั้นที่ชัดเจน:
| ชั้น (Layer) | หน้าที่ | มี SQL หรือไม่ |
|---|---|---|
| API Layer | รับ-ส่งข้อมูลกับ Client (REST API) | ไม่มี SQL |
| Service Layer | ประมวลผล Business Logic | ใช้ ORM + Parameterized Query เท่านั้น |
| Data Model | รับ-ส่งข้อมูลระหว่างชั้น (DTO) | ไม่มี SQL — เป็น Pure Data Object |
การแยกชั้นแบบนี้ทำให้ ข้อมูลจาก user ไม่มีทางสัมผัส SQL โดยตรง — ทุกอย่างต้องผ่าน ORM หรือ Parameterized Query เสมอ
สรุปหลักการป้องกัน SQL Injection ของ Saeree ERP
| Operation | วิธีที่ใช้ | ความเสี่ยง SQL Injection |
|---|---|---|
| INSERT (สร้างข้อมูล) | ORM Object → save | ไม่มี — Framework สร้าง Parameterized SQL |
| UPDATE (แก้ไข) | ORM Object → save | ไม่มี — Framework สร้าง Parameterized SQL |
| DELETE (ลบ) | ORM Object → delete | ไม่มี — Framework สร้าง Parameterized SQL |
| SELECT (ค้นหา) | Parameterized Query + Placeholder | ไม่มี — ค่า bind แยกจาก SQL |
| Login (ยืนยันตัวตน) | Parameterized Query + Security Framework | ไม่มี — ทุก parameter ถูก bind |
เปรียบเทียบ: โค้ดที่มีช่องโหว่ vs โค้ดของ Saeree ERP
| โค้ดที่มีช่องโหว่ | โค้ดของ Saeree ERP |
|---|---|
| เอาค่าจาก user มาต่อ SQL ตรงๆ | ใช้ Placeholder แล้ว bind ค่าแยกต่างหาก |
| เขียน INSERT/UPDATE ด้วย SQL เอง | ใช้ ORM Object — Framework สร้าง SQL ให้ |
| SQL กับข้อมูลอยู่ใน String เดียวกัน | SQL กับข้อมูลแยกกัน 100% |
| ขึ้นอยู่กับนักพัฒนาแต่ละคน | Framework บังคับให้ปลอดภัยโดยการออกแบบ |
SQL Injection ป้องกันได้ 100% ถ้าออกแบบถูกตั้งแต่แรก — Saeree ERP เลือกใช้ ORM สำหรับการเขียนข้อมูลทั้งหมด และ Parameterized Query สำหรับการอ่านข้อมูลทุกจุด ทำให้ข้อมูลของผู้ใช้ไม่มีทางกลายเป็นคำสั่ง SQL ได้
- ทีมพัฒนา Saeree ERP
Checklist สำหรับองค์กร — ระบบของคุณปลอดภัยจาก SQL Injection หรือยัง?
| ☐ | ทุก SQL Query ใช้ Parameterized Query / Prepared Statement หรือไม่? |
| ☐ | ไม่มีการต่อ String จาก user input เข้า SQL ตรงๆ? |
| ☐ | ใช้ ORM หรือ Framework ที่จัดการ SQL ให้อัตโนมัติ? |
| ☐ | Database User ที่ Application ใช้ มีสิทธิ์เฉพาะที่จำเป็น (Least Privilege)? |
| ☐ | มีการทำ Input Validation ก่อนส่งข้อมูลเข้าระบบ? |
| ☐ | Error Message ไม่แสดง SQL Error หรือโครงสร้าง Database ให้ผู้ใช้เห็น? |
| ☐ | มีการ Audit / Code Review เรื่อง SQL Injection เป็นประจำ? |
หากองค์กรของคุณกำลังมองหาระบบ ERP ที่ให้ความสำคัญกับความปลอดภัยตั้งแต่การออกแบบสถาปัตยกรรม สามารถนัดหมาย Demo หรือติดต่อทีมที่ปรึกษาเพื่อพูดคุยเพิ่มเติม
