문제 설명

해당 문제는 중학교 3학년 때 드림핵 X-MAS CTF 2023에 출제한 웹 해킹 문제입니다.

현재는 드림핵 워게임 플랫폼에 포팅이 되어있으며, 레벨 5 난이도로 평가를 받고 있습니다.

이 출제자 writeup 페이지 또한 문제 출제 당시 쓴 풀이를 가져왔기 때문에 조금 어색할 수 있습니다. 양해 바랍니다.

한줄 풀이 :

SSTI(RCE 안됨) -> JWT Secret leak, 어드민으로 생성하여 curl 을 사용하는 api/metar에 SSRF, flag 파일명은 영어 소문자 4자리로 api/metar 에 10번 접속 시 5분간 타임아웃이 된다. 따라서 일일이 요청을 보내면 구하기 어렵다. curl url grobbing 을 이용해서 api/metar?airport=file:///deploy/flag_[a-z][a-z][a-z][a-z].txt

메인 페이지

메인 페이지에 접속 시, 왼쪽 상단 METAR 와 NOTAM 버튼이 있습니다. 하지만, 동작하지 않습니다. 오른쪽 상단 Dashboard 와 Login 은 정상적으로 동작합니다.

01.png

대시보드 페이지 (로그인 X)

로그인을 하지 않은 상태(auth 쿠키가 없는 상태)에서 대시보드 버튼을 클릭하면, 로그인이 되어 있지 않다고 하고 되돌려 보냅니다.

main.py 65:77

@app.route('/dashboard', methods=['GET', 'POST'])
def admin():
    if request.cookies.get('auth'): // 이 코드로 인해 걸러집니다.
        try:
            decode_jwt = jwt.decode(request.cookies.get('auth'), JWTKey, algorithms=['HS256'])
            if decode_jwt['id'] == 'admin' and decode_jwt['isAdmin'] == True:
                return render_template('admin.html')
            else:
                return render_template_string('You are not admin.')
        except:
            return send_file("./cat/fail.jpg", mimetype='image/jpg') # BAD JWT    else:
        return render_template_string('<script>alert("You are not logged in.");history.back()</script>')

02.png

로그인 페이지

main.py 20:23에 근거하면 우리는 id 가 ‘admin’ 인 계정의 비밀번호를 모릅니다.

users = [
    {"id": "admin", "pw": "{{REDACTED}}"},
    {"id": "guest", "pw": "guest"},
]

로그인 페이지의 백엔드 코드를 보면, 복잡하면서도 간단한 로직을 갖고 있습니다.