본문 바로가기

드림핵

[드림핵 워게임] phpreg

<문제>

 

<풀이>

- 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