明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線(xiàn)學(xué)習(xí)分享的學(xué)習(xí)平臺(tái)!

ASP.NET虛擬主機(jī)的重大安全隱患(二)

[摘要]程序二:顯示目錄中所有子目錄和文件的程序listdir.aspx  目錄下有子目錄和文件兩種形式,必須分別對(duì)待。我們調(diào)用此程序本身對(duì)子目錄進(jìn)行列表顯示,而文件我們需要調(diào)用showfile.aspx程序?qū)ξ募膶傩院蛢?nèi)容進(jìn)行顯示。并且兩者還有不同的刪除方法,所以我們?cè)谶@里設(shè)置了兩個(gè)DataGrid,...
程序二:顯示目錄中所有子目錄和文件的程序listdir.aspx

  目錄下有子目錄和文件兩種形式,必須分別對(duì)待。我們調(diào)用此程序本身對(duì)子目錄進(jìn)行列表顯示,而文件我們需要調(diào)用showfile.aspx程序?qū)ξ募膶傩院蛢?nèi)容進(jìn)行顯示。并且兩者還有不同的刪除方法,所以我們?cè)谶@里設(shè)置了兩個(gè)DataGrid,兩個(gè)DataTable,兩個(gè)DataView,分別處理和顯示目錄和文件。

  顯示和處理目錄和文件的DataGrid的代碼(代碼在listdir.aspx文件):

  顯示目錄或文件的序號(hào)和名稱(chēng)的數(shù)據(jù)列類(lèi)似于listdrivers.aspx程序中的相應(yīng)代碼,這里就不再重復(fù)了。對(duì)于子目錄和文件分別有各自的處理頁(yè)面,所以需要導(dǎo)航到兩個(gè)不同的頁(yè)面,對(duì)于子目錄,我們繼續(xù)使用listdir.aspx程序?qū)ζ湎碌淖幽夸浐臀募M(jìn)行列表顯示:

<asp:HyperLinkColumn DataNavigateUrlField="DirName"
DataNavigateUrlFormatString="listdir.aspx?dir={0}"
DataTextField="DirDetail"
HeaderText="詳細(xì)信息"
Target="_new"
/>
對(duì)于文件,我們使用showfile.aspx程序顯示其屬性和內(nèi)容:
<asp:HyperLinkColumn DataNavigateUrlField="FileName"
DataNavigateUrlFormatString="showfile.aspx?file={0}"
DataTextField="FileDetail"
HeaderText="詳細(xì)信息"
Target="_new"
/>

  在兩個(gè)DataGrid(DirGrid,F(xiàn)ileGrid)中我們分別設(shè)置了兩個(gè)HyperLinkColumn列來(lái)導(dǎo)航到不同的處理頁(yè)面。

  在兩個(gè)DataGrid中我們都使用了一個(gè)刪除的按鈕列:

<asp:ButtonColumn HeaderText="刪除"
Text="刪除"
CommandName="Delete"
/>

  由于添加、更新、刪除功能列都是DataGrid的默認(rèn)模板列,所以可以在Vs.net中通過(guò)DataGrid的屬性生成器自動(dòng)添加此列。

  獲取上一頁(yè)面所傳遞來(lái)的參數(shù)的代碼:

  因?yàn)樵谙旅娈a(chǎn)生數(shù)據(jù)源的方法中需要使用由上一個(gè)頁(yè)面?zhèn)鬟f過(guò)來(lái)的參數(shù)來(lái)確定目錄和文件的名稱(chēng),所以在頁(yè)面的Page_Load方法里使用了下列代碼:

strDir2List = Request.QueryString["dir"];

  字符串strDir2List即傳過(guò)來(lái)的目錄名或文件名。

  因?yàn)槲覀兪褂昧藘蓚(gè)DateGrid,就需要進(jìn)行兩次數(shù)據(jù)綁定,就有兩個(gè)不同的生成數(shù)據(jù)源的方法。

  生成目錄數(shù)據(jù)網(wǎng)格(DirGrid)數(shù)據(jù)源的方法:

//通過(guò)此方法返回一個(gè)集合形式的數(shù)據(jù)視圖DataView,用來(lái)初始化子目錄的DataGrid
ICollection CreateDataSourceDir() {
dtDir = new DataTable();
DataRow dr;
//向DataTable中添加新的數(shù)據(jù)列,共四列
dtDir.Columns.Add(new DataColumn("DirID", typeof(Int32)));
dtDir.Columns.Add(new DataColumn("DirName", typeof(string)));
dtDir.Columns.Add(new DataColumn("DelDir", typeof(string)));
dtDir.Columns.Add(new DataColumn("DirDetail", typeof(string)));
//根據(jù)傳入的參數(shù)(目錄名)得到此目錄下所有子目錄名的字符串?dāng)?shù)組
string [] DirEntries = Directory.GetDirectories(strDir2List);
//使用foreach循環(huán)可以對(duì)未知長(zhǎng)度的數(shù)組進(jìn)行遍歷循環(huán)
foreach(string DirName in DirEntries){
dr = dtDir.NewRow();
dr[0] = i;//序號(hào)
dr[1] = DirName;//文件夾名稱(chēng)
dr[3] = "刪除";
dr[3] = "查看詳情";
dtDir.Rows.Add(dr);
i++;
}
DataView dvDir = new DataView(dtDir);
//返回得到的數(shù)據(jù)視圖
return dvDir;
}
生成文件數(shù)據(jù)網(wǎng)格(FileGrid)數(shù)據(jù)源的方法:
//通過(guò)此方法返回一個(gè)集合形式的數(shù)據(jù)視圖DataView,用來(lái)初始化文件的DataGrid
ICollection CreateDataSourceFile() {
dtFile = new DataTable();
DataRow dr;
dtFile.Columns.Add(new DataColumn("FileID", typeof(Int32)));
dtFile.Columns.Add(new DataColumn("FileName", typeof(string)));
dtFile.Columns.Add(new DataColumn("DelFile", typeof(string)));
dtFile.Columns.Add(new DataColumn("FileDetail", typeof(string)));
//根據(jù)傳入的參數(shù)(目錄名)得到此目錄下所有文件名的字符串?dāng)?shù)組
string [] FileEntries = Directory.GetFiles(strDir2List);
foreach(string FileName in FileEntries){
dr = dtFile.NewRow();
dr[0] = i;
dr[1] = FileName;
dr[2] = "刪除";
dr[3] = "查看詳情";
dtFile.Rows.Add(dr);
i++;
}
dvFile = new DataView(dtFile);
return dvFile;
}

  我們編程實(shí)現(xiàn)了兩個(gè)DataSource只需在頁(yè)面的Page_Load方法里對(duì)兩個(gè)DataGrid進(jìn)行數(shù)據(jù)綁定即可將得到的DataTable中的數(shù)據(jù)顯示在aspx頁(yè)面的DataGrid上。

  數(shù)據(jù)綁定代碼:

//對(duì)子目錄數(shù)據(jù)列表DirGrid進(jìn)行數(shù)據(jù)源定義和數(shù)據(jù)綁定
DirGrid.DataSource = CreateDataSourceDir();
DirGrid.DataBind();
//對(duì)文件數(shù)據(jù)列表FileGrid進(jìn)行數(shù)據(jù)源定義和數(shù)據(jù)綁定
FileGrid.DataSource = CreateDataSourceFile();
FileGrid.DataBind();

  通過(guò)我們上邊介紹的主要方法,我們實(shí)現(xiàn)了對(duì)某個(gè)邏輯驅(qū)動(dòng)器或目錄中的所有子目錄和文件進(jìn)行了列表顯示,并且可以根據(jù)顯示結(jié)果更進(jìn)一步的瀏覽子目錄或者查看文件的屬性和內(nèi)容提要。瀏覽子目錄仍然是通過(guò)listdir.aspx這個(gè)程序,沒(méi)有任何子目錄級(jí)別要求,沒(méi)有目錄深度限制。
刪除子目錄和文件的主要方法和代碼:

  在刪除子目錄時(shí),我們需要用到Directory.Delete (string,bool)方法,此方法有兩種:

  1.public static void Delete(string);

  從指定路徑刪除空目錄。

  2.public static void Delete(string, boolean);

  刪除指定的目錄并(如果指示)刪除該目錄中的任何子目錄,將boolean設(shè)置為true的話(huà),則刪除此目錄下的所有子目錄和文件,否則將boolean設(shè)置為false。

  在這里我們使用了第二種方法,如果選擇刪除的話(huà),將刪除此目錄下的所有子目錄和文件。

  注意:Directory 類(lèi)的所有方法都是靜態(tài)的,因而無(wú)需具有目錄Directory的實(shí)例就可被調(diào)用。

/*實(shí)現(xiàn)刪除子目錄的方法,此方法為VS.NET自動(dòng)添加,注意DataGridCommandEventArgs e為DirGrid中 CommandName="Delete" 的ButtonColumn的事件,通過(guò)此事件,我們可以得到是那一行的ButtonColumn按鈕列被點(diǎn)擊,進(jìn)而確定我們需要?jiǎng)h除的子目錄的名稱(chēng)*/
private void DirGrid_DeleteCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e){
/*定義一個(gè)單元格,e.Item為此事件所發(fā)生行的所有項(xiàng)目,e.Item.Cells[1]為整個(gè)行的第二個(gè)單元格的內(nèi)容,在此DataGrid中為子目錄的名稱(chēng)
*/
TableCell ItemCell = e.Item.Cells[1];
//得到此子目錄的名稱(chēng)的字符串
string item = ItemCell.Text;
//刪除此子目錄
Directory.Delete(item,true);
//刪除后進(jìn)行數(shù)據(jù)綁定以更新數(shù)據(jù)列表
DirGrid.DataBind();
}

  在刪除文件時(shí),我們需要用到File.Delete(string path);

  注意:File 類(lèi)的所有方法都是靜態(tài)的,因而無(wú)需具有目錄的實(shí)例就可被調(diào)用。

private void FileGrid_DeleteCommand(object source,
System.Web.UI.WebControls.DataGridCommandEventArgs e) {
TableCell ItemCell = e.Item.Cells[1];
//得到此文件名稱(chēng)的字符串
string item = ItemCell.Text;
//刪除此文件
File.Delete(item);
//刪除后進(jìn)行數(shù)據(jù)綁定以更新數(shù)據(jù)列表
DirGrid.DataBind();
}

  通過(guò)上邊的主要方法我們?cè)陧?yè)面上實(shí)現(xiàn)了一個(gè)刪除某一個(gè)子目錄或者文件的功能,此功能在測(cè)試時(shí)需要慎重使用,一旦刪除無(wú)法通過(guò)常規(guī)方法恢復(fù)。其他如目錄或文件改名、修改內(nèi)容等方法都可以在此程序基礎(chǔ)上添加相應(yīng)的功能,實(shí)現(xiàn)方法也很簡(jiǎn)單。各位愛(ài)好者可以通過(guò)添加相應(yīng)功能,使之?dāng)U充為一個(gè)基于Web的服務(wù)器文件管理系統(tǒng)。我們也可以由此看到這個(gè)程序的危害性,一個(gè)沒(méi)有對(duì)此安全隱患采取防范措施的服務(wù)器的文件系統(tǒng)就都暴露在了使用此程序的用戶(hù)面前。
程序三:顯示文件屬性和內(nèi)容的程序showfile.aspx

  在顯示屬性和內(nèi)容時(shí)需要用到的兩個(gè)主要的類(lèi):

  System.IO.FileInfo:提供創(chuàng)建、復(fù)制、刪除、移動(dòng)和打開(kāi)文件的實(shí)例方法,并且?guī)椭鷦?chuàng)建 FileStream 對(duì)象。

  System.IO.StreamReader:實(shí)現(xiàn)一個(gè) TextReader,使其以一種特定的編碼從字節(jié)流中讀取字符。除非另外指定,StreamReader的默認(rèn)編碼為 UTF-8,而不是當(dāng)前系統(tǒng)的 ANSI 代碼頁(yè)。UTF-8 可以正確處理 Unicode 字符并在操作系統(tǒng)的本地化版本上提供一致的結(jié)果。

  Showfile.aspx頁(yè)面主要代碼:

<asp:Label id="FileDetail" runat="server"/>

  我們只是將文件的屬性信息和部分內(nèi)容顯示在此Label上。所以沒(méi)有其他復(fù)雜的代碼。

  獲取文件信息和內(nèi)容的主要代碼都在Page_Load方法中(代碼在showfile.aspx.cs文件中):

//接收傳入的參數(shù),確定需要操作的文件名稱(chēng)
strFile2Show = Request.QueryString["file"];
//根據(jù)文件名實(shí)例化一個(gè)FileInfo對(duì)象
FileInfo fi = new FileInfo(strFile2Show);
FileDetail.Text = "文件名:";
FileDetail.Text += strFile2Show+"<br>";
FileDetail.Text += "文件大小";
//獲得文件的大小,然后變換單位為KB
FileDetail.Text += (fi.Length/1024).ToString()+"K<br>";
FileDetail.Text += "創(chuàng)建文件時(shí)間:";
//獲得文件的創(chuàng)建日期
FileDetail.Text += fi.CreationTime.ToString();
FileDetail.Text += "上次訪(fǎng)問(wèn)時(shí)間:";
//獲得文件的上次訪(fǎng)問(wèn)日期
FileDetail.Text += fi.LastAccessTime.ToString()+"<br>";
FileDetail.Text += "上次寫(xiě)入時(shí)間:";
//獲得文件的上次寫(xiě)入日期
FileDetail.Text += fi.LastWriteTime.ToString()+"<br>";
//實(shí)例化一個(gè)StreamReader對(duì)象,用于讀取此FileInfo的內(nèi)容
StreamReader FileReader = fi.OpenText();
//定義一個(gè)長(zhǎng)度為1000的字符數(shù)組作為緩沖區(qū)
char[] theBuffer = new char[1000];
/*ReadBlock方法:從當(dāng)前流中讀取最大數(shù)量的字符并從索引開(kāi)始將該數(shù)據(jù)寫(xiě)入緩沖區(qū)。
參數(shù):
char[] buffer:方法返回時(shí),包含指定的字符數(shù)組
int index:buffer 中開(kāi)始寫(xiě)入的位置
int count:最多讀取的字符數(shù)
*/
int nRead = FileReader.ReadBlock(theBuffer,0,1000);
FileDetail.Text += new String(theBuffer,0,nRead);
//關(guān)閉此 StreamReader 并釋放與之關(guān)聯(lián)的所有系統(tǒng)資源
FileReader.Close();

  到目前為止,我們實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的web頁(yè)面的服務(wù)器磁盤(pán)管理應(yīng)用程序,可以查看、刪除目錄和文件。如果需要修改文件、新建文件和文件夾等功能,只需稍作修改,添加上相應(yīng)的代碼就可以。由于我們只是通過(guò)這個(gè)程序說(shuō)明服務(wù)器中存在的安全隱患,所以在這里就不再實(shí)現(xiàn)這些功能了。

  通過(guò)這三個(gè)簡(jiǎn)單的程序,我想大家已經(jīng)能夠清楚的認(rèn)識(shí)到這一漏洞的危害性了,如果我們不加防范的話(huà),其他用戶(hù)的程序就能被惡意使用此功能的用戶(hù)查看、刪除,服務(wù)器的系統(tǒng)日志、系統(tǒng)文件也沒(méi)有任何安全可言了。