본문 바로가기

Web Hacking/Dreamhack

[Dreamhack] Command Injection Advanced write up

 

다음은 문제 코드이다.

 

<html>
    <head></head>
    <link rel="stylesheet" href="/static/bulma.min.css" />
    <body>
        <div class="container card">
        <div class="card-content">
        <h1 class="title">Online Curl Request</h1>
    <?php
        if(isset($_GET['url'])){
            $url = $_GET['url'];
            if(strpos($url, 'http') !== 0 ){
                die('http only !');
            }else{
                $result = shell_exec('curl '. escapeshellcmd($_GET['url']));
                $cache_file = './cache/'.md5($url);
                file_put_contents($cache_file, $result);
                echo "<p>cache file: <a href='{$cache_file}'>{$cache_file}</a></p>";
                echo '<pre>'. htmlentities($result) .'</pre>';
                return;
            }
        }else{
        ?>
            <form>
                <div class="field">
                    <label class="label">URL</label>
                    <input class="input" type="text" placeholder="url" name="url" required>
                </div>
                <div class="control">
                    <input class="button is-success" type="submit" value="submit">
                </div>
            </form>
        <?php
        }
    ?>
        </div>
        </div>
    </body>
</html>

 

GET요청의 url변수에 전달된 값을 가져오고 있다. strpos 함수를 통해 http가 포함된 문자열만 허용하고 있으며 받은 문자열을 shell_exec의 인자로 넘기고 있다.

 

문제 서버에 접속해보자.

 

 

해당 입력폼에 전달 시 GET 요청이 전송되는 것 같다. 이 문제에서는 escapeshellcmd 함수로 전달 받은 문자열을 필터링하고 있기 때문에 쉘 메타문자를 사용할 수 는 없다. 따라서 curl 명령어의 옵션만을 이용할 수 있다.

 

 

문제로 제공된 폴더를 보면 flag.c가 존재함을 알 수 있다. Dockerfile을 보면 flag.c 파일은 컴파일 되어 flag파일만 남고 사라짐을 알 수 있으며 파일 경로는 서버의 루트 경로 바로 밑에 존재한다. (/var/www가 아닌 / 밑에 있는 듯)

 

강의에서 나온 curl -o 옵션을 활용하려 시도했다. curl의 -o 옵션은 curl로 요청 보낸 후 응답 받을 위치를 로컬 위치로 선택할 수 있다. 먼저 문제 서버에서 작동하는지 테스트했다.

 

curl -o 테스트


 

문제 서버에서 접근이 가능한 cache 경로를 활용했다.

 

요청 후 

 

접근..? 요청을 /var/www/html/cache/test.txt로 보내야 되는데 위 과정을 생략했다..😅 다시

 

요청

 

접근 결과 제대로 저장이 됐다..! 이제 저 방식을 통해 cache 디렉토리 밑에 웹쉘을 저장할 수 있으면 cat /flag가 가능할 것 같다.

 

근데 아무리 생각해봐도 문제 서버를 통해 웹쉘을 올리거나 바로 flag를 얻는 법은 없다. 따라서 내 서버에 웹쉘을 올리고 curl -o를 통해 문제서버에 웹쉘이 저장되도록 접근이 필요하다. 집가면 해봐야지.. -> 자취방 공유기 관리자 페이지 비번을 전 주인이 바꿔놨는데 초기화도 안됨...ㅠㅠ

 

깃허브를 이용하자!

 

 

익스익스익스


 

 

 

깃헙에 웹쉘을 올린다. -> [내 깃헙닉넴].github.io/프로젝트 폴더명/파일명 -> 으로 서버처럼 깃헙을 이용할 수 있다.

 

 

입력폼에 다음과 같이 입력 후 -o 옵션을 통해 문제 서버에 업로드 후 접근하면,

 

 

위와 같이 웹쉘이 실행됐다. ㅎㅎ flag는 / 아래 있지만 제대로 확인해보자.

 

 

이제 flag를 가져오면 되지만, flag는 컴파일된 실행 파일이므로 실행하면 puts함수를 통해 flag를 뱉어낼 거다.

 

 

ㄱㄱ