สำหรับคนที่ SQL statement แบบนี้:
sql = "SELECT * FROM users WHERE id = " + id
"SELECT * FROM users WHERE id = 1 AND 1 = 1"
เราสังเกตุได้ว่าระบบจะทำงานตามปกติ
ซึ่งทำให้เรารู้ได้ว่า parameter นี้สามารถทำ SQL injection ได้
Time-based blind --- เช่น ส่ง orderBy="name DESC; SLEEP(5)"
สำหรับคนที่มี SQL statement แบบนี้:
sql = "SELECT * FROM users ORDER BY" + orderBy
"SELECT * FROM users ORDER BY name DESC; SLEEP(5)"
ถ้า response ของคุณช้ากว่า 5 วินาที
เราก็จะเดาได้ว่า parameter นี้สามารถทำ SQL injection ได้
Error-based --- เช่น ส่ง id="'name'"
Error message นี้ค่อนข้างสำคัญ เพราะมันบอกอะไรเราได้หลาย ๆ อย่าง เช่น
แค่นี้เราก็รู้แล้วว่า field id คือ integer
ใน Postgresql เราสามารถส่ง query เช่น id="(SELECT password FROM users WHERE username='tanin')::int" ซึ่งเราจะได้ query ดังนี้
select * FROM users WHERE id = (select hashed_password from users limit 1)::int; ERROR: invalid input syntax for integer: "sdweWFGwewef1123"
Hashed password หลุดผ่าน error message ไปซะงั้น... พวก error message ยังใช้ทดสอบชื่อ table ได้อีกด้วย มันอันตรายมากเลยทีเดียว
บทเรียนอันนี้ คือ อย่า propagate error ไปใน response นะครับ...
UNION query-based -- เช่น ส่ง id="1 union select * from users" --- และเราก็จะได้ records อื่น ๆ มาด้วย ถ้าโชคดี
Stacked queries --- คือการส่ง query อื่น เช่น ส่ง id="1; DELETE FROM users;" เพื่อลบ users ทั้งหมด
ขอแนะนำ Sqlmap นี้ทดสอบยิง SQL injection หลาย ๆ combination ให้ เพื่อทดสอบว่าระบบคุณปลอดภัยจริงหรือไม่ ยังไงก็ลองใช้กันดูนะครับ
วิธีป้องกันพื้นฐานก็น่าจะ:
บทเรียนอันนี้ คือ อย่า propagate error ไปใน response นะครับ...
UNION query-based -- เช่น ส่ง id="1 union select * from users" --- และเราก็จะได้ records อื่น ๆ มาด้วย ถ้าโชคดี
Stacked queries --- คือการส่ง query อื่น เช่น ส่ง id="1; DELETE FROM users;" เพื่อลบ users ทั้งหมด
ขอแนะนำ Sqlmap นี้ทดสอบยิง SQL injection หลาย ๆ combination ให้ เพื่อทดสอบว่าระบบคุณปลอดภัยจริงหรือไม่ ยังไงก็ลองใช้กันดูนะครับ
วิธีป้องกันพื้นฐานก็น่าจะ:
- อย่า output error ของจริงไปกับ HTTP response
- อย่าประกอบ SQL statement ด้วยตัวเอง --- ใช้ ORM (ถ้า ORM มี bug ก็ซวยไป...)