Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | |||||
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| 31 |
Tags
- loose comparison
- 웹
- WEB
- WhiteHatSchool
- session hijacking
- 타입 변환 취약점
- 화이트해커
- 화이트햇스쿨
- 한국정보기술연구원
- file download vulnerability
- 보안교육
- Cross Site Script
- type juggling
- 보안
- php
- webhacking
- WarGame
- cookie
- cybersecurity
- 웹해킹
- 워게임
- php7.4
- 드림핵
- dev-tools
- 정보보안
- web-misconf-1
- KITRI
- path traversal
- Dreamhack
- cookie tampering
Archives
- Today
- Total
xmi1e-vir.log
[Dreamhack] wargame 'phpreg' write-up 본문
🌱 Biginner
문제링크
php로 작성된 페이지입니다.
알맞은 Nickname과 Password를 입력하면 Step 2로 넘어갈 수 있습니다.
Step 2에서 system() 함수를 이용하여 플래그를 획득하세요.
플래그는 ../dream/flag.txt 에 위치합니다.
플래그의 형식은 DH{...} 입니다.
📌문제 파악
- 닉네임이랑 패스워드를 입력해서 제출하면 step2로 넘어간다/
<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>
- step1에서 step2로 넘어가는 부분
- 구체적으로는 if ($name === "dnyang0310" && $pw === "d4y0r50ng+1+13")를 참으로 만들어야 한다.
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);
# 이게 step2로 넘어가기 위한 조건
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";
}
?>
📌문제 풀이
STEP 1
주어진 식 if ($name === "dnyang0310" && $pw === "d4y0r50ng+1+13")는 다음 조건을 만족해야한다.
- 닉네임
- "nyang"이라는 문자열(대소문자 구분 없이)을 찾아 제거
- 따라서 "dnnyangyang0310"이라는 문자열을 입력하면 "nyang"부분이 지워지면서 dn[
nyang]yang0310 이렇게 우리가 원하는 닉네임이 된다.
- 비밀번호
- 비밀번호에 영문 알파벳이 미포함
- pw 패턴 /\d*\@\d{2,3}(31)+[^0-8\"]\!/을 d4y0r50ng로 치환
- \d*: 0개 이상의 숫자
- @: '@' 기호
- \d{2,3}: 2개 또는 3개의 숫자
- (31)+: '31'이 한 번 이상 반복
- [^0-8"]: 0부터 8까지의 숫자와 큰따옴표(")를 제외한 모든 문자
- !: '!' 기호
- 조건에 맞는 임의의 비밀번호를 작성하면 된다.
나는 "1@123319!+1+13"을 작성하였다.
STEP 2
- ../dream/flag.txt 로 이동하되, "flag"라는 글자는 없이 이동해야 하는것이 조건이다.
$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>";
}
먼저 pwd 명령을 통해 현재 디렉토리를 파악할 수 있었다.

cd .. && ls 명령을 통해 이전 디렉토리를 확인해보면, 우리가 찾고자 하는 dream 디렉토리가 위치하고 있다.

flag 필터링을 어떻게 우회 할것인가?
구글링을 했을때, 대다수의 블로그가 웹사이트 취약점에 대해서 다루고 있었는데 이 문제의 경우 리눅스 커맨드라인에 입력해야 하기 때문에 애를 많이 먹었다.
- 실패한 목록들
- 대문자로 바꾸기 → 우리가 우회하려는 preg_match()함수에서 /i 플래그를 통해 이를 막아두었다.
- cd ../dream && cat "$(printf '\x66\x6c\x61\x67').txt"
- cat /var/dream/"$(printf '\\x66\\x6c\\x61\\x67').txt"
→ 애초에 printf '\x66\x6c\x61\x67' 명령이 안먹히는 환경이다.
많은 삽질을 하다가 cat ../dream/fla""g.txt을 통해 풀어냈다.
preg_match('/flag/i', $input)은 "flag"라는 연속된 문자열을 찾기 때문에 이렇게 끊어주는 것 만으로도 간단하게 우회가 가능하다.
그러면 아무 문자로 끊으면 될까?
"로 끊을수 있었던 이유도 따로 있다.
- 셸(shell)에서 fla""g.txt는 완벽하게 붙여진 flag.txt로 인식한다.
- PHP 코드 내에서는 "fla" + 빈 문자열 "" + "g"를 붙여서 "flag"가 되는 형태이다.
그러나, 정규식에서는 문자열이 붙여진다고 이해하지 못하고 이를 각각의 문자열로 인식한다. 따라서 우회가 가능한 것이다.
결론적으로 플래그를 얻어낼 수 있었다.

[참고할 자료]
문제를 풀고 나서 다른 분이 푼 풀이를 보다가 내가 어렵게 푼 편이라는 것을 깨달았다.
따라서 더 쉽게 푸신 분들의 풀이를 함께 언급한다.
파일 이름인 flag를 직접 작성하지 않고서도 내용 출력이 가능
https://taesan-smj.tistory.com/61
이럴때는
을 이용하면 된다.
의 의미는 해당 파일 내부에서 모든 파일을 가져오라는 의미이므로cat ../dream/*.txt 를 입력하게 된다면, txt 확장자를 가지고 있는 경로에 있는 파일을 읽어오라는 뜻이다.
파일 이름의 일부만 입력해도 접근이 가능
https://koharinn.tistory.com/701
파일 이름의 일부를 * 처리해도 패턴에 매칭되는 파일이 있다면 접근이 가능하다.
'WARGAME > WEB' 카테고리의 다른 글
| [Dreamhack] wargame '🌱 simple-web-request' write-up (2) | 2025.09.12 |
|---|---|
| [Dreamhack] wargame 'Flying Chars' write-up (0) | 2025.09.11 |
| [Dreamhack] wargame 'ex-reg-ex' write-up (0) | 2025.09.07 |
| [Dreamhack] wargame 'pathtraversal' write-up (0) | 2025.09.07 |
| [Dreamhack] wargame 'Carve Party' write-up (0) | 2025.09.07 |