SQL Injection

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

ตัวอย่างของ SQL Injection

การโจมตี SQL Injection มีหลายรูปแบบ ขึ้นอยู่กับเป้าหมายและโครงสร้างของฐานข้อมูล เราจะมาดูตัวอย่างหลัก ๆ ที่พบบ่อยๆ

  1. การโจมตีแบบพื้นฐาน (Classic SQL Injection)
  2. การแทรกหลายคำสั่ง (Union-based SQL Injection)
  3. การปรับโครงสร้างคำสั่ง (Blind SQL Injection)

สร้างตารางตัวอย่าง

ก่อนที่เราจะเข้าไปดูตัวอย่างการโจมตี เรามาเริ่มด้วยการสร้างตารางตัวอย่างกันก่อนนะครับ

คำสั่ง SQL เพื่อสร้างตารางและแทรกข้อมูล
SQL
-- สร้างตารางผู้ใช้งาน
CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50),
    password VARCHAR(50)
);

-- แทรกข้อมูลตัวอย่าง
INSERT INTO users (username, password) VALUES ('admin', 'admin123');
INSERT INTO users (username, password) VALUES ('john', 'password1');
INSERT INTO users (username, password) VALUES ('jane', 'password2');

ข้อมูลในตาราง users

Classic SQL Injection (การโจมตีพื้นฐาน)

ผู้โจมตีอาจใช้การกรอกข้อมูลในฟอร์ม Login ที่ไม่ได้กรองข้อมูลอย่างถูกต้อง เช่น

SQL
-- คำสั่ง SQL ที่ระบบใช้ในการตรวจสอบการเข้าสู่ระบบ
SELECT * FROM users WHERE username = 'admin' AND password = 'password';

ถ้าผู้โจมตีกรอกข้อมูลดังนี้:

  • Username: admin
  • Password: ' OR '1' = '1

คำสั่ง SQL จะเปลี่ยนเป็น

SQL
SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1' = '1';

เนื่องจาก '1' = '1' เป็นจริงตลอดเวลา คำสั่งนี้จะคืนผลลัพธ์ที่ดึงข้อมูลของผู้ใช้ทั้งหมดออกมา ทำให้ผู้โจมตีสามารถล็อกอินได้สำเร็จโดยไม่รู้รหัสผ่านที่แท้จริง

Union-based SQL Injection (การแทรกหลายคำสั่ง)

การโจมตีแบบนี้ใช้คำสั่ง UNION เพื่อดึงข้อมูลจากตารางอื่นที่อาจไม่เกี่ยวข้องโดยตรง ตัวอย่างเช่น

SQL
-- คำสั่ง SQL ที่อาจใช้แสดงข้อมูลผู้ใช้
SELECT id, username FROM users WHERE username = 'john';

ถ้าผู้โจมตีกรอกข้อมูลดังนี้

  • Username: ' UNION SELECT null, database() --

คำสั่ง SQL จะเปลี่ยนเป็น

SQL
SELECT id, username FROM users WHERE username = 'john' UNION SELECT null, database();

ผลลัพธ์จะรวมข้อมูลจากตาราง users กับชื่อของฐานข้อมูลปัจจุบัน

ในกรณีนี้ ผู้โจมตีได้ข้อมูลชื่อฐานข้อมูลออกมาโดยใช้คำสั่ง UNION

Blind SQL Injection (การโจมตีแบบปรับโครงสร้างคำสั่ง)

การโจมตีแบบ Blind SQL Injection ใช้เมื่อผู้โจมตีไม่สามารถดูผลลัพธ์ของคำสั่ง SQL ได้โดยตรง แต่สามารถใช้คำสั่งเพื่อให้เกิดความแตกต่างในการตอบสนอง ตัวอย่างเช่น

SQL
-- ระบบอาจใช้คำสั่งนี้เพื่อตรวจสอบว่าผู้ใช้มีอยู่ในระบบหรือไม่
SELECT * FROM users WHERE username = 'admin' AND password = 'admin123';

ผู้โจมตีสามารถใช้เงื่อนไขที่ซับซ้อนเพื่อดูว่าเงื่อนไขเป็นจริงหรือไม่ เช่น:

  • Username: admin
  • Password: ' AND (SELECT LENGTH(database())) = 8 --

คำสั่ง SQL จะเปลี่ยนเป็น

SQL
SELECT * FROM users WHERE username = 'admin' AND password = '' AND (SELECT LENGTH(database())) = 8;

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

วิธีป้องกัน SQL Injection

1. การใช้ Prepared Statements (Parameterized Queries): โดยการใช้คำสั่ง SQL ที่ไม่รวมข้อมูลจากผู้ใช้เข้ากับโครงสร้างคำสั่ง SQL โดยตรง เช่น

SQL
cursor.execute("SELECT * FROM users WHERE username = ? AND password = ?", (username, password))

2. การกรองข้อมูล (Input Validation): ตรวจสอบข้อมูลที่ผู้ใช้กรอกให้ถูกต้อง เช่น การปฏิเสธอักขระพิเศษที่ไม่ควรอยู่ในข้อมูล

3. การใช้ ORM (Object Relational Mapping): ใช้เครื่องมือ ORM เช่น SQLAlchemy หรือ Django ORM เพื่อจัดการคำสั่ง SQL ให้ปลอดภัยจาก SQL Injection

แชร์เรื่องนี้