문제 설명
사이트에 들어가 보면
이렇게 Step 1과 Step 2를 해결해야만 flag를 찾을 수 있는 형식인 것 같다.
문제 파일을 다운로드해 봤다.
<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>
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">
<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>
index.php
step1.php는 왜 없는 건지 의문이긴 하지만.. 우선 대부분의 경우 그랬듯이 index.php 파일에는 유용한 정보가 없는 것 같다.
step2.php를 살펴 보니, 각각 Nickname과 Password에 들어가야 하는 값을 직접적으로 보여주고 있는 것을 확인했다.
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"] : "";
name이 "dnyang0310", pw가 "d4y0r50ng+1+13"이면 step2로 넘어갈 수 있다.
그러나, 입력값에 필터링이 걸려있는 것 역시 코드에서 찾아볼 수 있다.
위 코드를 보면 사용자가 입력한 name값에서 nyang을 빈 문자열로 필터링한다.
그렇기 때문에 name값에 dnyangnyang0310을 입력해 nyang이 정상적으로 들어가도록 해야 한다.
// pw filtering
if (preg_match("/[a-zA-Z]/", $input_pw)) {
echo "alphabet in the pw :(";
알파벳 대소문자 모두 입력 시 오류 메시지가 뜬다는 것이다.
그렇기 때문에 문제 이름대로 php 정규식을 이용하여 해결해야 되는 것 같다.
pw의 정규 표현식을 하나씩 해체해 보면,
\d* : 0~9 사이 숫자가 0개 이상 나타나야 함
\@ : @
\d{2, 3}(31) : 0~9 사이의 숫자 2~3회 후에 31을 씀
+ : 지금까지의 표현을 1회 이상 반복
[^0-8] : 0~8 이외의 문자가 있으면 패턴이 매칭
! : !
모든 요소를 조합해 보면 1@12319!라는 문자열을 만들 수 있다.
비밀번호는 d4y0r50ng+1+13이 되어야 해서 1@12319!+1+13을 비밀번호에 입력해 보자.
Step2로 넘어가는 것에 성공했다.
이 역시 step2.php 코드에서 입력값에 대한 필터링이 적용되는 것을 확인할 수 있다.
// 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";
}
}
이를 유의해서 명령어를 작성해 보면,
cat ../dream/f?ag.txt
를 넣을 수 있다. 해당 command를 입력해 봤더니,
플래그 획득에 성공했다!
'SWUFORCE > 워게임 풀이' 카테고리의 다른 글
[Dreamhack] web-misconf-1 (web) (0) | 2024.05.14 |
---|---|
[Dreamhack] devtools-sources (web) (0) | 2024.05.14 |
[Dreamhack] php7cmp4re (web) (0) | 2024.05.07 |
[Dreamhack] Carve Party (web) (0) | 2024.05.01 |
[Dreamhack] simple-web-request (web) (0) | 2024.05.01 |