Skip to main content
0

สรุปสั้น ๆ ก่อนเริ่มอ่าน

SQL Injection เป็นช่องโหว่ที่เป็นตำนาน แต่ยังคงมีความอันตราย เพราะยังมีการถูกโจมตีด้วยช่องโหว่นี้อยู่ โดยการป้องกันสามารถทำโดยการเปลี่ยนวิธีการเขียน SQL จากใช้การต่อ String ไปเป็นการเขียนแบบ Prepared Statements แต่ทั้งนี้การตั้ง User และ Password ที่ปลอดภัยให้ Database ก็มีความสำคัญเช่นกัน โดยในบทความจะสอนใช้ Libary mysql2 ใน Node.JS

SQL คืออะไร

SQL หรือชื่อเต็ม ๆ คือ Structured Query Language เป็นภาษาที่ใช้ในการจัดการข้อมูล (ปรับปรุง แก้ไข ลบ ค้นหา) ของ ฐานข้อมูลแบบเชิงสัมพันธ์ (Relational Database) ที่เก็บข้อมูลในรูปแบบ แถว และ คอลัมน์ (ไม่ใช่ชื่อของฐานข้อมูล) ซึ่งจะใช้ร่วมกับ Database Management System หรือย่อสั้น ๆ ว่า DBMS (ระบบจัดการฐานข้อมูล) เช่น MySQL, PostgreSQL, Oracle, MS Server SQL, SQLite เป็นต้น ซึ่งใครอยากเรียนรู้ SQL เพิ่มเติมสามารถเรียนได้ที่คอร์ส Essential SQL for Everyone ของทาง borntodev ได้เลยครับเรียนฟรี เรียนจบทำแบบทดสอบผ่านได้เกียรติบัตรด้วยครับ

มาทำความรู้จักกับ SQL Injection กันก่อน

SQL Injection เป็นช่องโหว่ด้านความปลอดภัยของฐานข้อมูลโดย Hacker สามารถดูและจัดการข้อมูลต่าง ๆ ในฐานข้อมูลได้ แม้เป็นข้อมูลที่มีการกำหนดสิทธิ์เข้าถึง เช่น ข้อมูลส่วนบุคคลของผู้ใช้ ภายในฐานข้อมูล โดยถูกจัดให้อยู่ในหมวด Injection ใน Open Web Application Security Project (OWASP) Top 10 ของปี 2021 ถึงแม้จะเป็นตำนาน แต่ก็ยังมีการโดนโจมตีจากช่องโหว่นี้อยู่ ซึ่งเกิดจากรูปแบบของการเขียน SQL ในการจัดการข้อมูล ที่ไม่ระวังทำให้เกิดช่องโหว่ขึ้นมา

รูปแบบการเขียน SQL ที่ไม่ปลอดภัย

ตัวอย่างที่การเขียน SQL ที่เสี่ยงต่อการโดน SQL Injection ซึ่งใช้วิธีในการต่อ String เพื่อทำการ Select ข้อมูลจาก table accounts โดย Hacker สามารถนำคำสั่ง SQL ที่จะใช้ในการ มาต่อท้ายได้

SELECT * FROM users WHERE custID='" + request.getParameter("id") + "'";

โดยการโจมตีจะเป็นลักษณะแบบนี้ คือการเพิ่มคำสั่ง SQL ต่อท้ายเข้าไป โดยในการโจมตีนี้จะเป็นการลบ table ที่เก็บข้อมูลผู้ใช้งานโดยการ drop ทิ้ง

 http://example.com/app/accountView?id='1; DROP TABLE users;--'

มาถึงการป้องกัน SQL Injection

โดยในบทความนี้จะแนะนำให้รู้จักกับวิธีการเขียนภาษา SQL แบบกำหนดพารามิเตอร์ (Prepared Statements) แทนการเขียนแบบต่อ String ที่เสี่ยงโดน SQL Injection โดยจะใช้เครื่องหมายคำถาม ? แทนการต่อ String

SELECT * FROM users WHERE custID= ?;

แต่ แน่นอน ว่าเครื่องหมายคำถาม ? ไม่ได้มาแทน request.getParameter(“id”) ได้ทันทีโดยจะต้องใช้ Libary สำหรับเรียกใช้ SQL ในแต่ละภาษามาช่วย ซึ่งในบทความนี้ขอยกตัวอย่างบน Node.JS ครับ

การเขียน SQL ในรูปแบบ Prepared Statements บน Node.JS

โดยใน Node.JS จะมี Libary ชื่อ mysql2 ซึ่งให้เขียน SQL ในรูปแบบกำหนดพารามิเตอร์ (Prepared Statements)

ทำการติดตั้ง Libary mysql2 โดยใช้คำสั่ง บน cmd ดังนี้

npm i mysql2

โดยตัว mysql2 สามารถใช้ได้ทั้งแบบ Promise และ Callback โดยจะขอยกตัวอย่างแบบ Promise ครับ

import mysql from 'mysql2/promise';

try {
  // create the connection to database
  const connection = await mysql.createConnection({
    host: 'localhost',
    user: 'root',
    password: 'root',
    database: 'test',
  });

  // ส่งคำสั่ง sql ไปที่ server database 
  const [results, fields] = await connection.execute(
    'SELECT * FROM users WHERE custID= ?',
    [request.getParameter("id")]
  );

  console.log(results); // คืนค่าผลลัมพ์ออกมา
  console.log(fields); // ข้อมูลอื่น ๆ ที่ได้หากมีผลลัมพ์
} catch (err) {
  console.log(err);
}

ซึ่งหากสังเกตุจากตรง Execute จะมี ? จำนวน 1 อันและภายใน List ที่มี request.getParameter(“id”) อยู่ข้างในจะมี 1 อันก็คือจำนวนของ ? จะเท่ากับจำนวนข้อมูลใน List ครับ และข้อมูลแต่ละอันจะไปแทน ? ตามลำดับ เช่น

// ส่งคำสั่ง sql ไปที่ server database 
const [results, fields] = await connection.execute(
    'SELECT * FROM users WHERE custID= ? AND username= ?',
    [1,'korarit']
);

โดยเครื่องหมาย ? อันแรกจะถูกแทนที่ด้วย 1 และ เครื่องหมาย ? อันที่สองจะถูกแทนด้วย korarit ครับ ซึ่งในการเขียนภาษา SQL แบบ Prepared Statements จะเป็นลักษณะนี้ครับ ซึ่งใน Libary สำหรับใช้งาน SQL ในหลาย ๆ ภาษาก็เป็นลักษณะเดียวกันครับ

การตั้ง User และ Password ให้ Database สำคัญเช่นกัน

หากเราทำการป้องกัน SQL Injection โดยใช้ วิธีการเขียน SQL แบบ Prepared Statements ไปแล้วก็ตามแต่หากตัว Database ของเราไม่มีการตั้ง User และ Password ที่ปลอดภัยเพียงพอก็จะทำให้ การเขียน SQL แบบ Prepared Statements ไร้ประโยชน์เหมือนกัน เพราะ Hacker ก็สามารถทำการ scan หา port ที่ใช้เชื่อมต่อกับ Database ของเราได้และสามารถลองใช้ User และ Password ยอดนิยมก่อนได้ ซึ่งเป็นเหมือนการเปิดประตูให้ Hacker สามารถ Query ตัว Database ของเราได้ไม่ต่างกับเจ้าของครับ

สรุป

SQL Injection เป็นช่องโหว่ที่เป็นตำนาน แต่ยังคงมีความอันตราย เพราะยังมีการถูกโจมตีด้วยช่องโหว่นี้อยู่ โดยการป้องกันสามารถทำโดยการเปลี่ยนวิธีการเขียน SQL จากใช้การต่อ String ไปเป็นการเขียนแบบ Prepared Statements แต่ทั้งนี้การตั้ง User และ Password ที่ปลอดภัยให้ Database ก็มีความสำคัญเช่นกัน

อ้างอิง

กรฤต แสงทอง

Author กรฤต แสงทอง

More posts by กรฤต แสงทอง

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

ตั้งค่าความเป็นส่วนตัว

คุณสามารถเลือกการตั้งค่าคุกกี้โดยเปิด/ปิด คุกกี้ในแต่ละประเภทได้ตามความต้องการ ยกเว้น คุกกี้ที่จำเป็น

ยอมรับทั้งหมด
จัดการความเป็นส่วนตัว
  • คุกกี้ที่จำเป็น
    เปิดใช้งานตลอด

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

  • คุกกี้สำหรับการติดตามทางการตลาด

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

บันทึกการตั้งค่า