Wargame/Hack The Box

[HTB] Toxic Writeup

Vardy 2023. 4. 21. 00:21

 

주어진 페이지에 접근해보자.

 

소스코드를 분석해보자.

//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);

사용자에게 /www/index.html 이라는 경로 값을 serialize 한 값을 PHPSESSID 로 전달하고,

응답 역시 사용자의 PHPSESSID 값을 디코딩해서 unserialize 처리를 한다.

 

관련해서 조사해보니 여러 자료가 나왔다.

 

주어진 쿠키의 값을 base64 디코딩을 한 뒤 파일 경로를 /etc/passwd로 수정하고 s:11(/etc/passwd의 길이가 11임) 처럼 경로 길이 값도 맞춰 준후 다시 base64인코딩을 한 후에

해당 값을 쿠키에 적용시키니 LFI가 가능했다.

 

이후 해당 기법과 관련된 RCE 공격 구문이 있어서 시도를 해봤는데 잘 되지 않아서 다른 파일들을 둘러봤다.

 

nginx.conf 파일을 보니 로그 파일의 경로가 노출되어 있었다.

nginx.conf

user www;
pid /run/nginx.pid;
error_log /dev/stderr info;

events {
    worker_connections 1024;
}

http {
    server_tokens off;
    log_format docker '$remote_addr $remote_user $status "$request" "$http_referer" "$http_user_agent" ';
    access_log /var/log/nginx/access.log docker;
    ###### ..............................................(1)

    charset utf-8;
    keepalive_timeout 20s;
    sendfile on;
    tcp_nopush on;
    client_max_body_size 1M;

    include  /etc/nginx/mime.types;

    server {
        listen 80;
        server_name _;

        index index.php;
        root /www;

        location / {
            try_files $uri $uri/ /index.php?$query_string;
            location ~ \.php$ {
                try_files $uri =404;
                fastcgi_pass unix:/run/php-fpm.sock;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include fastcgi_params;
            }
        }
    }
}

 

로그 파일 경로를 읽기 위한 사전 작업을 해주고

 

조회해보았더니 서버 접근 로그가 나타났다.

 

로그에 php코드를 삽입 시킨 후 로그파일을 조회하여 RCE를 트리거 해보기로 했다. 처음에는 path에 payload를 작성해봤는데 인코딩때문에 유효하지 않았다.

 

로그 값을 관찰하다가, User-Agent의 값은 띄어쓰기가 있더라도 별도 인코딩 처리 없이 요청이 가능하며, 로그 파일에 그대로 반영된다는 것을 확인했다.

 

User-Agent에 최상위 경로의 파일 목록을 읽는 소스를 넣어서 요청을 한 후, 로그 파일을 다시 읽어보니 파일 목록이 나타났다.

(entrypoint.sh 파일에 flag 파일명에 난수값을 더하는 과정이 있었어서 파일명을 확인해야 했다.)

 

파일 명을 확인하고 해당 파일을 조회하여 플래그를 획득 할 수 있었다.

 

FLAG = HTB{P0i5on_1n_Cyb3r_W4rF4R3?!}

 

* log파일을 오염시키는 시나리오까지는 생각했는데 계속 RCE로 리버스쉘을 시도해보다가 시간이 매우 많이 끌렸다.. 로그 파일을 조금 꼼꼼히 봤으면 내 요청이 내 서버 IP가 그대로 반영이 되지 않기 때문에 역으로 리버스쉘도 어렵다는것을 빨리 깨달았을텐데.. 아쉬웠다.

반응형