C# .Net

[Checkmarx弱掃處理] - Path traversal、Heap Inspection

蔡麒聰 2019/08/08 16:11:29
208

一、前言

      日前在專案開發中,業主使用Checkmarx的原始碼檢測工具對應用程式進行檢測,在檢測結果發現了幾項安全性漏洞,摘要如下圖所示:

      其中大部分是引用的JavaScript所造成的,實際因為專案程式造成的漏洞主要是Path TraversalHeap Inspection這兩項,以下將說明這兩項漏洞的成因及如何解決。

 

二、Path Traversal

       下圖中是Path Traversal的檢測結果圖,引起問題的是GetTempFilePath方法,GetTempFilePath會回傳一個檔案路徑

 

成因

       Path Traversal的成因是指當存取檔案的路徑是透過使用者輸入或是組合字串而成,即可能讓使用者任意決定檔案路徑,進而可對任意路徑的檔案進行存取或刪除等攻擊。

       一個簡單的範例程式如下所示

public ActionResult TestFile(string fileName)
{
    //App_Data目錄
    string dirPath = Server.MapPath("~/App_Data");
    //組路徑字串
    string filePath = Path.Combine(dirPath, fileName);
    if (System.IO.File.Exists(filePath))//檔案存在的話
    {
        //原本預期下載Excel檔
        return File(filePath, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", fileName); 
    }
    else
    {
        return Content("not exists");
    }
}

        由前端輸入的fileName參數,在未過濾的情況下,可透過輸入fileName=../Web.config來取得Web.config。示範結果如下:

 

解決方法

       簡單的解決方法,是對檔案路徑的斜線及點符號進行過濾,將fileNameReplace對斜線及點符號過濾,程式碼如下

public ActionResult TestFile(string fileName)
{
    fileName = fileName.Replace("/", "").Replace("..", "");
    string dirPath = Server.MapPath("~/App_Data");
    string filePath = Path.Combine(dirPath, fileName);
    if (System.IO.File.Exists(filePath))
    {
        return File(filePath, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", fileName); 
    }
    else
    {
        return Content("not exists");
    }
}

       再重新執行,結果如下

 

三、Heap Inspection

       Heap Inspection的檢測結果如下圖所示:

 

成因

      將敏感性資料(身分證號、密碼)儲存在 String 物件中,無法確實的由記憶體中清除。

      因 String 物件為不可變,只能透過程式語言的記憶體回收機制(Garbage Collection,GC)進行清除,但 String 物件即使不再使用,也不一定會馬上會被GC回收,也就是說我們無法確保敏感性資料是被清除,還是仍留在記憶體中。在應用程式意外結束時,應用程式的記憶體傾印即可能洩露敏感性資料;或是透過某些工具,也可以取得應用程式在記憶體中的資料。

 

解決方法

      有一個簡單的方法可以解決問題,就是用 Char[] 取代 String。但在 .Net 應用程式,提供了 System.Security.SecureString 類別讓我們使用,SecureString 的資料在記憶體中是加密的,且可設為唯讀,避免被修改。我們可用 SecureString 保存保敏感性資料,以減少機密資料在記憶體中的時間,降低被竊取的風險。

    String 與 SecureString 之間的轉換函數如下

private static SecureString getPwdSecurity(string value)
{
	SecureString result = new SecureString();
	foreach (char c in value)
	{
	    result.AppendChar(c);
	}

	return result;
} 

private static string SecureStringToString(SecureString value)
{
	IntPtr valuePtr = IntPtr.Zero;
	try
	{
		valuePtr = Marshal.SecureStringToGlobalAllocUnicode(value);
		return Marshal.PtrToStringUni(valuePtr);
	}
	finally
	{
		Marshal.ZeroFreeGlobalAllocUnicode(valuePtr);
	}
}

 

      在解決專案件的Hepa Inspection,把引起問題的函數改為如下

public static byte[] SetSecurity(byte[] content, SecureString ownerPassword, SecureString newOwnerPassword,
SecureString newUserPassword, bool canPrint, bool canCopy)
{
    //do something
}

 

      將 String 改為 SecureString 來解決此問題。

 

參考資料:

[ASP.net MVC/資安] 如何防範Path Traversal目錄瀏覽漏洞

[Checkmarx掃描漏洞處理] - Path traversal

[.NET]Privacy Violation: Heap Inspection(Security Features, Data flow)

Heap Inspection - Fortify Taxonomy

Secure Password Strings in Java and C#

SecureString Class

蔡麒聰