[WARGAME] DreamHack 웹해킹1 로드맵 / wargame - xss1

jckim22·2022년 10월 12일
0

웹페이지 분석

인덱스 화면이다.
3가지 페이지가 준비되어 있다.

첫번째 페이지인 /vuln 이다.

GET 메소드로 받을 수 있는 param에 스크립트 구문이 삽입 되어 있고 그 구문이 동작하는 것을 볼 수 있다.
이 말은 즉슨 url에 스크립트를 삽입하는 DOM-based XSS 공격을 사용할 수 있다는 것이다.

alert의 값을 변경해도 잘 작동한다

두번째 /memo이다.

이 곳에서는 memo에 대입하는 값을 html 텍스트로 보여준다.
하지만 스크립트 태그는 무시된다.
그 이유는 코드를 분석하면서 알아보자.

마지막으로 /flag 이다.

이 곳에서는 셀러니움으로 가상 접속을 할 url을 입력한다.
아까 봤던 vuln사이트에서는 DOM-based XSS 공격이 가능했기 때문에 그 곳을 이용하게 된다.
나는 가상의 랜덤 포트에서 접속한 것이기 때문에 셀러니움은 그 호스트로 가기 위해 설정한 로컬호스트:8000포트로 vuln을 찾아간다.
또한 이따가 코드 분석을 하면 알겠지만 그곳에서는 flag를 쿠키 설정한다.
그래서 그 곳에 쿠키를 메모하는 코드를 작성하게 되면 /memo페이지에는 flag가 출력될 것이다.

성공적으로 스크립트가 주입되었다.

그리고 아까 memo로 가게 되면 flag가 노출 되어 있는 것을 볼 수 있다.

코드 분석

def read_url(url, cookie={"name": "name", "value": "value"}):
    cookie.update({"domain": "127.0.0.1"})
    try:
        options = webdriver.ChromeOptions()
        for _ in [
            "headless",
            "window-size=1920x1080",
            "disable-gpu",
            "no-sandbox",
            "disable-dev-shm-usage",
        ]:
            options.add_argument(_)
        driver = webdriver.Chrome("/chromedriver", 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)

먼저 메인페이지 /에 라우팅된 코드부터 살펴보자
그저 index.html을 보여줄 뿐이다.

아까 살펴봤던 memo 코드를 보면 rendet_template로 감싸져 있다.
그래서 스크립트 태그가 실행이 되지 않았던 것이다.

그럼 가장 중요한 /flag를 보자
flag값과 url 값을 read_url()로 보낸다.
그 곳에서는 셀리니움을 이용해 가상의 웹 접속을 하고 그 곳에 쿠키를 설정한뒤 설정한 url로 이동한다.

우리는 url에 vuln 페이지를 이용해 스크립트 태그를 사용하고 그 내용은 memo페이지에 memo에 현재 쿠키를 GET하라는 내용이다.
따라서 현재 쿠키는 flag가 될 것이고 그 쿠키는 memo 화면에 출력된다.

profile
개발/보안

0개의 댓글