본문 바로가기
Dreamhack WarGame

[Dreamhack] phpreg 문제 풀이

by whiteTommy 2023. 11. 28.

Dreamhack CTF Season 3 Round #6 (🌱Div2) 에 출제된 문제입니다.

 

 

문제 파일을 받고, 웹 서버로 접속한다.

 

우선, Nickname과 Password를 입력해야 할 것으로 보인다.

 

앞서, 다운받은 문제 파일에서 step2.php 파일에서 Nickname과 Password와 관련된 부분을 확인해 보자.

<?php
          // POST request
          if ($_SERVER["REQUEST_METHOD"] == "POST") {
            $input_name = $_POST["input1"] ? $_POST["input1"] : "";
            $input_pw = $_POST["input2"] ? $_POST["input2"] : "";

            // pw filtering
            if (preg_match("/[a-zA-Z]/", $input_pw)) {
              echo "alphabet in the pw :(";
            }
            else{
              $name = preg_replace("/nyang/i", "", $input_name);
              $pw = preg_replace("/\d*\@\d{2,3}(31)+[^0-8\"]\!/", "d4y0r50ng", $input_pw);
              
              if ($name === "dnyang0310" && $pw === "d4y0r50ng+1+13") {
                echo '<h4>Step 2 : Almost done...</h4><div class="door_box"><div class="door_black"></div><div class="door"><div class="door_cir"></div></div></div>';

                $cmd = $_POST["cmd"] ? $_POST["cmd"] : "";

                if ($cmd === "") {
                  echo '
                        <p><form method="post" action="/step2.php">
                            <input type="hidden" name="input1" value="'.$input_name.'">
                            <input type="hidden" name="input2" value="'.$input_pw.'">
                            <input type="text" placeholder="Command" name="cmd">
                            <input type="submit" value="제출"><br/><br/>
                        </form></p>
                  ';
                }
                // cmd filtering
                else if (preg_match("/flag/i", $cmd)) {
                  echo "<pre>Error!</pre>";
                }
                else{
                  echo "<pre>--Output--\n";
                  system($cmd);
                  echo "</pre>";
                }
              }
              else{
                echo "Wrong nickname or pw";
              }
            }
          }
          // GET request
          else{
            echo "Not GET request";
          }
      ?>

 

위의 코드를 보면 NickName과 PassWord가 노출되어 있다는 사실을 알 수 있다.

if ($name === "dnyang0310" && $pw === "d4y0r50ng+1+13")

 

하지만, 위와 같이 직접 입력할 경우 필터링에 의해 nyang는 공백으로 대체될 것이고, password는 알파벳이 있으면 안 되므로 에러가 날 것이다.

 

먼저, nyang가 지워져도 dnyang0310이 입력으로 들어가도록 우회를 해보자.

NickName에는 dnynyangang0310를 입력하면 된다.

 

다음으로, 알파벳을 입력하지 않지만, d4y0r50ng+1+13이 입력으로 들어가도록 하기 위해 정규표현식을 보자.

 

/\d*\@\d {2,3}(31)+[^0-8\"]\!/  정규표현식이 d4y0r50ng로 바뀐다는 사실을 알 수 있다.

 

이제 정규 표현식 /\d*\@\d{2,3}(31)+[^0-8\"]\!/ 을 해석해 보자.

\d* : 숫자 0개 이상이다.

\@ : @이다.

\d {2,3} : 숫자 2개 이상 3개 이하이다.

(31)+ : 31이 1개 이상이다.

[^0-8\"] : 0-8, "제외한 나머지이다.

\! :!이다.

 

password에는 0@00319!+1+13을 입력하면 된다.

 

그러면, Step 2로 넘어갈 수 있다.

 

원하는 output이 나오기 위해서는 cat../dream/flag.txt를 통해 플래그를 얻을 수 있지만, cmd 필터링을 보면 flag가 있으면 error가 난다는 사실을 알 수 있다. 

cat ../dream/fla*.txt

 

 

위와 같이 입력해 주면 다음 결과를 얻을 수 있다.

--Output--
DH{ad866c64dabaf30136e22d3de2980d24c4da617b9d706f81d10a1bc97d0ab6f6}