2013-04-10 3 views
6

ローカルのSQL Expressデータベースの情報を更新するために作成したHTTPハンドラがあります。相対URIパスを防ぐために文字列を消化する

ユーザーは、相対URIパス "/../../file.zip"をクエリ文字列として使用することができ、制限された領域外のファイルをダウンロードできる可能性があることを認識しました。

サイトはまだライブではありませんので、セキュリティ上の問題はありませんが、このようなことは避けてください。

入力クエリから「..」を削除する単純なstring.replace行を追加しました。

これを保護するためにここで行うべきことがありますか?

public void ProcessRequest(HttpContext context) 
{ 
    string filesPath = "C:/Downloads/"; 
    string fileName = context.Request.QueryString["filename"]; 
    fileName = fileName.Replace("'", "''").Replace("..", "").Replace("/", "").Replace("\\", ""); 

    if (!string.IsNullOrEmpty(fileName) && File.Exists(filesPath + fileName)) 
    { 
     context.Response.ContentType = "application/octet-stream"; 
     context.Response.AddHeader("Content-Disposition", string.Format("attachment; filename=\"{0}\"", fileName)); 
     context.Response.WriteFile(filesPath + fileName); 
     //Do work to update SQL database here 
    } 
    else 
    { 
     context.Response.ContentType = "text/plain"; 
     context.Response.Write(filesPath + fileName + " Invalid filename"); 
    } 
} 
+1

一般的に、有害なシーケンスを削除しようとするのではなく、無効な入力を拒否するべきです。あなたの置き換えが './ 'に何をするのかを考えてください。空のファイル名、先頭と末尾のドットとスペース、制御文字、 'SHORTN〜1.AME'と潜在的に予約されたファイル名(' com1'など)のような奇妙さを引き起こすパターンがたくさんあります。ファイル名に入力を使用することは、特にWindows(特に、Windows)(http://msdn.microsoft.com/en-gb/library/windows/desktop/aa365247(v = vs.85).aspx)では難しくなります。 (Jasonが示唆しているように)ローカルディスク上のファイル名に生成されたIDを使用することができれば。 – bobince

+0

@bobinceそこに大きなヒント。これが私が質問した理由です。私がこのアプローチにもっと良い方法があることを知っていたので、私はちょうどこのような重要な問題について少しの指針を探していました。 –

答えて

10

私は通常、この問題をチェックするために、この単純なコードを使用します。

private string getPath(string basePath, string fileName) 
{ 
    var fullPath = System.IO.Path.GetFullPath(System.IO.Path.Combine(basePath, fileName)); 
    if (fullPath.StartsWith(basePath)) 
     return fullPath; 
    return null; 
} 

目標(それがコンパイルされないことがありので、私はそれはあなたのアイデアを与えることだけだ、それを直接入力します) Path.GetFullPathを使用することです。このメソッドは、/../などを完全なパスに変換します。次に、返されたパスが許可されたディレクトリにあることを確認します。
は、この方法が予想よりslighty異なるパスは、あなたがRequest.QueryString["filename"]は、実際にファイルを表し鍵となる可能性があり、詳細な説明

+1

私はこのアプローチの背後にある考え方が好きです。システムが開いているファイルを教えて、それが有効であることを確認しましょう。あなたがファイル名で文字や文字列をブラックリストに載せようとすると、間違いなく何かが見逃されます。 –

+0

素晴らしいアイデアもここにあります。これは私が元々やろうとしていたものでしたが、私は正しい方法を見つけることができませんでした。 GetFullPathは私が見つけられなかったメソッドです。 –

2

ためMSDNを読んで戻っていることを気をつけてください。ユーザーがファイルキーを簡単に推測できるようにしたくない場合は、キーを数字またはランダムな文字列にすることができます。マッピングをデータベースに保存し、そのキーを使用してローカルファイル名を取得することができます(2つのファイルを区別して実装の詳細を隠す場合は、ファイル名を表示することもできます)。

+0

これは私が思うにはこれを行う最も良い方法ですが、私の元の質問に答えたので、私は@Fabskeの答えをマークアップしました。私はこれをどうやって行うのかはわかりませんが、私はこのアプローチを使うことに目を向けます。 –