分类: ASP.NET2009-04-12 17:24 531人阅读 评论(0) 收藏 举报

ASP.Net 1.1后引入了对提交表单自动检查是否存在XSS(跨站脚本攻击)的能力。当用户试图用<xxxx>之类的输入影响页面返回结果的时候,ASP.Net的引擎会引发一个 HttpRequestValidationExceptioin。默认情况下会返回如下文字的页面:

Server Error in '/YourApplicationPath' Application

A potentially dangerous Request.Form value was detected from the client
(txtName="<b>").

Description: Request Validation has detected a potentially dangerous client input value, and processing of the request has been aborted. This value may indicate an attempt to compromise the security of your application, such as a cross-site scripting attack. You can disable request validation by setting validateRequest=false in the Page directive or in the configuration section. However, it is strongly recommended that your application explicitly check all inputs in this case.

Exception Details: System.Web.HttpRequestValidationException: A potentially dangerous Request.Form value was detected from the client (txtName="<b>").

....

这是ASP.Net提供的一个很重要的安全特性。因为很多程序员对安全没有概念,甚至都不知道XSS这种攻击的存在,知道主动去防护的就更少了。ASP.Net在这一点上做到默认安全。这样让对安全不是很了解的程序员依旧可以写出有一定安全防护能力的网站。

但是,当我Google搜索 HttpRequestValidationException 或者 "A potentially dangerous Request.Form value was detected from the client"的时候,惊奇的发现大部分人给出的解决方案竟然是在ASP.Net页面描述中通过设置validateRequest=false 来禁用这个特性,而不去关心那个程序员的网站是否真的不需要这个特性。看得我这叫一个胆战心惊。安全意识应该时时刻刻在每一个程序员的心里,不管你对安全的概念了解多少,一个主动的意识在脑子里,你的站点就会安全很多。

为什么很多程序员想要禁止 validateRequest 呢?有一部分是真的需要用户输入"<>"之类的字符。这就不必说了。还有一部分其实并不是用户允许输入那些容易引起XSS的字符,而是讨厌这种报错的形式,毕竟一大段英文加上一个ASP.Net典型异常错误信息,显得这个站点出错了,而不是用户输入了非法的字符,可是自己又不知道怎么不让它报错,自己来处理报错。

对于希望很好的处理这个错误信息,而不使用默认ASP.Net异常报错信息的程序员们,你们不要禁用validateRequest=false。

正确的做法是在你当前页面添加Page_Error()函数,来捕获所有页面处理过程中发生的而没有处理的异常。然后给用户一个合法的报错信息。如果当前页面没有Page_Error(),这个异常将会送到Global.asax的Application_Error()来处理,你也可以在那里写通用的异常报错处理函数。如果两个地方都没有写异常处理函数,才会显示这个默认的报错页面呢。

举例而言,处理这个异常其实只需要很简短的一小段代码就够了。在页面的Code-behind页面中加入这么一段代码:

protected void Page_Error(object sender, EventArgs e)
{
    Exception ex = Server.GetLastError();
    if (ex is HttpRequestValidationException)
    {
        Response.Write("请您输入合法字符串。");
        Server.ClearError(); // 如果不ClearError()这个异常会继续传到Application_Error()。
    }
}

这样这个程序就可以截获 HttpRequestValidationException 异常,而且可以按照程序员的意愿返回一个合理的报错信息。

这段代码很简单,所以我希望所有不是真的要允许用户输入<xxx>之类字符的朋友,千万不要随意的禁止这个安全特性,如果只是需要异常处理,那么请用类似于上面的代码来处理即可。

而对于那些通过 明确禁止了这个特性的程序员,自己一定要明白自己在做什么,而且一定要自己手动的检查必须过滤的字符串,否则你的站点很容易引发跨站脚本攻击。

关于存在Rich Text Editor的页面应该如何处理?

如果页面有富文本编辑器的控件的,那么必然会导致有<xxx>类的HTML标签提交回来。在这种情况下,我们不得不将validateRequest="false"。那么安全性怎么处理?如何在这种情况下最大限度的预防跨站脚本攻击呢?

根据微软的建议,我们应该采取安全上称为“默认禁止,显式允许”的策略。

首先,我们将输入字符串用 HttpUtility.HtmlEncode()来编码,将其中的HTML标签彻底禁止。

然后,我们再对我们所感兴趣的、并且是安全标签,通过Replace()进行替换。比如,我们希望有"<b>"标签,那么我们就将"&lt;b&gt;"显式的替换回"<b>"。

示例代码如下:

  void submitBtn_Click(object sender, EventArgs e)
  {
    // 将输入字符串编码,这样所有的HTML标签都失效了。
    StringBuilder sb = new StringBuilder(
                            HttpUtility.HtmlEncode(htmlInputTxt.Text));
    // 然后我们选择性的允许<b> 和 <i>
    sb.Replace("&lt;b&gt;", "<b>");
    sb.Replace("&lt;/b&gt;", "");
    sb.Replace("&lt;i&gt;", "<i>");
    sb.Replace("&lt;/i&gt;", "");
    Response.Write(sb.ToString());
  }

这样我们即允许了部分HTML标签,又禁止了危险的标签。

根据微软提供的建议,我们要慎重允许下列HTML标签,因为这些HTML标签都是有可能导致跨站脚本攻击的。

  • <applet>
  • <body>
  • <embed>
  • <frame>
  • <script>
  • <frameset>
  • <html>
  • <iframe>
  • <img>
  • <style>
  • <layer>
  • <link>
  • <ilayer>
  • <meta>
  • <object>

可能这里最让人不能理解的是<img>。但是,看过下列代码后,就应该明白其危险性了。

<img src="javascript:alert('hello');">
<img src="java script:alert('hello');">
<img src="java script:alert('hello');">

通过<img>标签是有可能导致Javascript执行的,这样攻击者就可以做他想伪装的任何事情。

关于<style>也是一样:

<style TYPE="text/javascript">
  alert('hello');
</style>

为了安全请不要随意在页面中设置validateRequest="false"的更多相关文章

  1. (转)通过在 Page 指令或 配置节中设置 validateRequest=false 可以禁用请求验证

    通过在 Page 指令或 配置节中设置 validateRequest=false 可以禁用请求验证 说明:   请求验证过程检测到有潜在危险的客户端输入值,对请求的处理已经中止.该值可能指示危及应用 ...

  2. 在Form Load中设置showInTaskBar =false 或 隐藏窗口 this.Hide()时会导致注册的全局快捷键无效

    在Form Load中设置showInTaskBar =false   或 隐藏窗口 this.Hide() 会导致注册的全局快捷键无效.  反正是其中一个,有点记不清了. 在Form Shown中s ...

  3. 在jsp页面中设置了远程验证,在初始化时必须预先调用一次。

    参考链接:http://code.taobao.org/p/sztaotao/diff/5/trunk/code/src/main/webapp/webpage/modules/sys/roleFor ...

  4. 在jsp页面中设置中序号

    首先要使用<c>标签的话需要先引入下面这句话: <%@ taglib prefix="c" uri="http://Java.sun.com/jsp/j ...

  5. 使用COCOS2D-X JSB开发,在js页面中设置iOS键盘模式

    XYSDK.h void setKeyboardType(int type); XYSDK.cpp voidXYSDK::setKeyboardType(int type) { #if (CC_TAR ...

  6. jsp页面中的EL表达式不被解析的问题

    原因:问题在web.xml配置文件上,web.xml声明部分一般分为如下版本的xsd, web-app_2_2.xsd web-app_2_3.xsd web-app_2_4.xsd web-app_ ...

  7. 关于在JSP页面中为什么一定要用${pageContext.request.contextPath}来获取项目路径,而不能用${request.contextPath}?

    这里的疑问在于pageContext和request都是JSP中的内置对象之一,为什么不直接用${request.contextPath}来获取项目路径? 出现这种疑问,其实是将JSP的内置对象和EL ...

  8. 微信小程序app.js中设置公有变量

    初始化GlobalData 在App.js的最上方可以设置GlobalData的初始值. App({ globalData:{ appid: '1wqas2342dasaqwe232342xxxxxx ...

  9. 如需在 HTML 页面中插入 JavaScript,请使用 <script> 标签。

    如需在 HTML 页面中插入 JavaScript,请使用 <script> 标签. <script> 和 </script> 会告诉 JavaScript 在何处 ...

随机推荐

  1. EF7学习资料整理

    EntityFramework 7 开发纪录 http://www.cnblogs.com/xishuai/archive/2014/11/28/ef7-develop-note.html Entit ...

  2. [软件安装]MYSQL

    https://dev.mysql.com/downloads/repo/yum/ wget https://repo.mysql.com//mysql57-community-release-el7 ...

  3. bzoj 4245: [ONTAK2015]OR-XOR【按位贪心】

    知道按位贪心但是不知道怎么贪-- 求一个a的异或前缀和s,然后按位从大到小贪心,ans的当前位能为0的条件是s中有>=m个位置这一位为0且没有flag,并且s[n]的这一位为0 如果符合要求,那 ...

  4. (11)用css设计电子相册 {上}

    本篇学习资料讲解:       通过css对电子相册进行排版 和 侧面强调“盒子模型.标准流.浮动和定位”的重要性. 先来看看"双向联动模式"的电子相册图: {鼠标指针经过某张图片 ...

  5. java启动参数一

    java启动参数共分为三类: 其一是标准参数(-),所有的JVM实现都必须实现这些参数的功能,而且向后兼容: 其二是非标准参数(-X),默认jvm实现这些参数的功能,但是并不保证所有jvm实现都满足, ...

  6. time模块,datetime模块

    time模块 time模块是包含各方面对时间操作的函数. 尽管这些常常有效但不是所有方法在任意平台中有效. 时间相关的操作,时间有三种表示方式: 时间戳               1970年1月1日 ...

  7. openstack知识---hypervisor

    hypervisor Hypervisor是一种运行在物理服务器和操作系统之间的中间软件层,可允许多个操作系统和应用共享一套基础物理硬件,因此也可以看作是虚拟环境中的“元”操作系统,它可以协调访问服务 ...

  8. hihocoder1703 第K小先序遍历

    思路: 给定n个节点二叉树的中序遍历,不同形态的二叉树的种类数有卡特兰数个.为了在中序序列[l, r]表示的子树上找先序序列第k小的树,首先需要从小到大枚举每个节点作根所能构成的二叉树的数目来确定树根 ...

  9. Android开发中查看未root真机的app数据库

    在Android开发中,如果用到数据库来储存数据,那么难免就要查看数据库中的内容,可是对于未root的真机来说,查看数据库就不是那么容易了,如果仅仅为了查看数据库再把手机root了,有点得不偿失,所以 ...

  10. QT入门学习2

    QT获取窗口几何布局有2类函数: 1.包含框架:x().y().frameGemetry().pos().move()... 2.不包含框架:geometry().width().height().w ...