WARGAME/web

[dreamhack] phpreg

lucykorea414 2023. 6. 28. 23:43
728x90

저번주에 진행한 이캅스 ctf에서 웹 챌린저팀이 만든 문제 + 드림핵의 babylinux 짬뽕한 문제느낌!!

텍스트 대체 + 리눅스 명령어를 우회할 수 있는지 보는 문제였습니다.

우선 접속하면 나오는 웹페이지입니다.

함께 제공되는 index.php 파일을 살펴봅시다.

 

<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<title>PHPreg</title>
</head>
<body>
    <!-- Fixed navbar -->
    <nav class="navbar navbar-default navbar-fixed-top">
      <div class="container">
        <div class="navbar-header">
          <a class="navbar-brand" href="/">PHPreg</a>
        </div>
        <div id="navbar">
          <ul class="nav navbar-nav">
            <li><a href="/">Step 1</a></li>
            <li><a href="/step2.php">Step 2</a></li>
          </ul>
        </div><!--/.nav-collapse -->
      </div>
    </nav><br/><br/><br/>
    <div class="container">
      <div class="box">
        <h4>Step 1 : Open the door & Go to Step 2 !!</h4>
        <div class="door"><div class="door_cir"></div></div>
        <p>
          <form method="post" action="/step2.php">
              <input type="text" placeholder="Nickname" name="input1">
              <input type="text" placeholder="Password" name="input2">
              <input type="submit" value="제출">
          </form>
        </p>
      </div>
    </div> 

    <style type="text/css">
      h4 {
        color: rgb(84, 84, 84);
      }
      .box{
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
      }
      .door { 
        position: relative;
        margin: 20px 0px;
        width: 140px;
        height: 180px;
        background-color: #b9abf7;
        border-radius: 10px;
      }
      .door_cir{
        position: absolute;
        border-radius: 50%;
        width: 20px;
        height: 20px;
        border: 2px solid rgba(255, 222, 113, 0.873);
        background-color: #ffea98;
        top: calc( 180px / 2 - 10px );
        right: 10px;
      }
    </style>
</body>
</html>

우선 크게 특별한건 없어 보이는데, 우선 nickname과 password를 입력하고 버튼을 누르면 post로 정보를 넘기고 있습니다.

 

여기서 step2.php를 보면,

<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<title>PHPreg</title>
</head>
<body>
  <!-- Fixed navbar -->
  <nav class="navbar navbar-default navbar-fixed-top">
    <div class="container">
      <div class="navbar-header">
        <a class="navbar-brand" href="/">PHPreg</a>
      </div>
      <div id="navbar">
        <ul class="nav navbar-nav">
          <li><a href="/">Step 1</a></li>
          <li><a href="/step2.php">Step 2</a></li>
        </ul>
      </div><!--/.nav-collapse -->
    </div>
  </nav><br/><br/><br/>
  <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>

  <style type="text/css">
    h4 {
      color: rgb(84, 84, 84);
    }
    .box{
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
    }
    pre {
      width: 80%;
    }
    .door_box {
      position: relative;
      width: 240px;
      height: 180px;
      margin: 20px 0px;
    }
    .door_black {
      position: absolute;
      width: 140px;
      height: 180px;
      background-color: black;
      border-radius: 10px;
      right:0px;
    }
    .door {
      z-index: 2;
      position: absolute;
      width: 140px;
      height: 180px;
      background-color: #b9abf7;
      border-radius: 10px;
      right: 100px;
    }
    .door_cir{
      z-index: 3;
      position: absolute;
      border-radius: 50%;
      width: 20px;
      height: 20px;
      border: 2px solid rgba(255, 222, 113, 0.873);
      background-color: #ffea98;
      top: calc( 180px / 2 - 10px );
      right: 10px;
    }
  </style>
</body>
</html>

이 부분에서 preg_match() 함수를 통해 post로 온 값을 대체하고 있습니다.

 

name이라는 변수는 우리가 입력한 input_name에서 nyang이라는 글자를 대소문자 구분 없이 지워버리고 있고, 마지막 if문을 보면 우리는 name을 dnyang0310으로 바꿔줘야합니다.

비밀번호는 숫자, "@" 기호, 2~3개의 숫자, "31"을 1회 이상 반복하며, 숫자 0부터 8을 제외한 어떤 문자든지가 마지막에 "!" 문자로 끝나는 패턴을 하면 d4y0r50ng으로 대체되고, 특이하게 input_pw에는 영어문자가 들어가면 안됩니다!

계속 머릿속으로만 생각하면서 하면 결과가 눈에 안보여서 짜증나서 저는 https://onlinephp.io/ 라는 사이트를 사용하여 테스트를 했습니다.

 

PHP Sandbox - Execute PHP code online through your browser

 

onlinephp.io

대체 될 것을 예상하고 마지막 결과가 if문과 같이 나오기 위해서는 다음과 같이 해주면 굳!!

그럼 이제 올바른 값을 입력해주면 다음과 같은 step2 화면이 뜹니다!

 

여기서 step2.php를 다시 보면, 

우리는 문제 설명을 통해 ../dream/flag.txt 여기에 플래그가 있다는 것을 알고 있습니다.

 

그러면, "flag"라는 단어 없이 저 flag.txt를 읽어야한다는것!

이거는 이미 babylinux를 풀면서 알게되었죠!

 

command에 cat ../dream/*.txt 를 쳐주면 다음과 같이 플래그가 뜹니다 :)

굳!! ㅎㅎ

728x90