Linux

[Linux] 드림핵 phpreg 문제 풀이 : 정규표현식 활용

여백 :: 2024. 12. 20. 23:30

 

비기너즈에 있는 정규 표현식 활용 문제이다.

걍 코드 분석만 제대로 하면 쉽게 풀 수 있는 문제지만, 본의 아니게 이상한데서 삽질하는 바람에 조금 오래걸림 에휴;;

 

 

사이트는 이렇게 생겼고 step1과 step2를 거쳐야 flag를 획득할 수 있는 듯 하다.

 

일단 아래 코드부터 살펴보자. (문제 풀이에 필요한 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>

 

 

사이트에 name과 pw를 입력하면 정규표현식으로 이를 필터링 하고 다음 step으로 넘어가서 cmd로 flag를 찾으면 되는 구조이다. 아래 정규표현식 filtering을 분석하여 name과 pw를 작성해보자.

 

// 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>';

 

우선 가장 첫 번째 필터링은 pw 필터링인데, 대소문자 알파벳을 막고있다.

 

1. pw : 알파벳 금지

 

이후 else 문에서 먼저 name의 경우 nyang 문자열이 포함되어 있다면, 해당 부분을 공백으로 대체하고 있고, 그 이후의 중첩 if문을 보면 $name이 dnyang0310 이어야 step2로 넘어가는 것을 볼 수 있다. 

어쨋든 nyang은 포함이 되어야 step2로 넘어가는데 현재 해당 단어를 필터링하고 있기에 다음과 같이 작성해주면 된다.

 

2. name = dnynyangang0310 

 

이렇게 하면 중간의 nyang 문자열이 공백으로 대체되었을때 앞 뒤로 있던 ny + ang이 합쳐지면서 문자열이 포함될 수 있다!

 

name을 구했으니 이제 pw로 넘어가면, 얘는 필터링이 다음과 같이 더욱 구체적으로 되어있다.

\d* : 숫자가 0개 이상

\@ : @ 문자

\d{2,3} : 숫자가 2~3개

(31)+ : 31 이 1개 이상

[^0-8\"] : 0에서 8까지의 숫자 혹은 " 문자 이외의 한 문자

\! : ! 문자

 

위 조건을 만족하는 문자열이 pw로 들어왔을때, 해당 부분을 d4y0r50ng 로 대체해준다는 의미이다.

여기에 앞서 1번에서 pw에 알파벳 금지였던 점을 명심해야 하는데, 이는 [^0-8\"] 부분에서 알파벳을 사용하게 되면 이러한 이유에 의해 필터링에 걸리므로 숫자 9를 사용해주었다. (본인은 이를 까먹고 알파벳을 넣었다가 계속 막혔었다...)

 

그리고 이후의 중첩 if문을 보면 $pw가 d4y0r50ng +1+13 여야 step2로 넘어갈 수 있으므로 해당 정규표현식 대치 부분 뒤에 +1+13까지 붙여줘야 통과가 될 것이다.

 

위 분석 결과를 토대로 pw를 다음과 같이 작성하였음!

 

3. pw = 123@12319!+1+13

 

 

 

그러면 이렇게 step2로 넘어가게 된다!

 

step2 부분의 코드는 다음과 같다.

 

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

 

step1과 달리 굉장히 간단한데, 오직 flag 단어만 필터링 하고 있으므로 그냥 fl*ag 를 넣어주면 될 것 같다.

 

따라서 다음과 같이 작성하여 플래그 획득!

 

 

플래그 획득