當程式被原始碼安全檢測工具掃出「Path Manipulation」的 issue ,要怎麼辦呢?
有時程式中操作檔案會依QueryString或是某個TextBox的值來決定要Copy還是要Delete。
但這樣的做法會被原始碼安全檢測工具掃出「Path Manipulation(Input Validation and Representation, Data flow)」的 issue !
以下用範例來說明,
WebForm1.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs"
Inherits="WebApplication1.WebForm1" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox ID="txtFileName" runat="server" Text="README.TXT"></asp:TextBox>
<!-- File Delete -->
<asp:Button ID="Button1" runat="server" Text="DeleteFile_1" OnClick="Button1_Click" />
<asp:Button ID="Button2" runat="server" Text="DeleteFile_2" OnClick="Button2_Click" />
<!-- File Copy -->
<asp:Button ID="Button3" runat="server" Text="CopyFile_1" OnClick="Button3_Click" />
<asp:Button ID="Button4" runat="server" Text="CopyFile_2" OnClick="Button4_Click" />
</div>
</form>
</body>
</html>
WebForm1.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
namespace WebApplication1
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
//假如我們的Web AP下有Data目錄
string dataFolderPath = Server.MapPath(@"~\Data\");
string fileName = txtFileName.Text;
string deleteFilePath = Path.Combine(dataFolderPath, fileName);
if (File.Exists(deleteFilePath))
File.Delete(deleteFilePath);
}
protected void Button2_Click(object sender, EventArgs e)
{
//假如我們的Web AP下有Data目錄
string dataFolderPath = Server.MapPath(@"~\Data\");
string fileName = txtFileName.Text;
DeleteFile(dataFolderPath, fileName);
}
void DeleteFile(string folderName, string delFileName)
{
foreach (string fullFileName in Directory.EnumerateFiles(folderName))
{
string fileName = Path.GetFileName(fullFileName);
if (delFileName.ToUpper() == fileName.ToUpper())
{
File.Delete(fullFileName);
}
}
}
protected void Button3_Click(object sender, EventArgs e)
{
//假如我們的Web AP下有Data目錄
string dataFolderPath = Server.MapPath(@"~\Data\");
//假如我們的Web AP下有Temp的目錄
string tempFolderPath = Server.MapPath(@"~\temp\");
string fileName = txtFileName.Text;
string tempFile = Path.Combine(tempFolderPath, fileName);
string dataFile = Path.Combine(dataFolderPath, fileName);
if(File.Exists(tempFile))
File.Copy(tempFile, dataFile, false);
}
protected void Button4_Click(object sender, EventArgs e)
{
//假如我們的Web AP下有Data目錄
string dataFolderPath = Server.MapPath(@"~\Data\");
//假如我們的Web AP下有Temp的目錄
string tempFolderPath = Server.MapPath(@"~\temp\");
string fileName = txtFileName.Text;
CopyFile(tempFolderPath, dataFolderPath, fileName);
}
void CopyFile(string sourcePath, string destPath, string fileName)
{
//假如我們的Web AP下有Data目錄
foreach (string fullFileName in Directory.EnumerateFiles(sourcePath))
{
string sourceFileName = Path.GetFileName(fullFileName);
if (fileName.ToUpper() == sourceFileName.ToUpper())
{
string destFilePath = Path.Combine(destPath, sourceFileName);
File.Copy(fullFileName, destFilePath, true);
}
}
}
}
}
先來看看 Delete 檔案的部份,如 Button1_Click Method,
//假如我們的Web AP下有Data目錄
string dataFolderPath = Server.MapPath(@"~\Data\");
string fileName = txtFileName.Text;
string deleteFilePath = Path.Combine(dataFolderPath, fileName);
if (File.Exists(deleteFilePath))
File.Delete(deleteFilePath);
刪除的檔案是從畫面上的TextBox(txtFileName.Text)而來的,所以它是 不可靠,有風險 的!
所以這時,原始碼安全檢測工具就會賞你「Path Manipulation Critical issue」。
那要如何修正呢?
把握一個原則,針對檔案操作,不能使用 有風險的檔名 ,這樣就可以了!
所以新增一個刪除檔案的 Method ,然後拿 有風險的檔名 跟某個目錄裡的檔案去比較,有找到的話,再針對找到的檔名操作就可以了,如下,
void DeleteFile(string folderName, string delFileName)
{
foreach (string fullFileName in Directory.EnumerateFiles(folderName))
{
string fileName = Path.GetFileName(fullFileName);
if (delFileName.ToUpper() == fileName.ToUpper())
{
File.Delete(fullFileName);
break;
}
}
}
請注意,我們是針對 fullFileName 操作哦!
所以使用的話,就改成如 Button2_Click Method 的內容,如下,
//假如我們的Web AP下有Data目錄
string dataFolderPath = Server.MapPath(@"~\Data\");
string fileName = txtFileName.Text;
DeleteFile(dataFolderPath, fileName);
Copy 檔案,如 Button3_Click Method 內容,在 File.Copy 及 File.Exists 都會有「Path Manipulation issue」,如下,
//假如我們的Web AP下有Data目錄
string dataFolderPath = Server.MapPath(@"~\Data\");
//假如我們的Web AP下有Temp的目錄
string tempFolderPath = Server.MapPath(@"~\temp\");
string fileName = txtFileName.Text;
string tempFile = Path.Combine(tempFolderPath, fileName);
string dataFile = Path.Combine(dataFolderPath, fileName);
if(File.Exists(tempFile))
File.Copy(tempFile, dataFile, false);
所以,這時操作也是要讓它操作 沒風險的檔案名稱 ,所以新增一個 CopyFile Method,來比較,並負責Copy File,如下,
void CopyFile(string sourcePath, string destPath, string fileName)
{
//假如我們的Web AP下有Data目錄
foreach (string fullFileName in Directory.EnumerateFiles(sourcePath))
{
string sourceFileName = Path.GetFileName(fullFileName);
if (fileName.ToUpper() == sourceFileName.ToUpper())
{
string destFilePath = Path.Combine(destPath, sourceFileName);
File.Copy(fullFileName, destFilePath, true);
break;
}
}
}
所以使用的話,就改成如 Button4_Click Method 的內容,如下,
//假如我們的Web AP下有Data目錄
string dataFolderPath = Server.MapPath(@"~\Data\");
//假如我們的Web AP下有Temp的目錄
string tempFolderPath = Server.MapPath(@"~\temp\");
string fileName = txtFileName.Text;
CopyFile(tempFolderPath, dataFolderPath, fileName);
以上是筆者的解法,如果有其他的方式,也請讓我知道哦!
2014/03/27 補充使用LINQ去Search File,如下,
void DeleteFileLINQ(string folderName, string delFileName)
{
var searchFile = (from f in Directory.EnumerateFiles(folderName)
where Path.GetFileName(f).ToUpper() == delFileName.ToUpper()
select f).FirstOrDefault();
if (!string.IsNullOrEmpty(searchFile))
File.Delete(searchFile);
}
void CopyFileLINQ(string sourcePath, string destPath, string fileName)
{
//假如我們的Web AP下有Data目錄
var sourceFile = (from f in Directory.EnumerateFiles(sourcePath)
where Path.GetFileName(f).ToUpper() == fileName.ToUpper()
select f).FirstOrDefault();
if (!string.IsNullOrEmpty(sourceFile))
{
string sourceFileName = Path.GetFileName(sourceFile);
string destFilePath = Path.Combine(destPath, sourceFileName);
File.Copy(sourceFile, destFilePath, true);
}
}
參考資料
Input Validation and Representation Server.HtmlEncode Replace Tool
Fortify白箱測試Critical issue: Path Manipulation
Hi,
亂馬客Blog已移到了 「亂馬客 : Re:從零開始的軟體開發生活」
請大家繼續支持 ^_^