[WARGAME][드림핵 CTF] Relative Path Overwrite Advanced

jckim22·2022년 12월 8일
0

[WEBHACKING] STUDY (WARGAME)

목록 보기
111/114

이번 문제는 이전에 공부할 때 풀었던 문제이다. 다시 복습 차원에서 풀어보도록 하겠다.

공부한 것을 활용하여 처음 푸는 느낌으로 문제를 풀어나갔다.

아래는 서버 코드이다.

index.php

<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<title>Relative-Path-Overwrite-Advanced</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-Advanced</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>

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>

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') {
        param = "nope !!";
    }
    else {
        for (var i = 0; i < filter.length; i++) {
            if (param.toLowerCase().includes(filter[i])) {
                param = "nope !!";
                break;
            }
        }
    }

    param_elem.innerHTML = param;
</script>

404.php

<?php 
    header("HTTP/1.1 200 OK");
    echo $_SERVER["REQUEST_URI"] . " not found."; 
?>

이전 문제와 코드 상에서 눈에 띄게 다른 점은 404.php이다.

나머지는 분석을 해봐야 알 것 같다.

먼저 웹페이지를 분석해보겠다.
아래를 보자

아무것도 하지 않았는데 nope!! 이 출력된다.

filter.js가 어떻게 돌아가는지 확인하려고 souces탭을 보았는데 filter.js는 로드되어 있지 않았다.

위처럼 fiter.js는 static라는 디렉토리 안에 있는데 여전히 호스트/filter.js를 로드하니 당연한 일이었다.

그리고 소스상의 script에서 이전 문제와 다른 점을 하나 더 발견 했다.
filter가 정의되어 있지 않으면 nope !!을 출력하는 것이다.

그래서 어떤 문자를 입력하든 nope이 출력된 것이다.

이제 핵심이라고 생각 되는 404.php를 보자.


위 코드를 보면 패킷에서 요청 url을 출력한 뒤 not found라고 출력해준다.

이를 이용하여 xss를 시도할 수 있다.

아래처럼 잘못된 파일을 잘못된 경로로 로드 할 떄 404.php가 불러와진다.
또한 vuln 페이지는 /때문에 /filter.js를 로드하고 있다.

잘못된 파일을 로드하고 있는 것인데 어떤 설정에 의해 js파일에 그 내용이 담기게 된다.

아래처럼 잘못된파일/ 이렇게 하면 내가 입력한 잘못된 경로마저 request url로 인식이 되어 화면에 출력되게 된다.

그럼404.php를 악용하여 잘못된 경로를 입력하는 곳에 script문을 삽입하면 문제를 풀 수 있을 것 같다.

아래처럼 아무문자 뒤에 /까지 붙였더니 filter.js에는 그 문자가 url로 인식되어 출력되고 있었다.
그럼 앞에 내용을 끝내고 뒤에 내용을 주석처리 한다면 script문을 실행할 수 있을 것이다.

아래처럼 injection 하면 앞에 내용은 ;으로 인해 끝나게 되고 뒤에는 //로 인해 주석처리가 되면서 alert가 실행되게 된다.

alert를 변형해 아래처럼 익스플로잇을 짠다.
이전과 달리 %2b로 +를 인코딩 할 필요가 없는 것이 그저 파일에 내용이 담기는 것이기 때문에 인코딩을 할 필요가 없는 것 같다.

%2b, +를 두번 시도해서 된 것이라서 정확한 이유를 알 수 없다.

코드 상에서는 encode가 되고 있는데 post를 보내면 당연히 인코딩이 될 것이라고 생각했지만 +만 가능했다.

이유는 추후에 더 알아보겠다.
아마 전 문제는 접속이었고 이번 문제는 파일에 코드를 쓰는 느낌이라서 그런 것 같다.

profile
개발/보안

0개의 댓글