2009-08-24 10 views
1

ユーザー入力を受け付けないようにして、ファイルを読み書きするパスを選択することを強く推奨します。しかし、あなたが保持したいベースディレクトリ(例えばftpフォルダのルート)を持っていると仮定すると、与えられたユーザ入力がそのフォルダ内に私たちを保持するようにするにはどうすればよいですか?例えばサブディレクトリ内のユーザー入力ファイルパスを安全に実施

Path.Combine(_myRootFolder、_myUserInput)

はまだ_myRootFolderの外で私たちを取ることができます。そして、これはまた、危険な可能性があり

NEWPATH = Path.Combine(_myRootFolder、_myUserInput) (newPath.StartsWith(_myRootFolder)) ...

は「/バック/に/ myrootfolder /のようなものを与えられている場合。 ./../and/out/again "と入力します。これのための戦略は何ですか?私が使用することができますblindingly明白な.NETメソッドが欠けていますか?

答えて

4

ASP.NETアプリケーション内では、生成されたパスがアプリケーションルート外にある場合に例外をスローするServer.MapPath(filename)を使用できます。

あなたが望むのは安全なファイル名で、そこにすべてのファイルを入れたいだけならもっと簡単になります。

FileInfo file = new FileInfo(
     Server.MapPath(
      Path.Combine(@"c:\example\mydir", filename))); 

あなたがASP.NETの外にいる場合は、Path.GetFullPathを使用できます。

string potentalPath = Path.Combine(@"c:\myroot\", fileName); 
if (Path.GetFullPath(potentialPath) ! = potentialPath) 
    // Potential path transversal 

または、Path.GetFullPathを呼び出して、ロック先のディレクトリと一致する開始点を確認します。

+0

ええ、それは私が望む機能の一種です...私は残念なことに、ある場所から別の場所に複数のファイルをバッチでアップロードするWindowsサービスで残念です。 –

+0

別のアプローチを追加しました – blowdart

+0

クール - ありがとう - GetFullPathは行く方法のように見えます:) –

-1

入力文字列を解析し、../を正規表現で切り取ることができます。

+1

しかしパスショートカットの私自身の知識に頼っている私は何を避けるために願っています。 「../」は確かに道を上がる唯一の方法ですか?たとえば、奇妙なUnicode文字でエンコードするURLタイプのトリックを行うことはできますか?ファイルパスが完全にエスケープされた後、チェックを行うのは可能でしょうか? –

0

FTPサーバーの例では、ユーザーがホームディレクトリとアクセス許可を適切に設定して、フォルダから移動できないようにする必要があります。あなたがそれをすることができない理由は何ですか?

1

私は(私はこのかかわらをテストしていない)Path.FullPathは何が必要でしょうと信じて:

string newPath = Path.Combine(_myRootFolder, _myUserInput); 
string newPath = Path.FullPath(newPath); 
if (newPath.StartsWith(_myRootFolder)) ... 
1

私が知っている、このスレッドは静かな古いですが、でコードを書いてから、次の読者を防ぐためにすることを潜在的なセキュリティエラー、私は指摘する必要があると思う、arg2が直接ユーザーの入力に基づいている場合Path.Combine(arg1, arg2)を使用して保存されません。 arg2が「C:¥Windows¥System32¥cmd.exe」の場合、arg1パラメータは完全に無視され、APIまたはサーバーアプリケーションのユーザーにファイルシステム全体への完全なアクセス権が与えられます。

この方法を使用する際は十分注意してください。

私は(私の知る限り)、セキュアである必要があり、この解決策を考え出した:

public static string SecurePathCombine(params string[] paths) 
    { 
     string combinedPath = ""; 

     foreach (string path in paths) 
     { 
      string newPath = Path.Combine(combinedPath, path); 

      if (!newPath.StartsWith(combinedPath)) 
       return null; 

      combinedPath = newPath; 
     } 

     if (Path.GetFullPath(combinedPath) != combinedPath) 
      return null; 

     return combinedPath; 
    } 
関連する問題