파일 업로드 / 다운로드 하는 기능에서 발생할 수 있는취약점들과 취약점으로부터 안전하게 구현할 수 있는 방법.
- 파일 업로드 취야점
- 서버의 파일 시스템에 사용자가 원하는 경로 또는 파일 명 등으로 업로드가 가능하여 악영향을 미칠 수 있는 파일이 업로드 되는 취약점
- 파일 다운로드 취약점
- 서버의 기능구현 상의도하지 않은파일을 다운로드할 수 있는 취약점
file upload code
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()
악의적 요청
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--
이름에 ../ 를 심음
Server File System
$ 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
upload 디렉토리를 벗어나서 저장됨.
File Upload
CGI ( Common Gateway Interface)
사용자의 요청을 받은 서버가 동적인 페이지를 구성하기 위해 엔진에 요청을 보내고 엔진이 처리한 결과를 서버에게 반환하는 기능을 말한다.
웹 서버는 Apache, 웹 어플리케이션은 php를사용하는서버에 사용자가 요청을 보내면 Apache는 사용자의 요청을 해석하고 사용자가 요청하는 리소스의 확장자가 .php와 같이 php엔진을 사용하기로 설정되어 있는 확장자라면
mod_php (CGI) 를 통해 사용자의 요청을 php 엔진이 처리 및 실행하도록 요청함.
ex) Apache 설정 파일
<FilesMatch ".+\.ph(p[3457]?|t|tml)$">
SetHandler application/x-httpd-php
</FilesMatch>
.php 확장자 외에도 .ph ~~ 등의 확장자는 php에서 처리하도록 핸들링 되어있음.
Python의 flask, django 와 Nodejs의 express 등은 서버,CGI,웹 어플리케이션 등이 통합된 프레임워크입니다. 미리 라우팅 된 경로에만 접근이 가능하도록 설정하여 서비스 됨.
웹 서비스가 동작하는 경로에 원하는 파일 내용과 파일명을 업로드 할 수 있다면 서버가 엔진에 요청하는 확장자를 업로드하여 서버의 웹 어플리케이션에 원하는 코드 실행가능.
웹 어플리케이션이 실행하는 코드를 악의적인 공격자가 조작할 수 있다면 웹 어플리케이션 언어에 내장딘 OS 명령어 등 사용가능. 해당 서버의쉘을 웹을 통해 사용한다고 하여 WebShell 이라는 악성코드 등장.
<?php
if(!empty($_FILES['file'])){
$filename = generateRandomString(); // custom function
$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
}
}
?>
파일 이름에 .html 확장자 ,내용에 <script></script>로 Stored XSS 가능.
아니면 .php 확장자로 php 코드실행가능
CGI로 php 확장자는 php에서 처리하도록 핸들링 되어있기 때문
File Download
사용자가 입력한 파일이름을 검증하지 않는 경우.
@app.route("/download")
def download():
filename = request.args.get("filename", "")
return open("uploads/" + filename, "rb").read()
http://example.com/download?filename=docs.pdf 같은 정상적인 파일 다운로드 요청이 아닌,
http://example.com/download?filename=../../../../etc/passwd처럼 다른 경로에 접근하여 시스템 계정 파일 다운로드 가능
파일 다운로드 취약점을 막기 위해서는 기본적으로 인자에 다운로드 받으려는 파일의 경롸 이름을 넘기지 않는것이 좋음.
.. / \\ 같은 값을 적절히 필터링 해야함.
하지만 ../ 값을 단순히 filename = filename.replace("../", "") 같은 방식으로 없애면 ..././file에서 ../가 삭제되어 ../file이 되는 형식으로 우회가능.
윈도우는 ..\\ 으로도 ../ 대신 사용가능하므로 둘다 필터링 해야함.
'Security' 카테고리의 다른 글
[wargame] xss-1 (0) | 2021.09.25 |
---|---|
[wargame] csrf-2 (0) | 2021.09.25 |
[Webhacking] server side request forgery (SSRF) (0) | 2021.09.24 |
[Webhacking] path traversal (0) | 2021.09.24 |
[Webhacking] server side template injection (SSTI) (0) | 2021.09.24 |