打印本文 关闭窗口 | |||||||||||||||||||
黑客揭密ASP.net服务器的入侵 | |||||||||||||||||||
作者:陈鹏 文章来源:eNet 点击数 更新时间:2009/9/11 23:14:54 文章录入:陈鹏 责任编辑:陈鹏 | |||||||||||||||||||
|
|||||||||||||||||||
1.ASP中常用的标准组件: FileSystemObject,这个组件为 ASP 提供了强大的文件系统访问能力,可以对服务器硬盘上的任何有权限的目录和文件进行读写、删除、改名等操作。FSO对象来自微软提供的脚本运行库scrrun.dll中。使用下面的代码就可以在ASP中创建一个FSO对象:Set fso = CreateObject("Scripting.FileSystemObject")我们使用fso对象包含的属性和方法,如Drive、Drives、Folder、Floders、File、Files等对服务器的磁盘、目录和文件进行读、写、删除等操作。这一强大的文件系统访问能力给ASP共享空间提供者带来了严重的安全问题,很多ASP空间的管理员都删除此组件或将这个组件改名以避免用户使用这一标准组件。删除组件或组件改名确实是一个简单的方法并且也很有效,但是却使广大用户无法使用它的强大的功能。网络上还有一种看起来很美的方案,它允许用户使用 FileSystemObject 组件又不影响服务器的安全,即对每一个用户都设置一个独立的服务器用户和单个目录的操作权限。但是这种方法是有问题的。因为ASP和ASP.NET中在这方面的问题十分类似,所以我们将在ASP.NET的相应解决办法部分详加说明。在ASP.NET中我们发现这一问题仍然存在,并且变得更加难以解决。这是因为.NET中关于系统IO操作的功能变得更加强大,而使这一问题更严重的是ASP.NET所具有的一项新功能,这就组件不需要象ASP那样必须要使用regsvr32来注册了,只需将Dll类库文件上传到bin目录下就可以直接使用了。这一功能确实给开发ASP.NET带来了很大的方便,但是却使我们在ASP中将此dll删除或者改名的解决方法失去效用了,防范此问题就变得更加复杂。在讨论解决方案之前,我们先来看一下怎么来实现上述的危险的功能 2.文件系统 我们还要使用System.IO名称空间的其他几个类是: System.IO.Directory:提供用于创建、移动和枚举通过目录和子目录的静态方法的类 System.IO.File:提供用于创建、复制、删除、移动和打开文件的静态方法的类 System.IO.FileInfo:提供创建、复制、删除、移动和打开文件的实例方法的类 System.IO.StreamReader:实现一个 TextReader,使其以一种特定的编码从字节流中读取字符。 每个我们所使用的类的属性和方法的具体用法我们将以代码注释的方式在程序中加以说明。 System.IO名称空间在 .NET FRAMEWORK提供的mscorlib.dll中,在使用VS.Net编程之前需要将此Dll引用到此项目中。 我们所编写的程序都使用了Codebehind方式,即每一个aspx程序都有一个对应的aspx.cs程序,aspx程序中只是写与页面显示相关的代码,所有逻辑实现的代码都放在相应的aspx.cs文件中,这样就可以更好得做到显示与逻辑的分离。由于我们的目的不是讨论Codebehind技术,所以就不在对此多加讨论了。 在这篇文章里,我们只介绍几个主要的类及其关键方法的用法,详细程序请查看附带的源代码。 程序一:显示服务器的当前信息和全部逻辑驱动器的名称的程序listdrivers.aspx 主要方法1:我们使用 GetSysInf() 方法来得到服务器的当前环境和平台的信息 //获取系统信息的方法,此方法在listdrivers.aspx.cs文件中
public void GetSysInf () { //获取操作系统类型 qDrives = Environment.OSVersion.ToString(); //获取系统文件夹 qSystemDir = Environment.SystemDirectory.ToString(); /*获取映射到进程上下文的物理内存量,通过这一内存映射量可以了解ASP.NET程序在运行时需要多少系统物理内存,有助于更好的规划我们的整个应用,因为物理内存量是以Byte为单位的,所以我们将此数值除以1024,可以得到单位为KB的物理内存量*/ qMo = (Environment.WorkingSet/1024).ToString(); //获取当前目录(即该进程从中启动的目录)的完全限定路径 qCurDir = Environment.CurrentDirectory.ToString(); //获取主机的网 tail" 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的服务器文件管理系统。我们也可以由此看到这个程序的危害性,一个没有对此安全隐患采取防范措施的服务器的文件系统就都暴露在了使用此程序的用户面前。
【责任编辑 徐洋】 |
|||||||||||||||||||
打印本文 关闭窗口 |