最近有個文檔管理功能的項目上線,交給測試部測試後,反饋系統存在一個遍歷漏洞,竟然能遍歷出c盤的文件目錄,我去,經過跟蹤排查,原來是Path.Combine的原因,在工具類中的方法如下:
其中AppDomain.CurrentDomain.BaseDirectory為應用程序目錄,我的應用程序目錄是f:/wwwroot,按我們想法是,經過MapPath轉換後的路徑肯定是f:/wwwroot開頭的,但實際上不是這樣。
<code>string path=MapPath("//")/<code>
最後得到的結果是://
還有很多類似的坑,看下面的測試
測試1
//依次顯示的是:
\\p12
\\p13\\
/p13/
\\p12
\\p13\\
/p13/
得出一個結論是:
1、path2 不能以 \\ 和 / 開頭的字符串, 如果是這個字符串開頭的,則返回 path2
測試2
還有很多類似的坑,看下面的測試
<code>Path.Combine("C:\\11", "D:\\aa.txt");/<code>
得到結果是:@"D:\\aa.txt"
得出結論:
如果 path2 包含絕對路徑,則該方法返回 path2。
當然可能還有其他坑,我這裡懶得一個個測試,為了保證安全,自己寫一個Combine更放心一點,分享我寫的方法,起碼可以保證得到的結果是第一個參數開頭的,代碼如下:
<code>public static string Combine(params string[] paths)
{
if (paths.Length == 0)
{
throw new ArgumentException("please input path");
}
else
{
StringBuilder builder = new StringBuilder();
string spliter = "\\\";
string firstPath = paths[0];
if (firstPath.StartsWith("http://", StringComparison.OrdinalIgnoreCase) || firstPath.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
{
spliter = "/";
}
if (!firstPath.EndsWith(spliter))
{
firstPath = firstPath + spliter;
}
builder.Append(firstPath);
for (int i = 1; i < paths.Length; i++)
{
string nextPath = paths[i];
if (nextPath.StartsWith("/") || nextPath.StartsWith("\\\"))
{
nextPath = nextPath.Substring(1);
}
if (i != paths.Length - 1)//not the last one
{
if (nextPath.EndsWith("/") || nextPath.EndsWith("\\\"))
{
nextPath = nextPath.Substring(0, nextPath.Length - 1) + spliter;
}
else
{
nextPath = nextPath + spliter;
}
}
builder.Append(nextPath);
}
return builder.ToString();
}
}/<code>
閱讀更多 鵝是程序猿 的文章