专注于技术经验交流

水至清则无鱼、宁静而致远!

技术、经验、学习共同打造网络新生活!
  首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

在ASP.NET中防止注入攻击(4)

Posted on 2006-07-13 18:31  小鱼儿  阅读(361)  评论(2编辑  收藏  举报
在ASP.NET中防止注入攻击(4)

验证文件和URL地址

  如果你的程序允许输入文件名,文件地址或者文件存放路径,你需要验证它们的格式是否正确并且根据你的程序实际情况它指向一个有效的位置.如果此步验证失败,你的程序可能会被错误地要求访问文件.

  验证文件路径

  为了避免你的程序被用户利用来访问文件,防止接受用户编写代码输入的文件或者文件路径.例如 : 

如果你接受输入文件名,使用System.IO.Path.GetFileName方法来取得文件的全称 
如果你不得不接受输入文件路径,使用System.IO.Path.GetFullPath来取得完整的文件路径 

  使用MapPath方法防止跨应用程序的映射 

  如果你使用MapPath方法在服务器上映射一个提供的虚拟目录到一个物理目录,使用Request.MapPath方法的一个带bool参数的重载版本来防止跨应用程序的映射.下面是此项技术的示例代码 :

try
{
string mappedPath = Request.MapPath( inputPath.Text, 
Request.ApplicationPath, false);
}
catch (HttpException)
{

//
Cross-application mapping attempted

}

  最终的false参数将会防止跨应用程序的映射.这意味着用户不允许使用".."这样的语法提供一个不在你所指定的虚拟目录里面的非法路径.

  如果你使用服务器控件,你可以使用Control.MapPathSecure方法获取虚拟目录对应的实际目录地址.

  Control.MapPathSecure方法在访问一个非授权的文件时抛出一个HttpException的异常.需要更多信息,请参看.NET Framework文档中的Control.MapPathSecure方法介绍.

  使用代码访问安全机制限制文件输入输出

  管理员可以通过设置程序使它的可信度为"中"来限制程序向它所在的虚拟目录读写文件的能力..NET代码安全机制可以保证程序在它所在的虚拟目录之外没有任何的文件访问权利.

  要设置一个应用程序的信任度为"中",可以在Web.config或者Machine.config文件中加入:

<trust level = "Medium" />

  验证URL

  你可以用象下面的这样的正则表达式来对URL进行特征匹配.

^(?:http|https|ftp)://[a-zA-Z0-9\.\-]+(?:\:\d{1,5})?(?:[A-Za-z0-9\.\;\:\@\&\=\+\$\,\?/]|%u[0-9A-Fa-f]{4}|%[0-9A-Fa-f]{2})*$

  这只是约束输入的格式,不验证它是否在应用程序可接受的范围内.你应该验证它是否在你的程序的上下文中有效.例如,您的应用程序是否跟你指定的服务器进行通讯?

  第三步.对不安全代码进行编码
  如果您输入文本输入到一个网页,使用HttpUtility.HtmlEncode方法对它进行编码.如果这些文来自于用户输入,数据库或者一个本地文件,请确保总是这样做.

  同样地,如果您书写的URL里面包含不安全的字符因为他们来自于用户输入内容,数据库等,使用HttpUtility.UrlEncode方法进行编码.

  为了防止存储数据前编码可能会使存储的数据受到破坏,请确保在将它们显示出来时尽可能后面的步骤将它们编码.

  使用HtmlEncode对不安全的输出编码

  HtmlEncode对HTML标记置换成特殊含文的字符串来表示这些符号而又让浏览器不把它们当作HTML标记来解释处理.比如."<"被置换成< " (冒号) 被替换成" 这些标记被显示成无害的文本.

<%@ Page Language="C#" ValidateRequest="false" %>

<s cript runat="server">
void submitBtn_Click(object sender, EventArgs e)
{
Response.Write(HttpUtility.HtmlEncode(inputTxt.Text));
}
</s cript>

<html xmlns="http://www.w3.org/1999/xhtml"; >
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox ID="inputTxt" Runat="server" 
TextMode="MultiLine" Width="382px" Height="152px">
</asp:TextBox>
<asp:Button ID="submitBtn" Runat="server" Text="Submit" 
OnClick="submitBtn_Click" />
</div>
</form>
</body>
</html>

  查看HTML编码的效果,请建立一个虚拟目录将前述的文件放进去,运行此页面,在文本框中输入一些HTML代码,点击提交按钮.例如,下面的输入被当作普通文本来显示.

Run s cript and say hello <s cript>alert('hello');</s cript> 

  如果你移除调用HtmlEncode方法,简单地输入文本的内容,浏览器会执行代码并弹出一个提示框.

  使用UrlEncode 方法对不安全的URL地址进行编码

  如果你需要获取有用户输入部分的URL参数,这可能带来一定的安全风险,使用HttpUtility.UrlEncode方法对这个地址字符串编码.

HttpUtility.UrlEncode(urlString);

  第四步.对SQL语句使用命令参数方式.

  为了避免注入式攻击请使用SQL的参数方式.参数(Parameters)集合提供类型检测和长度检测.如果你使用参数集合,输入的内容将被当作文本值来对待,数据库不会执行包含在其中的代码.使用参数集方式的一个额外的好处是,你可以严格限定输入的类型和长度.如果输入型超出范围将会触发异常.

  当调用一个存储过程时使用参数集

  下面的代码片段演示了在调用存储过程时使用参数集的例子.

SqlDataAdapter myCommand = new SqlDataAdapter("AuthorLogin", 
myConnection);
myCommand.SelectCommand.CommandType = CommandType.StoredProcedure;
SqlParameter parm = myCommand.SelectCommand.Parameters.Add(
"@LoginId", SqlDbType.VarChar, 11);
parm.Value = Login.Text;

  在创建你自己的SQL语句时使用参数集.

  如果你不能使用存储过程,你仍然可以使用参数集,请看下面的代码.

SqlDataAdapter myCommand = new SqlDataAdapter(
"SELECT au_lname, au_fname FROM Authors WHERE au_id = @au_id", myConnection);
SQLParameter parm = myCommand.SelectCommand.Parameters.Add(
"@au_id" ,SqlDbType.VarChar, 11);
Parm.Value = Login.Text;

  如果需要获取更多的如果防止SQL注入攻击的信息请参看How to : Protect From SQL Injection in ASP.NET

  第五步.验证ASP.NET的错误信息没有被返回到客户端

  你可以使用<customErrors>元素来配置客户端,一般的错误信息应该被程序错误检测机制返回到客户端.

  请确认已经更改web.config中的mode属性为"remoteOnly",下面是示例.

<customErrors mode = "remoteOnly">

  安在装了一个ASP.NET 的程序之后,你可以按照如下设定指定客户端的错误信息页面。

<customErrors mode = "on" defaultRedirect = "YourErrorPage.htm">

New Document