[드림핵] phpreg

SONG's 보안·2024년 5월 7일

드림핵

목록 보기
27/33

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


문제 설명

들어가면 이런 화면이 떠있다.

문제 설명에 나와있는 것처럼 알맞은 nickname과 password를 입력해야하는 것 같다.

F12를 눌러서 코드를 확인해보았는데 별도로 nickname과 password에 관한 내용이 없어 문제 파일을 봐보았다.

문제파일에는 step2.php라는 파일이 있었고 확인해보았다.

  <div class="container">
    <div class="box">
      <!-- PHP code -->
      <?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";
          }
      ?>
    </div>
  </div>

여기에서 중요하게 볼 코드는 이것이다.

              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"] : "";

Name --> "dnyang0310", p --> "d4y0r50ng+1+13"이면 step2로 넘어갈 수 있다는 사실을 알 수 있다.
하지만 입력 값에 필터링이 되어있어 해당 값들을 그대로 입력하면 제대로 로그인을 할 수 없다.

첫번째 조건은 pw가 소문자나 대문자가 포함되어있으면 아래 문구가 뜬다.

            if (preg_match("/[a-zA-Z]/", $input_pw)) {
              echo "alphabet in the pw :(";
            }

즉, 비밀번호가 d4y0r50ng+1+13이지만 알파벳이 포함되어있으면 안된다는 것이다.

두번째 조건은 Name에서 "nyang"을 빈 문자열로 필터링한다. 그리고 pw는 정규표현식을 통해 필터링 된다.

              $name = preg_replace("/nyang/i", "", $input_name);
              $pw = preg_replace("/\d*\@\d{2,3}(31)+[^0-8\"]\!/", "d4y0r50ng", $input_pw);

즉, Name의 값이 dnyang0310이지만 빈 문자열로 바꿔버린다는 것이다...

그렇다면 어떻게 풀어야할까?

Name같은 경우, 필터링한 값이 dnyang0310 되야하므로 dnynyangang0310이라고 적으면 된다. 중간의 nyang만 없어지므로 필터링을 우회할 수 있다.

pw의 정규표현식을 풀어보면

\d* : 0 ~ 9까지 중 한 자리 숫자를 의미. 뒤의 *은 0개 이상 나타나야 한다는 것을 의미
\d{2, 3}(31) : 0 ~ 9까지 중 한 자리 숫자를 2번 혹은 3번 반복
+ : 지금까지의 표현을 1회 이상 반복
[^0-8] : 0~8 이외의 문자가 있어야한다.

이렇게 정규표현식을 해석해서 pw을 써보면 44@555319!+1+13 라고 만들어 주었다.

입력하니 step2로 넘어갔다.

입력 창에 command라고 뜨길래 무슨 명령어를 입력해야하는게 아닌가 싶어 소스코드를 다시 보았다.

                // 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";
              }

보면 flag에 대한 필터링이 적용되어있다.
리눅스 명령어 중 *를 이용해서 코드를 쓰면되지 않을까 싶었다.
cat ../dream/*.txt
맨 위 사진을 보면 flag파일의 주소가 나와있어 그것을 이용해주었다.

profile
前) SWLUG 27기

0개의 댓글