이름과 문제 설명을 보니 대충 웹서버 홈 디렉토리에 있는 파일들을 찾아보며 플래그를 출력하는 문제 같다.
#!/usr/bin/python3
from flask import Flask, request, render_template, abort
from functools import wraps
import requests
import os, json
users = {
'0': {
'userid': 'guest',
'level': 1,
'password': 'guest'
},
'1': {
'userid': 'admin',
'level': 9999,
'password': 'admin'
}
}
def internal_api(func):
@wraps(func)
def decorated_view(*args, **kwargs):
if request.remote_addr == '127.0.0.1':
return func(*args, **kwargs)
else:
abort(401)
return decorated_view
app = Flask(__name__)
app.secret_key = os.urandom(32)
API_HOST = 'http://127.0.0.1:8000'
try:
FLAG = open('./flag.txt', 'r').read() # Flag is here!!
except:
FLAG = '[**FLAG**]'
@app.route('/')
def index():
return render_template('index.html')
@app.route('/get_info', methods=['GET', 'POST'])
def get_info():
if request.method == 'GET':
return render_template('get_info.html')
elif request.method == 'POST':
userid = request.form.get('userid', '')
info = requests.get(f'{API_HOST}/api/user/{userid}').text
return render_template('get_info.html', info=info)
@app.route('/api')
@internal_api
def api():
return '/user/<uid>, /flag'
@app.route('/api/user/<uid>')
@internal_api
def get_flag(uid):
try:
info = users[uid]
except:
info = {}
return json.dumps(info)
@app.route('/api/flag')
@internal_api
def flag():
return FLAG
application = app # app.run(host='0.0.0.0', port=8000)
# Dockerfile
# ENTRYPOINT ["uwsgi", "--socket", "0.0.0.0:8000", "--protocol=http", "--threads", "4", "--wsgi-file", "app.py"]
코드를 보면 기능을 담당하는 함수마다 `@app.route(경로)`이런 형식으로 경로를 보여주는 것을 보아하니 처음에 내가 생각한 풀이 방식은 맞는 모양이다.
그렇다면 저 경로를 어디에 입력해야할지 찾아봐야할 것 같다.
“Get User Info” 라는 버튼이 있으니 눌러보았다.
userid에 값을 입력하면 값에 대응되는 유저 정보를 보여주는 창인가 보다.
위 창의 url인데 url의 맨 뒤를 보면 “Get User Info” 버튼을 눌러보니 url에는 /get_info 라는 값이 붙어있는 것이 보인다.
@app.route('/get_info', methods=['GET', 'POST'])
def get_info():
if request.method == 'GET':
return render_template('get_info.html')
elif request.method == 'POST':
userid = request.form.get('userid', '')
info = requests.get(f'{API_HOST}/api/user/{userid}').text
return render_template('get_info.html', info=info)
위 코드는 ‘/get_info’ 경로로 들어가게 되면 어떤 기능을 할지 알 수 있는데
@app.route('/api/flag')
@internal_api
def flag():
return FLAG
FLAG를 리턴해주는 코드도 ‘/get_info’와 같이 `@app.route(경로)`이런 형식이기 때문에 url에 플래그 경로를 입력하면 풀리지 않을까 해서 입력해보았다.
오우 안되넹.. ㅋ
역시 이렇게 쉽게는 못푸는 모양이다
그럼 다음으로 입력할만한 곳은 userid를 입력하는 그곳에 입력하면 될 것 같다.
이것도 안되는 것 같다.
왜지? 그럼 어떻게 해야하지?
한 번 버프 스위트로 요청 내용을 한 번 뜯어보자
허허 뭐가 없다 그럼 뭐가 잘못됐느냐?
입력한 경로가 잘못되었을 것이다.
그럼 다른 경로를 찾아보자
@app.route('/get_info', methods=['GET', 'POST'])
def get_info():
if request.method == 'GET':
return render_template('get_info.html')
elif request.method == 'POST':
userid = request.form.get('userid', '')
info = requests.get(f'{API_HOST}/api/user/{userid}').text
return render_template('get_info.html', info=info)
오 get_info를 구성하는 코드에서 힌트를 얻을 수 있다.
userid를 입력했을때 어디에서 정보를 가져오느냐? `/api/user/{userid}` 바로 이 경로에서 가져오고있다.
그렇다면 FLAG를 출력하는 파일은? `/api/flag`이 경로에 있다.
그렇다면 상위 디렉토리에 갔다가(api), flag를 실행시키면 플래그가 출력될 것 같다.
holy,, ‘userid=undefined’ 라는 것이 새로 생긴 것 같다. 그렇다면 경로는 이게 맞는 것 같은데… 어떻게 더 해볼 수 있나..
@app.route('/api/user/<uid>')
@internal_api
def get_flag(uid):
try:
info = users[uid]
except:
info = {}
return json.dumps(info)
오홍 userid가 이런식으로 경로에 들어가서 실행이 되며, 유저정보가 출력이 되는거구나
그렇다면 userid의 값에 ../flag를 넣으면 실행이 잘 될 것 같은데?
라는 결론을 얻을 수 있다.
그렇다면 위의 버프 스위트 리퀘스트에 ‘userid = undefined’에 undefined를 지우고 ../flag를 넣으면 플래그가 나올 것 같다
해결 ㅋ
'DreamHack > Web hacking' 카테고리의 다른 글
[LEVEL-1] simple-ssti (1) | 2023.12.06 |
---|---|
[LEVEL-1] Apache htaccess (1) | 2023.12.06 |
[LEVEL-1] simple_sqli_chatgpt (1) | 2023.11.27 |
[LEVEL-1] session-basic (0) | 2023.11.20 |
[LEVEL-1] Type c-j (0) | 2023.11.15 |