Dreamhack xss-1 문제 풀이

    728x90

    1. 문제 설명

    XSS 취약점 이용, flag.txt와 FLAG 변수에 플래그 값이 있음을 확인한다.

     

    2. 문제 풀이

    from flask import Flask, request, render_template
    from selenium import webdriver
    from selenium.webdriver.chrome.service import Service
    import urllib
    import os
    
    app = Flask(__name__)
    app.secret_key = os.urandom(32)
    
    try:
        FLAG = open("./flag.txt", "r").read()
    except:
        FLAG = "[**FLAG**]"
    
    
    def read_url(url, cookie={"name": "name", "value": "value"}):
        cookie.update({"domain": "127.0.0.1"})
        try:
            service = Service(executable_path="/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("http://127.0.0.1:8000/")
            driver.add_cookie(cookie)
            driver.get(url)
        except Exception as e:
            driver.quit()
            # return str(e)
            return False
        driver.quit()
        return True
    
    
    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)
    
    
    @app.route("/")
    def index():
        return render_template("index.html")
    
    
    @app.route("/vuln")
    def vuln():
        param = request.args.get("param", "")
        return param
    
    
    @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>'
    
    
    memo_text = ""
    
    
    @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)
    
    
    app.run(host="0.0.0.0", port=8000)

    제공된 파일의 app.py은 위와 같다. flag 부분을 유심히 보면 GET을 받으면 flag.html을 렌더하여 리턴하지만, POST를 받으면 check_xss함수를 실행하면서 flag를 인자로 준다.

     

    check_xss는 read_url을 실행하는데, 이때 인자로 받은 flag를 전달한다.  즉 flag는 쿠키에 포함되어 있음을 확인한다.

    이제 사이트에 접속해보면 위와 같은 화면이 뜬다.

     

    가장 위에 링크를 클릭했을때, 위와 같은 화면이 나타난다. /vuln은 값을 다른 검증없이 그대로 출력함을 확인할 수 있다.

     

    다시 이전화면으로 돌아가 두번째 링크를 눌러본다. 위 코드에서 render_templete은 값을 화면에 표시하는 역할을 한다. <script>alert(1)</script>를 url에서 memo 뒤에 넣어보았을 때, 작동을 하진 않고 문자열로 출력되는 것을 확인할 수 있다.

    결국은 /vuln과 memo를 동시에 이용하여 /memo에 플래그 값을 띄우는게 목표이다.

     

    우리는 GET방식으로 넘겨주는 location.href를 사용하여, cookie에 포함된 flag값을 memo에 저장해줄것이다. "/memo?memo="을 통해 location.href가 /memo?memo= 로 이동하도록 하고, 그 값은 cookie를 불러오는 document.cookie를 보낼 수 있도록

    <script>location.href="/memo?memo="+document.cookie;</script>을 /flag 페이지로 이동하여 사용한다.

     

    사용한 후에 memo로 들어가보면 위와 같이 flag가 출력됨을 확인할 수 있다.

     

    3. 정리

    xss의 취약점을 이용하여 풀어보는 문제로, memo를 이용하는게 핵심이다.

    댓글