
#!/usr/bin/env python3
import os
import string
from flask import Flask, request, abort, render_template, session
# 비밀 파일을 저장할 경로와 허용할 문자 집합을 정의합니다.
SECRETS_PATH = 'secrets/'
ALLOWED_CHARACTERS = string.ascii_letters + string.digits + '/'
#알파벳 대문자 소문자 숫자 슬래시만 허용 된다.
# Flask 애플리케이션을 초기화합니다.
app = Flask(__name__)
# 세션 암호화에 사용할 비밀 키를 무작위로 생성합니다.
app.secret_key = os.urandom(32)
# 샘플 파일을 생성하여 기본 메시지를 씁니다.
with open(f'{SECRETS_PATH}/sample', 'w') as f:
f.write('Hello, world :)')
# 플래그 파일을 생성하기 위한 디렉토리를 만듭니다.
flag_dir = SECRETS_PATH + os.urandom(32).hex()
os.mkdir(flag_dir) # 임의의 이름으로 디렉토리 생성
flag_path = flag_dir + '/flag'
#a990c3f13f7d8f6a541b4910814e901d027c460be6de7958d9d3cfb28c5f4984
#secrets/os.urandom(32).hex/flag
# '/flag' 경로에서 플래그 내용을 읽어 새 플래그 파일에 씁니다.
with open('/flag', 'r') as f0, open(flag_path, 'w') as f1:
f1.write(f0.read())
@app.route('/', methods=['GET'])
def get_index():
# 비밀 파일 경로를 세션 데이터에 안전하게 저장합니다.
session['secret'] = flag_path
# 파일 읽기 기능을 제공합니다.
path = request.args.get('path') # 쿼리 파라미터에서 'path' 값을 가져옵니다.
# 경로가 유효한지 검사합니다.
if not isinstance(path, str) or path == '':
return render_template('index.html', msg='input the path!') # 경로가 없을 경우 오류 메시지 반환
# 허용된 문자 집합에 포함되지 않은 문자가 있는지 검사합니다.
if any(ch not in ALLOWED_CHARACTERS for ch in path):
return render_template('index.html', msg='invalid path!') # 잘못된 문자 포함 시 오류 메시지 반환
# 전체 경로를 만듭니다.
full_path = f'./{SECRETS_PATH}{path}'
# 파일이 실제로 존재하는지 확인합니다.
if not os.path.isfile(full_path):
return render_template('index.html', msg='invalid path!') # 파일이 없을 경우 오류 메시지 반환
try:
# 파일을 열고 내용을 읽어 반환합니다.
with open(full_path, 'r') as f:
return render_template('index.html', msg=f.read())
except:
# 예외가 발생하면 500 오류를 발생시킵니다.
abort(500)
flag_path를 알아내야 하는 문제이다.
플래그 경로는 32자리 랜덤 hex 값이다.
flag_dir = SECRETS_PATH + os.urandom(32).hex()
브루트 포스는 불가능 해보인다.
경로는 자동적으로 secrets/부터 시작되게 만든다.
SECRETS_PATH = 'secrets/'
sample을 써서 실험해 보자.
with open(f'{SECRETS_PATH}/sample', 'w') as f:
f.write('Hello, world :)')

Hello, world :)가 잘 출력되는 거 같다.
Burp를 이용해서 session 비밀키가 어떤 형태로 가는지 확인해 보자.

Cookie: session= 형태로 Request 되어있다.
import os
import string
from flask import Flask, request, abort, render_template, session
# 비밀 파일을 저장할 경로와 허용할 문자 집합을 정의합니다.
SECRETS_PATH = 'secrets/'
ALLOWED_CHARACTERS = string.ascii_letters + string.digits + '/'
#알파벳 대문자 소문자 숫자 슬래시만 허용 된다.
# Flask 애플리케이션을 초기화합니다.
app = Flask(__name__)
# 세션 암호화에 사용할 비밀 키를 무작위로 생성합니다.
app.secret_key = os.urandom(32)
코드 처음을 보면 Flask의 secret_key를 사용하여 세션 쿠키를 암호화한 것을 확인할 수 있다.
그렇다면 Flask_unsign 모듈을 이용해서 복호화시켜보자.
python 에는 표준 라이브러리에는 포함되어있지 않으니 Kali를 이용해서 설치를 해보도록 하자
pip install flask-unsign
설치를 완료한다면
사용자 전용 실행 파일 경로로 이동하여 실행해 보자.
cd ~/.local/bin
flask-unsign 실행해서 복호화해서 submit 시키면...

답이 나온다.
'CTF' 카테고리의 다른 글
| Dreamhack - Curling (0) | 2025.03.20 |
|---|---|
| chockshop (0) | 2024.12.10 |
| (CTF 출제) simple-web-request (1) | 2024.10.09 |
| (CTF 출제) Tomcat Manager (1) | 2024.09.05 |
| (CTF 출제) amocafe (2) | 2024.09.05 |