프롤로그
1주일간, 무선통신과 AES 암호학에 대해서 되게 심도있게 공부하고, 그것으로 발표자료를 준비하느라 좀 블로그에 신경을 못 썼다. 오늘 일단 발표자료는 다 완성이 되어서 이제 웹 해킹 마저 공부했던 거 계속 문제를 풀어보자.
문제
문제 코드
<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>
STEP1
<?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";
}
?>
즉 여기에만 우리는 관심을 가지면 된다.
우선 홈페이지 접속을 해보자.
step1에서는 아이디와 비밀번호를 접속해야 step2 로 넘어갈 수 있다.
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>';
코드를 보면, input_name과 input_pw 부분에 각자 입력을 받는데,
name = dnyang0310, pw = d4y0r50ng+1+13 이면 step 1을 해결할 수 있다.
저대로 입력을 하려고 할때, name 부분에서는 nyang 단어가 입력되어있는 부분은 공백으로 바뀌고, 비밀번호 부분에서는 [a-zA-Z] 즉 영어가 들어가있는 순간 오류가 뜨게 되어있다.
아니 이게 무슨 말이야. dnyang0310 을 입력하면 nyang가 포함되어있으니까 d0310만 남게 되고 그러면 아이디를 입력을 할 수가 없고,
비밀번호는 d4y0r50ng 인데, 영어가 있으면 안 되는 상황이다. 즉 영어를 입력하면 오류가 난다니! 이 무슨 ...
이 step1 과정을 뚫을려면 저 아이디와 비밀번호를 뚫을 수 있게 우회하는 방법을 찾아야겠다.
내가 생각한 방법은, nyang 단어가 사라지니까, 저 단어 양 뒤로 dnyang0310을 분할해서 채워넣는 방법이다.
dnnyangyang0310 을 아이디로 입력하면 nyang 부분은 중간에 한 번 없어지고 뒤쪽은 살아남지 않을까 싶다.
이제 비밀번호를 분석해보자.
$pw = preg_replace("/\d*\@\d{2,3}(31)+[^0-8\"]\!/", "d4y0r50ng", $input_pw);
나는 php 코드를 잘 모르기 때문에 전지전능하신 GPT 님께 저 코드를 물어보았다.
d* | 숫자가 0개 이상 |
@ | @가 있어야한다. |
d{2, 3} | 숫자가 2개 또는 3개 |
(31) | 31이 한 번 이상 반복 |
+[^0-8\"] | 0~8이 아님 |
! | !가 들어감. |
즉 조합해보면 숫자@숫자1숫자2319! 이렇게 들어가게 된다면 d4y0r50ng 로 바뀌게 될 것이다.
비밀번호는 d4y0r50ng+1+13 인 것을
if ($name === "dnyang0310" && $pw === "d4y0r50ng+1+13") {
여기 코드에서 진작헤 확인하였으므로, d4y0r50ng로 바뀌도록 무언가 작업하고 뒤에 +1+13으로 바꿔주면 된다.
위에 표에 해당하게 아무렇게나 입력해보자.
123@1231319!+1+13 을 입력해보자.
즉 id = dnnyangyang0310, pw = 123@1231319!+1+13 를 입력해보자.
그리고 제출을 누르면
step2 로 잘 넘어온 것을 확인할 수 있다.
step2
그 다음 step2의 코드를 확인해보자.
문제에서 분명 system함수를 사용해서 내부에 있는 ../dream/flag.txt 파일을 확인해보라고 했다.
파일을 읽는 명령어는 cat. 즉 cat ../dream/flag.txt 를 입력하면 될 것이다 라고 생각을 일단 깔고간다.
근데 하나 걸리는 점은
// cmd filtering
else if (preg_match("/flag/i", $cmd)) {
echo "<pre>Error!</pre>";
}
이 코드가 하나 껴있다는 것. flag 라는 단어를 입력하게 되면 Error! 가 된다는 것이다.
else{
echo "<pre>--Output--\n";
system($cmd);
echo "</pre>";
}
}
command 까지는 입력 안 해도 되고
cat ../dream/flag.txt 에서 flag 단어를 빼고 해당 파일을 어떻게 출력할 수 있는가를 찾아야하는데,
이럴때는 *을 이용하면 된다. *의 의미는 해당 파일 내부에서 모든 파일을 가져오라는 의미이므로
cat ../dream/*.txt 를 입력하게 된다면, txt 확장자를 가지고 있는 경로에 있는 파일을 읽어오라는 뜻이다.
실행해보면
flag 가 잘 출력되었다.
flag는
DH{ad866c64dabaf30136e22d3de2980d24c4da617b9d706f81d10a1bc97d0ab6f6}
이다.
에필로그
1주일만에 해서 감 다 죽었다고 생각했는데, 매우 쉬운 난이도라 그런가 죽지는 않았다. 다시 이론 공부할뻔;;
'보안 스터디 > 웹 해킹' 카테고리의 다른 글
[드림핵/워게임] sql injection bypass WAF (웹 해킹) (2) | 2024.09.16 |
---|---|
[드림핵/워게임] session (웹 해킹) (1) | 2024.01.27 |
[드림핵/워게임] web-ssrf (웹 해킹) (0) | 2024.01.16 |
[드림핵/웹해킹] ServerSide: SSRF (0) | 2024.01.16 |
[드림핵/워게임] image-storage (웹 해킹) (1) | 2024.01.15 |