Path.Combineの安全なバージョン
-
03-07-2019 - |
質問
信頼する rootPath
と、信頼しない relativePath
があります。結果が rootPath
の下にあること、およびユーザーが ..
を使用して開始を戻すことができないように、それらを結合したいポイント。次のようなものを許可する相対パスをします: hello \ .. \ world
== world
解決
展開するには、Path.Combineを使用し、結果に対してGetFullPathを呼び出し、その結果がrootPathで始まることを確認します。
ハードリンクからは保護されませんが、二重ドットなどの単純なものをキャッチする必要があります。
上記のコード:
string Resolve(string fileName)
{
string root = FileRoot();
string ret = Path.GetFullPath(Path.Combine(root, fileName));
if (ret.StartsWith(root.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar)) return ret;
throw new ArgumentException("path resolved to out of accesable directroy");
}
他のヒント
Path.GetFullPath()
を呼び出して、信頼できる rootPath
で始まるかどうかを確認できます。妄想する傾向がある場合は、 rootPath
がルート化されていることも確認してください。
public Boolean IsPathSafe(String rootPath, String relativePath)
{
return rootPath.EndsWith(Path.DirectorySeparatorChar.ToString()) &&
Path.IsPathRooted(rootPath) &&
Patch.Combine(rootPath, relativePath).GetFullPath().StartsWith(rootPath);
}
最初のテストの説明については、テクノフィルの答えに関するAlex Martelliのコメントを参照してください。
できることの1つは、バックスラッシュ( \
)と二重ドット( ..
)の数を数えることです。ドットはバックスラッシュの数よりも小さいです。フォルダ構造内の rootPath
の上に移動するには、少なくとも二重ドットと同じ数のバックスラッシュが必要です。したがって、少なくとも relativePath
のみを許可する場合は、もう1つバックスラッシュを使用すると、安全になります。
所属していません StackOverflow