วันพฤหัสบดีที่ 25 กุมภาพันธ์ พ.ศ. 2559

Type Of SQL Injection (Part 2 Unvalidated Input (Injection))

Boolean-based blind -- เช่น ส่ง id="1 AND 1=1"
สำหรับคนที่ 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 นี้ค่อนข้างสำคัญ เพราะมันบอกอะไรเราได้หลาย ๆ อย่าง เช่น



select * FROM users WHERE id = 'name'; ERROR: invalid input syntax for integer: "name"



แค่นี้เราก็รู้แล้วว่า 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 ให้ เพื่อทดสอบว่าระบบคุณปลอดภัยจริงหรือไม่ ยังไงก็ลองใช้กันดูนะครับ

วิธีป้องกันพื้นฐานก็น่าจะ:
  1. อย่า output error ของจริงไปกับ HTTP response
  2. อย่าประกอบ SQL statement ด้วยตัวเอง --- ใช้ ORM (ถ้า ORM มี bug ก็ซวยไป...)