-
[webhacking] XSS-1 / XSS-2 문제 풀이해킹/wargame 2023. 3. 5. 16:04
XSS (Cross Side Scripting)에 관한 문제 2개를 가져왔습니다.
관련 개념 설명은 아래 포스팅을 참고해 주시기 바랍니다.
https://white-hack.tistory.com/entry/webhacking-1-XSS-Cross-Site-Scripting-feat-SOP
[webhacking] 1. XSS ( Cross Site Scripting ) / feat. SOP
XSS 이란? 클라이언트 사이드 취약점 중 하나로, 공격자가 웹 리소스에 오리진 권한으로 악성 스크립트를 삽입하여 이용자가 그 사이트를 방문했을 때, 해당 악성 스크립트가 실행되어 세션 정보
white-hack.tistory.com
문제 1. XSS - 1
https://dreamhack.io/wargame/challenges/28/
xss-1
여러 기능과 입력받은 URL을 확인하는 봇이 구현된 서비스입니다. XSS 취약점을 이용해 플래그를 획득하세요. 플래그는 flag.txt, FLAG 변수에 있습니다. 플래그 형식은 DH{...} 입니다. Reference Client-side
dreamhack.io
코드 분석
#!/usr/bin/python3 from flask import Flask, request, render_template from selenium import webdriver 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: 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)
엔드포인트는 총 3가지로, 각각 함수에 대해 살펴보겠습니다.
- /vuln : "param" 이라는 파라미터를 전달받고 그 값을 출력합니다.
- /flag : GET요청에는 flag.html을 보여주고, POST요청에는 param을 전달받은 후 쿠키를 포함하여 check_xss함수를 호출합니다.
check_xss함수는 read_url함수를 통해 /vuln 엔드포인트에 접속합니다. - /memo : "memo" 이라는 파라미터를 전달받고, 전역변수 memo_text에 저장한 후,
render_template함수를 통해 memo.html에 값을 저장하고 출력합니다.
/vuln 과 /memo 엔드포인트는 사용자의 입력을 출력하는데, /memo 엔드포인트가 render_template함수를 통해 HTML 엔티티 코드로 저장하기 때문에 XSS가 발생하지 않지만, /vuln 엔드포인트는 입력받은 값을 그대로 출력하기 때문에 XSS에 취약합니다.
Exploit
/flag 엔드포인트에서 text 상자에 XSS를 시도해 봅시다.
<script>location.href = "/memo?memo=" + document.cookie </script>
다음과 같이 자바스크립트 코드를 넣어주게 되면, /memo 엔드포인트로 접속하고, memo 파라미터에 쿠키 값을 넣어주게 됩니다.
이제 /memo 엔드포인트로 이동하게 되면 저장된 쿠키를 확인할 수 있습니다.
취약점 보완법
이용자의 입력값을 별다른 검증 없이 그대로 출력했기 때문에 XSS가 발생했습니다.
악성태그를 필터링하는 HTML Sanitization을 이용하거나, render_template함수를 사용해 엔티티코드로 치환하는 것으로 보완할 수 있습니다.
문제 2. XSS - 2
https://dreamhack.io/wargame/challenges/268/
xss-2
여러 기능과 입력받은 URL을 확인하는 봇이 구현된 서비스입니다. XSS 취약점을 이용해 플래그를 획득하세요. 플래그는 flag.txt, FLAG 변수에 있습니다. 플래그 형식은 DH{...} 입니다. Reference ClientSide:
dreamhack.io
코드 분석
#!/usr/bin/python3 from flask import Flask, request, render_template from selenium import webdriver 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: 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(): return render_template("vuln.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>' 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)
문제 1과 비슷하지만, 차이점은 vuln() 함수가 위와는 다르게 render_template을 사용하여 엔티티코드로 치환하고 있습니다.
따라서 위 문제와 똑같이 풀 수 없으므로, 이를 우회하는 기법을 사용해야 합니다.
우선 /vuln 엔드포인트로 가서 XSS를 사용해봅시다.
/vuln?param=<script>alert(1)</script>
다음과 같이 param으로 script 태그를 전달하면 아무 반응이 없습니다.
아마도 script 태그를 필터링하고 있는 것 같습니다.
/vuln?param=<img src="https://www.google.co.kr/images/branding/googlelogo/2x/googlelogo_color_160x56dp.png">
위 src의 링크는 구글 사진입니다. img 태그를 사용하면 정상적으로 사진이 추가된 것을 확인할 수 있습니다.
따라서 script태그가 아닌 img 태그를 이용해서 XSS를 사용해 볼 수 있습니다.
Exploit
다시 /flag 엔드포인트로 돌아와서 XSS를 사용해봅시다.
<img src="" onerror="location.href='/memo?memo='+document.cookie">
위와 같이 onerror 이벤트로 memo의 엔드포인트로 이동하여 memo를 cookie로 전달하게 하면,
문제 1과 같이 /memo 엔드포인트에 쿠키가 노출될 것입니다.
- onerror는 이미지 로딩시 문제가 생겼을 때 호출됩니다. src=""로 설정하였기 때문에 onerror가 불릴 것입니다.
/memo 엔드포인트에서 플래그를 얻어냈습니다.
이 문제는 풀이 방법이 다양한 것 같습니다. 더 다양한 풀이는 구글에 XSS bypass sheet 또는 XSS cheat sheet라고 검색하시면 다양하게 XSS 필터링을 우회하는 방법이 나와있을 것입니다.
취약점 보완법
이 코드는 Flask로 짜여져 있고, 봇이 XSS 필터링을 하기 때문에 추가적인 우회에 대해서는 필터링 코드를 작성해야 합니다.
<, > 같은 특수문자를 필터링하는 것이 하나의 방법이 될 수 있습니다.
'해킹 > wargame' 카테고리의 다른 글
[webhacking] cookie, session- basic 풀이 (0) 2023.03.03 [web hacking] login filtering 풀이 (0) 2023.02.28 [web hacking] strcmp 풀이 (0) 2023.02.28 - /vuln : "param" 이라는 파라미터를 전달받고 그 값을 출력합니다.