SlowTurtle_

천천히 그러나 끝까지 완주

Webhacking-Write-Up/Dreamhack

[Dreamhack] phpMyRedis

SlowTurtle_ 2023. 1. 11. 12:03
728x90

[Dreamhack] phpMyRedis

기본 페이지는 위와 같이 생겼다.

<?php
    include_once "./core.php";
?>
<html>
    <head></head>
    <link rel="stylesheet" href="/static/bulma.min.css" />
    <body>
        <div class="container card">
            <div class="card-content">
                <div class="columns">
                    <div class="column is-10">
                        <h1 class="title">phpMyRedis</h1>
                    </div>
                    <div>
                        <div class="column is-2"><a href="/config.php" class="card-footer-item">Config</a></div>
                    </div>
                </div>
                <form method="post">
                    <div class="field">
                        <label class="label">Command</label>
                        <div class="control">
                            <textarea class="textarea" name="cmd"><?=isset($_POST['cmd'])?$_POST['cmd']:'return 1;'?></textarea>
                        </div>
                        <label class="checkbox">
                            <input type="checkbox" name="save">Save
                        </label>
                    </div>
                    <div class="control">
                        <input class="button is-success" type="submit" value="submit">
                    </div>
                </form>
                <?php 
                    if(isset($_POST['cmd'])){
                        $redis = new Redis();
                        $redis->connect($REDIS_HOST);
                        $ret = json_encode($redis->eval($_POST['cmd']));
                        echo '<h1 class="subtitle">Result</h1>';
                        echo "<pre>$ret</pre>";
                        if (!array_key_exists('history_cnt', $_SESSION)) {
                            $_SESSION['history_cnt'] = 0;
                        }
                        $_SESSION['history_'.$_SESSION['history_cnt']] = $_POST['cmd'];
                        $_SESSION['history_cnt'] += 1;

                        if(isset($_POST['save'])){
                            $path = './data/'. md5(session_id());
                            $data = '> ' . $_POST['cmd'] . PHP_EOL . str_repeat('-',50) . PHP_EOL . $ret;
                            file_put_contents($path, $data);
                            echo "saved at : <a target='_blank' href='$path'>$path</a>";
                        }
                    }
                ?>
            </div>
        </div>
        <br/>
        <div class="container card">
            <div class="card-content">
                <div class="columns">
                    <div class="column is-10">
                        <h1 class="title">Command History</h1>
                    </div>
                    <div class="column is-2"><a href="/reset.php" class="card-footer-item">Reset</a></div>
                </div>
                <div class="content">
                    <ul>
                    <?php
                        for($i=0; $i<$_SESSION['history_cnt']; $i++){
                            echo "<li>".$_SESSION['history_'.$i]."</li>";
                        }
                    ?>
                    </ul>
                </div>
            </div>
        </div>
    </body>
</html>

if(isset~ 부분을 보자. $redis변수는 Redis클래스의 인스턴스임을 알 수 있다. 따라서 Redis의 모든 기능을 사용할 수 있는 것을 알 수 있다. 중간에 -> 이 있길래 저게 사용이 가능한가싶어서 알아보니 해당 객체의 안쪽을 지칭할 때 사용하는 것을 알 수 있었다. 그 다음 eval메소드의 인수 값을 사용자가 입력한 값으로 받아온다.(eval함수 참고 => https://support.microsoft.com/ko-kr/office/eval-%ED%95%A8%EC%88%98-8c4a1b10-85ba-40db-b0c8-5290da4d4166)

(redis 공식 사이트에서 eval함수 사용법 참고 https://redis.io/commands/eval/)

자 그럼 이제 flag를 가져오기 위한 과정을 시작해보자!

위치를 /var/www/html로 변경(현재 위치가 /var/www/html 되어있었지만 확실함을 위해..)

Redis의 dbfilename을 slow.php로 바꿨다.(whebshell에 업로드하기 위함.) 

생성한 webshell을 Redis에서 인식하게 만들기 위하여 save명령어 사용(Redis메모리는 휘발성임을 기억하자. save명령어로 파일의 경로, 이름, 데이터를 함께 설정할 수 있음.)

webshell에 올렸다. 그리고 slow.php에 들어갔을 때 바로 /flag가 출력되도록했다.

flag값을 획득할 수 있었다.

728x90