문제 설명
php 7.4로 작성된 페이지입니다.
알맞은 Input 값을 입력하고 플래그를 획득하세요.
플래그 형식은 DH{}
입니다.
풀이
해당 문제로 접속하면 아래와 같은 입력 폼이 2개가 존재한다.
소스 코드
소스 코드는 index.php, check.php, flag.php가 있고 다음과 같다.
index.php
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<title>php7cmp4re</title>
</head>
<body>
<!-- Fixed navbar -->
<nav class="navbar navbar-default navbar-fixed-stop">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="/">php7cmp4re</a>
</div>
<div id="navbar">
<ul class="nav navbar-nav">
<li><a href="/">index page</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</nav>
<div class="container">
<div class="box">
<h4>Enter the correct Input.</h4>
<p>
<form method="post" action="/check.php">
<input type="text" placeholder="input1" name="input1">
<input type="text" placeholder="input2" name="input2">
<input type="submit" value="제출">
</form>
</p>
</div>
<?php
require_once('flag.php');
error_reporting(0);
?>
</div>
</body>
</html>
check.php
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<title>php7cmp4re</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="/">php7cmp4re</a>
</div>
<div id="navbar">
<ul class="nav navbar-nav">
<li><a href="/">Index page</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</nav>
<div class="container">
<?php
require_once('flag.php');
error_reporting(0);
// POST request
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$input_1 = $_POST["input1"] ? $_POST["input1"] : "";
$input_2 = $_POST["input2"] ? $_POST["input2"] : "";
sleep(1);
if($input_1 != "" && $input_2 != ""){
if(strlen($input_1) < 4){
if($input_1 < "8" && $input_1 < "7.A" && $input_1 > "7.9"){
if(strlen($input_2) < 3 && strlen($input_2) > 1){
if($input_2 < 74 && $input_2 > "74"){
echo "</br></br></br><pre>FLAG\n";
echo $flag;
echo "</pre>";
} else echo "<br><br><br><h4>Good try.</h4>";
} else echo "<br><br><br><h4>Good try.</h4><br>";
} else echo "<br><br><br><h4>Try again.</h4><br>";
} else echo "<br><br><br><h4>Try again.</h4><br>";
} else{
echo '<br><br><br><h4>Fill the input box.</h4>';
}
} else echo "<br><br><br><h3>WHat??!</h3>";
?>
</div>
</body>
</html>
flag.php
<?php
$flag = 'flag{**Sample**}'
?>
소스 코드를 분석해보면 flag.php는 그냥 FLAG가 flag 변수에 들어있고 형식을 알려준다.
index.php에서 중요한 소스 코드는 아래와 같다. check.php로 POST 메소드로 전송되는 폼이 있고, 입력 폼 2개는 각각 input1과 input2가 존재한다. php 코드는 require_once 함수를 사용해서 flag.php 파일을 읽어오고, error_reporting 함수의 인자가 0이므로 오류 출력을 끈 것을 볼 수 있다.
<form method="post" action="/check.php">
<input type="text" placeholder="input1" name="input1">
<input type="text" placeholder="input2" name="input2">
<input type="submit" value="제출">
</form>
<?php
require_once('flag.php');
error_reporting(0);
?>
check.php에서 중요한 소스 코드는 아래 코드이다. check.php처럼 require_once 함수를 사용해 flag.php 파일을 읽어오고 error_reporting 함수로 오류 출력을 끄고 있다. 아래의 주석으로 친절하게 POST 메소드 요청이 어떻게 처리되는지 보여주고 있다. 요청되는 메소드가 POST이면 input1에 입력한 값은 input_1로 input2에 입력한 값은 input_2의 변수에 저장된다.
input_1과 input_2의 값이 둘 다 존재해야 하고 input_1의 길이는 4보다 작아야 한다. 또한 8보다 작고, 7.A보다 작아야 하며, 7.9보다는 커야 한다. input_2는 길이가 3보다 작고 1보다 커야 한다. 값은 숫자 74보다 작아야 하고, 문자 74보다 커야 한다고 한다.
<div class="container">
<?php
require_once('flag.php');
error_reporting(0);
// POST request
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$input_1 = $_POST["input1"] ? $_POST["input1"] : "";
$input_2 = $_POST["input2"] ? $_POST["input2"] : "";
sleep(1);
if($input_1 != "" && $input_2 != ""){
if(strlen($input_1) < 4){
if($input_1 < "8" && $input_1 < "7.A" && $input_1 > "7.9"){
if(strlen($input_2) < 3 && strlen($input_2) > 1){
if($input_2 < 74 && $input_2 > "74"){
echo "</br></br></br><pre>FLAG\n";
echo $flag;
echo "</pre>";
} else echo "<br><br><br><h4>Good try.</h4>";
} else echo "<br><br><br><h4>Good try.</h4><br>";
} else echo "<br><br><br><h4>Try again.</h4><br>";
} else echo "<br><br><br><h4>Try again.</h4><br>";
} else{
echo '<br><br><br><h4>Fill the input box.</h4>';
}
} else echo "<br><br><br><h3>WHat??!</h3>";
?>
</div>
FLAG 조건
앞에서 약간 설명이 길었는데 flag의 조건은 다음과 같다.
- input1과 input2의 값이 둘 다 존재해야 한다.
- input1의 길이는 4보다 작아야 하고, 문자 8과 7.A보다 작아야 하며, 문자 7.9보다 커야 한다.
- input2의 길이는 2어야 하고, 숫자 74보다 작고, 문자 74보다 커야 한다.
여기서 숫자도 아니고 문자열과 연산을 하고 있다. php 7.0 이상부터는 타입 힌팅 강화라는 것에 의해 funtion ( int $foo )
라고 했을 때, “100”의 문자를 넘기면 int 형의 100으로 변환된다고 한다. 따라서 문자열을 정수로 비교할 때, 문자열을 정수로 변환하려 시도한다는 것을 알 수 있다.
7.A
라는 문자열은 처음 보는 형태이다. 이는 찾아보니 16진수로 나타내어 A가 16진수로 0x41이 된다. ASCII 코드 표를 살펴보면 9인 0x39보다 커야 하므로 이 사이에 있는 문자는 : ; < = > ? @
의 문자가 해당된다.
따라서 7.:
문자를 input1 자리에 넣고 input2는 일단 74를 넣어서 확인해보았다.
개발자 도구로 확인해보면 Good try.라는 문자열이 보인다. 이는 input1의 조건을 만족했다는 문자열이다.
두 번째로 input2에 들어갈 값의 길이는 1과 3 사이이고, “74” < input2 < 74 이어야 한다. php에서는 문자열에서 숫자로 형변환할 때, 숫자가 아닌 문자를 만날 때까지 가장 긴 문자를 찾는다. 만약 7:
이라고 한다면 이는 "74"
보다 크고 숫자인 74
보다 작게 되는 것이다. 따라서 7 다음에 숫자가 아닌 아무 특수문자나 영문자를 써주면 이를 만족한다. 한글은 참고로 한 글자에 3바이트로 해석하니 안된다.
댓글남기기