0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

「バリデーションしてるから安全」は危険だった話

0
Last updated at Posted at 2026-05-11

要約

  • 「ユーザー入力」でのファイル名生成が、そもそも非推奨
  • 正規表現での、バリデーションチェックでは不十分
  • 静的解析ツールは設計レベルを見ている
  • Replaceのような細かい実装も注意が必要

背景

ASP Classic / VBScript の既存システム
これらをセキュアコーディングする際に引っかかった内容になります。

正確には、CSVダウンロード改修にて
動的なファイル名出力を行う際エスケープ処理で対応した場合
にひっかかりました。

動的な命名箇所

CSVダウンロード機能を改修していた際、
ユーザーが任意にファイル名を指定できる仕様でした。

Dim fileName
fileName = Request.Form("fileName")

Request.Formから受け取った値をファイル操作に使うと
Path Traversalのリスクがあります

そもそも、Path Traversalとは

../

../ を利用して上位ディレクトリへ移動し、
本来アクセスできないディレクトリへ移動する攻撃です。

/download?file=../../web.config

例えば、
ユーザー入力で動的にファイル名を作る場合上記のような入力が通ると

  • 設定ファイル
  • DB接続情報
  • システム内部ファイル

などが漏洩する可能性があります。

最初の対策:正規表現によるバリデーション

Function CheckFileName(strFileName, strExt)

    Dim reg, strBaseName

    Set reg = New RegExp
    reg.global = true
    reg.Pattern = "^[a-zA-Z0-9_]+$"

    ' 拡張子を除去
    strBaseName = Replace(strFileName, strExt, "")

    If (reg.Test(strBaseName)) Then
        CheckFileName = strBaseName & strExt
    Else
        Response.Write "Invalid file name"
        CheckFileName = ""
    End If

End Function
  • ../
  • /
  • .
  • \

この内容で、上記は弾けるため十分と思い
解析ツールに回した結果NGを受けました。

なぜNGなのか?

Request.Form → ファイル操作

というデータフローそのものが危険と判定されていたためです。

静的解析ツールの観点では、

  • 今は安全でも
  • 将来コード変更される可能性がある
  • チェック漏れが発生するかもしれない

という前提で判定します。

つまり、

ユーザー入力をファイル処理に使っている

という設計自体がリスク扱いになります。

セキュアコーディングの方向性

危険な入力を使わない

というのが前提にあるため、ツールで引っかかる内容になりました。

Replaceの使い方にも注意点が

今回のバリデーションで期待していたことは、
拡張子を除いた部分が安全かのチェックでした。
→除去した結果として、安全化の判定を行ってました。

strBaseName = Replace(strFileName, strExt, "")

Replace は一致した文字列をすべて削除します。

test.csv.csv

そのため、上記のような入力に対して、
意図しない除去が発生する可能性があります。

正しい拡張子除去方法

末尾だけを安全に除去するなら、こちらの方が安全になります。

If Right(strFileName, Len(strExt)) = strExt Then
    strBaseName = Left(strFileName, Len(strFileName) - Len(strExt))
End If

最終的な解決策

ユーザー入力を使わず、下記で対処するという結論に至りました。

  • サーバー側で安全なファイル名を生成
  • Sessionに保存
  • CSV出力時はSessionから取得
fileName = Session("CsvFileName")
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?