본문 바로가기

Wargame/Dreamhack

[Dreamhack] file-download-1

file-download-1 | 워게임 | Dreamhack

 

file-download-1

File Download 취약점이 존재하는 웹 서비스입니다. flag.py를 다운로드 받으면 플래그를 획득할 수 있습니다. Reference Introduction of Webhacking

dreamhack.io

 

우선 파일을 다운받고 압축을 풀어준다.

 

압축을 풀고 나온 파일의 압축을 또 풀어준다.

드디어 나온 파일과 폴더들을 열어보겠다.

static

 

templates

 

requirements

 

뭔가 있을까 싶어 열어보았지만 전부 쓸데없는 애들이었다.

 

위에 있던 링크를 클릭해보았다.

 

Upload My Memo 를 클릭하니 아래와 같은 창으로 이동한다.

일단 예시문에 나와있는대로 Filename과 Content를 입력하고 Upload 버튼을 눌렀더니,

Memo를 입력했다는 메시지 아래에 입력한 Filename대로 페이지가 생기고, 마찬가지로 입력했던 Content가 아래에 보인다.

페이지 경로는 /read?name=my-first-memo 이다.

read 페이지에서 name 파라미터로 전달된 이름의 파일을 읽는 것으로 추측된다.

 

메모에 뭔가를 업로드해서 flag.py를 다운로드 받으면 된다는걸 알 수 있다.

그럼 flag.py는 어떻게 받는걸까?

 

아까 열어보지 않은 파일이 하나 남아있다는걸 기억하는가?

파이썬 소스코드 파일 말이다.

 

app.py

#!/usr/bin/env python3
import os
import shutil

from flask import Flask, request, render_template, redirect

from flag import FLAG

APP = Flask(__name__)

UPLOAD_DIR = 'uploads'


@APP.route('/')
def index():
    files = os.listdir(UPLOAD_DIR)
    return render_template('index.html', files=files)


@APP.route('/upload', methods=['GET', 'POST'])
def upload_memo():
    if request.method == 'POST':
        filename = request.form.get('filename')
        content = request.form.get('content').encode('utf-8')

        if filename.find('..') != -1:
            return render_template('upload_result.html', data='bad characters,,')

        with open(f'{UPLOAD_DIR}/{filename}', 'wb') as f:
            f.write(content)

        return redirect('/')

    return render_template('upload.html')


@APP.route('/read')
def read_memo():
    error = False
    data = b''

    filename = request.args.get('name', '')

    try:
        with open(f'{UPLOAD_DIR}/{filename}', 'rb') as f:
            data = f.read()
    except (IsADirectoryError, FileNotFoundError):
        error = True


    return render_template('read.html',
                           filename=filename,
                           content=data.decode('utf-8'),
                           error=error)


if __name__ == '__main__':
    if os.path.exists(UPLOAD_DIR):
        shutil.rmtree(UPLOAD_DIR)

    os.mkdir(UPLOAD_DIR)

    APP.run(host='0.0.0.0', port=8000)

 

upload_memo() 함수에 정의된 내용을 살펴보자.

사용자가 메모를 작성하면 제목은 filename으로, 내용은 content로 저장된다.

여기서 POST 요청으로 전달한 filename 파라미터 값에 상위 디렉토리 이동 명령어 ".."를 탐지한다.

".." 문자열이 탐지되지 않으면, filename 파라미터 명으로 파일을 생성하고, content를 내용으로 작성한다.

생성된 파일의 경로는 /uploads/{filename} 이다.

 

사실 flag.py가 어디있는지 모르지만 ".." 문자열을 탐지하는 것으로 보아 웹 디렉토리 최상위 경로에 있는 것 같다.

 

read_memo() 함수에 정의된 내용을 보면 upload_memo() 와 다르게 ".." 문자열에 대한 탐지가 존재하지 않는다.

 

그럼 /read?name=../flag.py로 접근하면 flag.py 파일을 읽어오려나.

 

 

FLAG = 'DH{uploading_webshell_in_python_program_is_my_dream}'

'Wargame > Dreamhack' 카테고리의 다른 글

[Dreamhack] XSS-1  (0) 2023.09.14
[Dreamhack] FFFFAAAATTT  (0) 2023.04.02
[Dreamhack] sql injection bypass WAF  (0) 2022.11.12
[Dreamhack] blind sql injection advanced  (0) 2022.11.12
[Dreamhack] CSRF-2  (0) 2022.09.25