Dreamhack/Dreamhack Wargame (Challenge)

[80] IT 비전공자 [dreamhack]Type c-j문제 풀기

imaginefuture-1 2024. 11. 28. 07:44

web 문제다 type c-j? cj 회사 그런건가요 ㅈㅅ 농담임

 

 

홈페이지 들어갔더니 id 비번을 쳐야한다

 

 

 

전세계 국룰 넣겠습니다
이런

 

 

소스코드 보러가볼게요

 

check.php

 

<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<title>Type c-j</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="/">Type c-j</a>
        </div>
        <div id="navbar">
          <ul class="nav navbar-nav">
            <li><a href="/">Index page</a></li>
          </ul>
        </div><!--/.nav-collapse -->
      </div>
    </nav><br/><br/><br/>
    <div class="container">
    <?php
    function getRandStr($length = 10) {
        $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $charactersLength = strlen($characters);
        $randomString = '';
    
        for ($i = 0; $i < $length; $i++) {
            $randomString .= $characters[mt_rand(0, $charactersLength - 1)];
        }
        return $randomString;

    }
    require_once('flag.php');
    error_reporting(0);
    $id = getRandStr();
    $pw = sha1("1");
    // POST request
    if ($_SERVER["REQUEST_METHOD"] == "POST") {
      $input_id = $_POST["input1"] ? $_POST["input1"] : "";
      $input_pw = $_POST["input2"] ? $_POST["input2"] : "";
      sleep(1);

      if((int)$input_id == $id && strlen($input_id) === 10){
        echo '<h4>ID pass.</h4><br>';
        if((int)$input_pw == $pw && strlen($input_pw) === 8){
            echo "<pre>FLAG\n";
            echo $flag;
            echo "</pre>";
          }
        } else{
          echo '<h4>Try again.</h4><br>';
        }
      }else {
      echo '<h3>Fail...</h3>';
     }
    ?> 
    </div> 
</body>
</html>

 

이 코드는 간단한 PHP 기반 인증 시스템으로, 특정 조건을 만족했을 때만 플래그를 출력하는 웹 애플리케이션입니다. 주요 로직을 분석하고, 플래그를 얻는 방법을 설명하겠습니다.


1. 주요 분석 포인트

1. 랜덤 ID 생성

$id = getRandStr();
  • getRandStr 함수는 10자리 길이의 랜덤 문자열을 생성합니다.
  • 이 문자열은 id 변수에 저장됩니다.

2. 비밀번호 설정

$pw = sha1("1");
  • 비밀번호는 SHA1 해시로 sha1("1")의 결과입니다.
  • SHA1("1")의 값은 356a192b7913b04c54574d18c28d46e6395428ab입니다.

3. 입력 검증

if ((int)$input_id == $id && strlen($input_id) === 10) {
    // ID 검증
    if ((int)$input_pw == $pw && strlen($input_pw) === 8) {
        echo "<pre>FLAG\n";
        echo $flag;
        echo "</pre>";
    }
}
  • 입력된 input_id와 input_pw를 검증합니다.
  • 조건:
    • input_id가 id와 같고, 길이가 10이어야 합니다.
    • input_pw가 pw와 같고, 길이가 8이어야 합니다.

4. 취약점 발견

  1. (int) 캐스팅 취약점:
    • (int)$input_id == $id에서 문자열이 정수형으로 캐스팅됩니다.
    • 랜덤 문자열 id가 숫자로 시작하지 않으면 (int)$id는 0이 됩니다.
    • 따라서, input_id에 0을 입력하면 조건을 우회할 수 있습니다.
  2. SHA1 해시의 정수 캐스팅:
    • SHA1 결과는 긴 문자열이지만, (int) 캐스팅하면 첫 숫자만 고려됩니다.
    • SHA1("1") = 356a192b7913b04c54574d18c28d46e6395428ab에서 (int)로 캐스팅하면 356이 됩니다.
    • 따라서 input_pw에 356을 입력해 조건을 우회할 수 있습니다.

2. 플래그 획득 방법

Exploit Steps

  1. ID 우회:
    • input_id에 0을 입력합니다. 이는 (int)$id == $id 조건을 우회합니다.
  2. PW 우회:
    • input_pw에 356을 입력합니다. 이는 (int)$pw == $pw 조건을 우회합니다.
  3. HTTP POST Request 다음과 같은 POST 요청을 보냅니다:
  4. POST / HTTP/1.1 Host: <target-url> Content-Type: application/x-www-form-urlencoded input1=0&input2=356

결과

  • 서버는 FLAG를 출력합니다.

3. 방어 방법

이 취약점을 막기 위해 다음과 같은 조치를 취할 수 있습니다:

  1. 엄격한 비교:
    • (int)를 사용하지 않고, === 연산자를 사용하여 타입과 값을 모두 비교합니다.
    if ($input_id === $id && strlen($input_id) === 10) { ... }
    
  2. SHA1 검증 강화:
    • SHA1 해시값을 비교할 때 문자열 비교를 사용합니다.
  3. 입력 검증:
    • ctype_alnum 등을 사용하여 입력값이 숫자나 알파벳으로만 구성되었는지 확인합니다.

요약

플래그를 얻으려면 POST 요청에 input1=0과 input2=356을 보내면 됩니다. 이는 (int) 캐스팅 취약점을 악용한 것입니다.

 


 

 

 

 

index.php

 

<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<title>Type c-j</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="/">Type c-j</a>
        </div>
        <div id="navbar">
          <ul class="nav navbar-nav">
            <li><a href="/">index page</a></li>
          </ul>
        </div><!--/.nav-collapse -->
      </div>
    </nav><br/><br/><br/>
    <div class="container">
      <div class="box">
      <h4>Enter the correct ID & Password.</h4>
        <p>
          <form method="post" action="/check.php">
              <input type="text" placeholder="Id" name="input1">
              <input type="text" placeholder="Password" name="input2">
              <input type="submit" value="제출">
          </form>
        </p>
      </div>

    <?php
        require_once('flag.php');
        error_reporting(0);
    ?> 
    </div> 
</body>
</html>

 


 


조건:input_id가 id와 같고, 길이가 10이어야 합니다.
input_pw가 pw와 같고, 길이가 8이어야 합니다.

SHA1 해시의 정수 캐스팅:SHA1 결과는 긴 문자열이지만, (int) 캐스팅하면 첫 숫자만 고려됩니다.SHA1("1") = 356a192b7913b04c54574d18c28d46e6395428ab에서 (int)로 캐스팅하면 356이 됩니다.따라서 input_pw에 356을 입력해 조건을 우회할 수 있습니다.

ID 우회:input_id에 0을 입력합니다. 이는 (int)$id == $id 조건을 우회합니다.

 

 

지피티가 알려준 힌트로 이것저것 넣어본다

id 0

pw 356

안됨-> 조건 안맞음

id 0000000000

pw 356

안됨->조건 안맞음

id 0000000000

pw 35619279 

안됨->int 된거 아니냐 왜안되냐

id 0000000000

pw 356a192b

로그인됨 아 ㅋㅋ 

 

flag 굳 굳