소스코드 보러가볼게요
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. 취약점 발견
- (int) 캐스팅 취약점:
- (int)$input_id == $id에서 문자열이 정수형으로 캐스팅됩니다.
- 랜덤 문자열 id가 숫자로 시작하지 않으면 (int)$id는 0이 됩니다.
- 따라서, input_id에 0을 입력하면 조건을 우회할 수 있습니다.
- SHA1 해시의 정수 캐스팅:
- SHA1 결과는 긴 문자열이지만, (int) 캐스팅하면 첫 숫자만 고려됩니다.
- SHA1("1") = 356a192b7913b04c54574d18c28d46e6395428ab에서 (int)로 캐스팅하면 356이 됩니다.
- 따라서 input_pw에 356을 입력해 조건을 우회할 수 있습니다.
2. 플래그 획득 방법
Exploit Steps
- ID 우회:
- input_id에 0을 입력합니다. 이는 (int)$id == $id 조건을 우회합니다.
- PW 우회:
- input_pw에 356을 입력합니다. 이는 (int)$pw == $pw 조건을 우회합니다.
- HTTP POST Request 다음과 같은 POST 요청을 보냅니다:
- POST / HTTP/1.1 Host: <target-url> Content-Type: application/x-www-form-urlencoded input1=0&input2=356
결과
- 서버는 FLAG를 출력합니다.
3. 방어 방법
이 취약점을 막기 위해 다음과 같은 조치를 취할 수 있습니다:
- 엄격한 비교:
- (int)를 사용하지 않고, === 연산자를 사용하여 타입과 값을 모두 비교합니다.
if ($input_id === $id && strlen($input_id) === 10) { ... }
- SHA1 검증 강화:
- SHA1 해시값을 비교할 때 문자열 비교를 사용합니다.
- 입력 검증:
- 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
로그인됨 아 ㅋㅋ
'Dreamhack > Dreamhack Wargame (Challenge)' 카테고리의 다른 글
[82] IT 비전공자 [dreamhack]memory_leakage문제 풀기 (0) | 2024.11.30 |
---|---|
[81] IT 비전공자 [dreamhack]NoSQL-CouchDB문제 풀기 (0) | 2024.11.29 |
[79] IT 비전공자 [dreamhack]out of money문제 풀기 (0) | 2024.11.27 |
[78] IT 비전공자 [dreamhack]Simple Crack Me문제 풀기 (0) | 2024.11.26 |
[77] IT 비전공자 [dreamhack][wargame.kr] tmitter문제 풀기 (0) | 2024.11.25 |