<문제>
<풀이>
- step1
1. 코드 및 사이트 확인
문제 사이트에 접속하면 처음으로 보이는 페이지다. 닉네임과 패스워드를 입력하는 폼을 확인할 수 있다.
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";
}
step2.php 파일에서 코드를 확인해보자.
끝부분을 보면 $name(닉네임)이 "dnyang0310"이고 $pw(패스워드)가 "d4y0r50ng+1+13"일 때 step2가 열리는 것을 알 수 있다.
코드에서 확인한 대로 닉네임과 패스워드를 입력해보았다.
step2로 넘어가지 못하고 에러 메시지가 출력된다.
if (preg_match("/[a-zA-Z]/", $input_pw)) {
echo "alphabet in the pw :(";
}
코드를 확인해보면 위와 같이 패스워드에 들어가는 알파벳을 필터링하는 코드가 있다.
알파벳을 입력하지 않고 패스워드에 "d4y0r50ng+1+13"가 입력되도록 우회하는 방법을 찾아야 한다.
이후의 코드를 읽어보니 해결방법이 보였다.
$name = preg_replace("/nyang/i", "", $input_name);
$pw = preg_replace("/\d*\@\d{2,3}(31)+[^0-8]\!/", "d4y0r50ng", $input_pw);
preg_replace() 함수로 주어진 정규표현식을 만족하는 문자열을 다른 문자열로 치환하는 코드가 있다.
주어진 정규표현식을 자세히 살펴보면,
preg_replace("/nyang/i", "", $input_name) 은 $input_name 값에서 nyang이라는 문자열을 공백 문자열로 치환하는 기능을 한다.
이때 \i는 대소문자를 구분하지 않는다는 의미이다.
따라서 결과적으로 $name에 들어가야 하는 문자열이 "dnyang0310" 인데
이대로 입력하면 nyang이 공백 문자열로 치환되어 $name에 "d0310"으로 들어가게 되므로
$input_name에 "dnynyangang0310"를 입력하여 nyang이 공백문자열로 치환된 결과가 "dnyang0310"가 되도록 한다.
preg_replace("/\d*\@\d{2,3}(31)+[^0-8]\!/", "d4y0r50ng", $input_pw) 은 $input_pw 값에서 정규표현식을 만족하는 문자열을 "d4y0r50ng"로 치환하는 기능을 한다.
정규표현식을 뜯어보면,
\d* : 0개 이상의 숫자
\@ : 그냥 '@' 문자
\d{2,3} : 2자리 또는 3자리의 숫자
(31)+ : '(31)' 그룹을 1회 이상 반복
[^0-8] : 0부터 8까지의 숫자가 아닌 하나의 문자. 즉, 9
\! : 그냥 '!' 문자
따라서 주어진 정규표현식을 만족하는 "1@1231319!+1+13", "123@2313131!" 등의 문자열을 입력하면 해당 문자열이 "d4y0r50ng"로 치환된다.
$input_pw에 "1@1231319!+1+13"을 입력하여 치환된 결과가 "d4y0r50ng+1+13"가 되도록 한다.
2. 익스플로잇
찾아낸 값들을 입력했다.
3. step2 입장
step2가 열렸다.
- step2
1. 코드 및 사이트 확인
step2에서는 command 입력창을 확인할 수 있다.
$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>";
}
코드를 확인해보면, 입력창에 입력된 값을 $cmd 변수에 담아서
대소문자 구분없이 flag라는 문자열이 들어가면 Error!를 출력하고
그 조건문을 넘어가면 $cmd의 값을 시스템 명령어로 실행한 결과를 출력하는 것을 알 수 있다.
문제에서 플래그는 ../dream/flag.txt에 위치한다고 했으므로
시스템 명령어 cat ../dream/flag.txt 를 실행하면 flag.txt에 들어있는 flag값이 Output으로 출력될 것이다.
그런데 flag라는 문자열이 필터링되고 있으므로 우회해야 한다.
2. 익스플로잇
시스템 명령어에서 $(시스템 명령어) 는 $() 안에 있는 시스템 명령어를 실행한 결과로 치환된다.
따라서 cat ../dream/f$(echo la)g.txt 라는 익스플로잇 코드를 입력하면
$()안에 있는 echo la가 la로 치환되면서 결과적으로 cat ../dream/flag.txt 라는 명령어가 완성된다.
3. flag 획득
익스플로잇 코드 실행 결과 플래그가 출력되었다.
'드림핵' 카테고리의 다른 글
[드림핵 워게임] ex-reg-ex (0) | 2023.08.09 |
---|---|
[드림핵 워게임] Flying Chars (0) | 2023.08.09 |
[드림핵 워게임] cg-simple_sqli (0) | 2023.08.08 |
[드림핵 워게임] amocafe (0) | 2023.08.08 |
[드림핵 워게임] sql injection bypass WAF (0) | 2022.11.27 |