01.11 c#使用Path.Combine的坑

最近有個文檔管理功能的項目上線,交給測試部測試後,反饋系統存在一個遍歷漏洞,竟然能遍歷出c盤的文件目錄,我去,經過跟蹤排查,原來是Path.Combine的原因,在工具類中的方法如下:


c#使用Path.Combine的坑


其中AppDomain.CurrentDomain.BaseDirectory為應用程序目錄,我的應用程序目錄是f:/wwwroot,按我們想法是,經過MapPath轉換後的路徑肯定是f:/wwwroot開頭的,但實際上不是這樣。

<code>string path=MapPath("//")/<code>

最後得到的結果是://

還有很多類似的坑,看下面的測試

測試1


c#使用Path.Combine的坑


//依次顯示的是:

\\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>


c#使用Path.Combine的坑


分享到:


相關文章: