ASP.NET虛擬主機的重大安全隱患(二)
2024-07-10 13:04:18
供稿:網友
程序二:顯示目錄中所有子目錄和文件的程序listdir.aspx
目錄下有子目錄和文件兩種形式,必須分別對待。我們調用此程序本身對子目錄進行列表顯示,而文件我們需要調用showfile.aspx程序對文件的屬性和內容進行顯示。并且兩者還有不同的刪除方法,所以我們在這里設置了兩個datagrid,兩個datatable,兩個dataview,分別處理和顯示目錄和文件。
顯示和處理目錄和文件的datagrid的代碼(代碼在listdir.aspx文件):
顯示目錄或文件的序號和名稱的數據列類似于listdrivers.aspx程序中的相應代碼,這里就不再重復了。對于子目錄和文件分別有各自的處理頁面,所以需要導航到兩個不同的頁面,對于子目錄,我們繼續使用listdir.aspx程序對其下的子目錄和文件進行列表顯示:
<asp:hyperlinkcolumn datanavigateurlfield="dirname"
datanavigateurlformatstring="listdir.aspx?dir={0}"
datatextfield="dirdetail"
headertext="詳細信息"
target="_new"
/>
對于文件,我們使用showfile.aspx程序顯示其屬性和內容:
<asp:hyperlinkcolumn datanavigateurlfield="filename"
datanavigateurlformatstring="showfile.aspx?file={0}"
datatextfield="filedetail"
headertext="詳細信息"
target="_new"
/>
在兩個datagrid(dirgrid,filegrid)中我們分別設置了兩個hyperlinkcolumn列來導航到不同的處理頁面。
在兩個datagrid中我們都使用了一個刪除的按鈕列:
<asp:buttoncolumn headertext="刪除"
text="刪除"
commandname="delete"
/>
由于添加、更新、刪除功能列都是datagrid的默認模板列,所以可以在vs.net中通過datagrid的屬性生成器自動添加此列。
獲取上一頁面所傳遞來的參數的代碼:
因為在下面產生數據源的方法中需要使用由上一個頁面傳遞過來的參數來確定目錄和文件的名稱,所以在頁面的page_load方法里使用了下列代碼:
strdir2list = request.querystring["dir"];
字符串strdir2list即傳過來的目錄名或文件名。
因為我們使用了兩個dategrid,就需要進行兩次數據綁定,就有兩個不同的生成數據源的方法。
生成目錄數據網格(dirgrid)數據源的方法:
//通過此方法返回一個集合形式的數據視圖dataview,用來初始化子目錄的datagrid
icollection createdatasourcedir() {
dtdir = new datatable();
datarow dr;
//向datatable中添加新的數據列,共四列
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)));
//根據傳入的參數(目錄名)得到此目錄下所有子目錄名的字符串數組
string [] direntries = directory.getdirectories(strdir2list);
//使用foreach循環可以對未知長度的數組進行遍歷循環
foreach(string dirname in direntries){
dr = dtdir.newrow();
dr[0] = i;//序號
dr[1] = dirname;//文件夾名稱
dr[3] = "刪除";
dr[3] = "查看詳情";
dtdir.rows.add(dr);
i++;
}
dataview dvdir = new dataview(dtdir);
//返回得到的數據視圖
return dvdir;
}
生成文件數據網格(filegrid)數據源的方法:
//通過此方法返回一個集合形式的數據視圖dataview,用來初始化文件的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)));
//根據傳入的參數(目錄名)得到此目錄下所有文件名的字符串數組
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;
}
我們編程實現了兩個datasource只需在頁面的page_load方法里對兩個datagrid進行數據綁定即可將得到的datatable中的數據顯示在aspx頁面的datagrid上。
數據綁定代碼:
//對子目錄數據列表dirgrid進行數據源定義和數據綁定
dirgrid.datasource = createdatasourcedir();
dirgrid.databind();
//對文件數據列表filegrid進行數據源定義和數據綁定
filegrid.datasource = createdatasourcefile();
filegrid.databind();
通過我們上邊介紹的主要方法,我們實現了對某個邏輯驅動器或目錄中的所有子目錄和文件進行了列表顯示,并且可以根據顯示結果更進一步的瀏覽子目錄或者查看文件的屬性和內容提要。瀏覽子目錄仍然是通過listdir.aspx這個程序,沒有任何子目錄級別要求,沒有目錄深度限制。
刪除子目錄和文件的主要方法和代碼:
在刪除子目錄時,我們需要用到directory.delete (string,bool)方法,此方法有兩種:
1.public static void delete(string);
從指定路徑刪除空目錄。
2.public static void delete(string, boolean);
刪除指定的目錄并(如果指示)刪除該目錄中的任何子目錄,將boolean設置為true的話,則刪除此目錄下的所有子目錄和文件,否則將boolean設置為false。
在這里我們使用了第二種方法,如果選擇刪除的話,將刪除此目錄下的所有子目錄和文件。
注意:directory 類的所有方法都是靜態的,因而無需具有目錄directory的實例就可被調用。
/*實現刪除子目錄的方法,此方法為vs.net自動添加,注意datagridcommandeventargs e為dirgrid中 commandname="delete" 的buttoncolumn的事件,通過此事件,我們可以得到是那一行的buttoncolumn按鈕列被點擊,進而確定我們需要刪除的子目錄的名稱*/
private void dirgrid_deletecommand(object source, system.web.ui.webcontrols.datagridcommandeventargs e){
/*定義一個單元格,e.item為此事件所發生行的所有項目,e.item.cells[1]為整個行的第二個單元格的內容,在此datagrid中為子目錄的名稱
*/
tablecell itemcell = e.item.cells[1];
//得到此子目錄的名稱的字符串
string item = itemcell.text;
//刪除此子目錄
directory.delete(item,true);
//刪除后進行數據綁定以更新數據列表
dirgrid.databind();
}
在刪除文件時,我們需要用到file.delete(string path);
注意:file 類的所有方法都是靜態的,因而無需具有目錄的實例就可被調用。
private void filegrid_deletecommand(object source,
system.web.ui.webcontrols.datagridcommandeventargs e) {
tablecell itemcell = e.item.cells[1];
//得到此文件名稱的字符串
string item = itemcell.text;
//刪除此文件
file.delete(item);
//刪除后進行數據綁定以更新數據列表
dirgrid.databind();
}
通過上邊的主要方法我們在頁面上實現了一個刪除某一個子目錄或者文件的功能,此功能在測試時需要慎重使用,一旦刪除無法通過常規方法恢復。其他如目錄或文件改名、修改內容等方法都可以在此程序基礎上添加相應的功能,實現方法也很簡單。各位愛好者可以通過添加相應功能,使之擴充為一個基于web的服務器文件管理系統。我們也可以由此看到這個程序的危害性,一個沒有對此安全隱患采取防范措施的服務器的文件系統就都暴露在了使用此程序的用戶面前。
程序三:顯示文件屬性和內容的程序showfile.aspx
在顯示屬性和內容時需要用到的兩個主要的類:
system.io.fileinfo:提供創建、復制、刪除、移動和打開文件的實例方法,并且幫助創建 filestream 對象。
system.io.streamreader:實現一個 textreader,使其以一種特定的編碼從字節流中讀取字符。除非另外指定,streamreader的默認編碼為 utf-8,而不是當前系統的 ansi 代碼頁。utf-8 可以正確處理 unicode 字符并在操作系統的本地化版本上提供一致的結果。
showfile.aspx頁面主要代碼:
<asp:label id="filedetail" runat="server"/>
我們只是將文件的屬性信息和部分內容顯示在此label上。所以沒有其他復雜的代碼。
獲取文件信息和內容的主要代碼都在page_load方法中(代碼在showfile.aspx.cs文件中):
//接收傳入的參數,確定需要操作的文件名稱
strfile2show = request.querystring["file"];
//根據文件名實例化一個fileinfo對象
fileinfo fi = new fileinfo(strfile2show);
filedetail.text = "文件名:";
filedetail.text += strfile2show+"<br>";
filedetail.text += "文件大小";
//獲得文件的大小,然后變換單位為kb
filedetail.text += (fi.length/1024).tostring()+"k<br>";
filedetail.text += "創建文件時間:";
//獲得文件的創建日期
filedetail.text += fi.creationtime.tostring();
filedetail.text += "上次訪問時間:";
//獲得文件的上次訪問日期
filedetail.text += fi.lastaccesstime.tostring()+"<br>";
filedetail.text += "上次寫入時間:";
//獲得文件的上次寫入日期
filedetail.text += fi.lastwritetime.tostring()+"<br>";
//實例化一個streamreader對象,用于讀取此fileinfo的內容
streamreader filereader = fi.opentext();
//定義一個長度為1000的字符數組作為緩沖區
char[] thebuffer = new char[1000];
/*readblock方法:從當前流中讀取最大數量的字符并從索引開始將該數據寫入緩沖區。
參數:
char[] buffer:方法返回時,包含指定的字符數組
int index:buffer 中開始寫入的位置
int count:最多讀取的字符數
*/
int nread = filereader.readblock(thebuffer,0,1000);
filedetail.text += new string(thebuffer,0,nread);
//關閉此 streamreader 并釋放與之關聯的所有系統資源
filereader.close();
到目前為止,我們實現了一個簡單的web頁面的服務器磁盤管理應用程序,可以查看、刪除目錄和文件。如果需要修改文件、新建文件和文件夾等功能,只需稍作修改,添加上相應的代碼就可以。由于我們只是通過這個程序說明服務器中存在的安全隱患,所以在這里就不再實現這些功能了。
通過這三個簡單的程序,我想大家已經能夠清楚的認識到這一漏洞的危害性了,如果我們不加防范的話,其他用戶的程序就能被惡意使用此功能的用戶查看、刪除,服務器的系統日志、系統文件也沒有任何安全可言了。