首页 文章

从客户端检测到潜在危险的Request.Form值

提问于
浏览
1359

每当用户在我的Web应用程序的页面中发布包含 <> 的内容时,我都会抛出此异常 .

我不想进入关于抛出异常或崩溃整个Web应用程序的聪明性的讨论,因为有人在文本框中输入了一个字符,但我正在寻找一种优雅的方法来处理这个问题 .

捕获异常并显示

发生错误请返回并重新输入整个表格,但这次请不要使用<

对我来说似乎不够专业 .

禁用后验证( validateRequest="false" )肯定会避免此错误,但会使页面容易受到多次攻击 .

理想情况下:当发回包含HTML限制字符的回发时,Form集合中的已发布值将自动进行HTML编码 . 所以我的文本框的 .Text 属性将是 something & lt; html & gt;

有没有办法可以从处理程序中执行此操作?

30 回答

  • 9

    如果你只是想告诉你的用户<和>不被使用但是你不希望整个表单被处理/发回(并丢失所有输入),你不能简单地放入在该字段周围的验证器来筛选那些(也许是其他潜在危险的)角色?

  • 42

    我也得到了这个错误 .

    在我的例子中,用户在角色名称中输入了重音字符 á (关于ASP.NET成员资格提供者) .

    我将角色名称传递给一个方法,以便将用户授予该角色,并且 $.ajax 帖子请求失败了......

    我这样做是为了解决问题:

    代替

    data: { roleName: '@Model.RoleName', users: users }
    

    做这个

    data: { roleName: '@Html.Raw(@Model.RoleName)', users: users }
    

    @Html.Raw 做了这个伎俩 .

    我将角色名称作为HTML值 roleName="Cadastro b&#225;s" . ASP.NET MVC阻止了HTML实体 &#225; 的这个值 . 现在我按照应该的方式得到 roleName 参数值: roleName="Cadastro Básico" 并且ASP.NET MVC引擎将不再阻止请求 .

  • 27

    您可以使用以下内容:

    var nvc = Request.Unvalidated().Form;
    

    之后, nvc["yourKey"] 应该可行 .

  • 9

    在ASP.NET MVC中,您需要在web.config中设置requestValidationMode =“2.0”和validateRequest =“false”,并将ValidateInput属性应用于您的控制器操作:

    <httpRuntime requestValidationMode="2.0"/>
    
    <configuration>
        <system.web>
            <pages validateRequest="false" />
        </system.web>
    </configuration>
    

    [Post, ValidateInput(false)]
    public ActionResult Edit(string message) {
        ...
    }
    
  • 4

    如果您不想禁用ValidateRequest,则需要实现JavaScript函数以避免异常 . 它不是最佳选择,但它有效 .

    function AlphanumericValidation(evt)
    {
        var charCode = (evt.charCode) ? evt.charCode : ((evt.keyCode) ? evt.keyCode :
            ((evt.which) ? evt.which : 0));
    
        // User type Enter key
        if (charCode == 13)
        {
            // Do something, set controls focus or do anything
            return false;
        }
    
        // User can not type non alphanumeric characters
        if ( (charCode <  48)                     ||
             (charCode > 122)                     ||
             ((charCode > 57) && (charCode < 65)) ||
             ((charCode > 90) && (charCode < 97))
           )
        {
            // Show a message or do something
            return false;
        }
    }
    

    然后在代码后面的PageLoad事件中,使用下一个代码将属性添加到控件:

    Me.TextBox1.Attributes.Add("OnKeyPress", "return AlphanumericValidation(event);")
    
  • 380

    Cause

    默认情况下,ASP.NET会验证可能导致cross-site scripting(XSS)和SQL injections的潜在不安全内容的所有输入控件 . 因此,通过抛出上述异常,它不允许这样的内容 . 默认情况下,建议允许在每次回发时进行此检查 .

    Solution

    在许多情况下,您需要通过Rich TextBoxes或Rich Text Editors向页面提交HTML内容 . 在这种情况下,您可以通过将 @Page 指令中的ValidateRequest标记设置为false来避免此异常 .

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

    这将禁用对已将ValidateRequest标志设置为false的页面的请求的验证 . 如果要禁用此功能,请检查整个Web应用程序;您需要在web.config <system.web>部分将其设置为false

    <pages validateRequest ="false" />
    

    对于.NET 4.0或更高版本的框架,您还需要在<system.web>部分中添加以下行以完成上述工作 .

    <httpRuntime requestValidationMode = "2.0" />
    

    而已 . 我希望这可以帮助你摆脱上述问题 .

    参考:ASP.Net Error: A potentially dangerous Request.Form value was detected from the client

  • 4

    如果您使用的是.NET 4.0,请确保将其添加到 <system.web> 标记内的web.config文件中:

    <httpRuntime requestValidationMode="2.0" />
    

    在.NET 2.0中,请求验证仅适用于 aspx 请求 . 在.NET 4.0中,这扩展到包括 all 请求 . 通过指定以下内容,您可以在处理 .aspx 时恢复为仅执行XSS验证:

    requestValidationMode="2.0"
    

    您可以通过指定完全禁用请求验证:

    validateRequest="false"
    
  • 41

    您可以在Global.asax中捕获该错误 . 我仍然想验证,但显示适当的消息 . 在下面列出的博客上,可以获得这样的示例 .

    void Application_Error(object sender, EventArgs e)
        {
            Exception ex = Server.GetLastError();
    
            if (ex is HttpRequestValidationException)
            {
                Response.Clear();
                Response.StatusCode = 200;
                Response.Write(@"[html]");
                Response.End();
            }
        }
    

    重定向到另一个页面似乎也是对异常的合理回应 .

    http://www.romsteady.net/blog/2007/06/how-to-catch-httprequestvalidationexcep.html

  • 476

    如果您使用的是框架4.0,那么web.config中的条目(<pages validateRequest =“false”/>)

    <configuration>
        <system.web>
            <pages validateRequest="false" />
        </system.web>
    </configuration>
    

    如果您使用的是框架4.5,那么web.config中的条目(requestValidationMode =“2.0”)

    <system.web>
        <compilation debug="true" targetFramework="4.5" />
        <httpRuntime targetFramework="4.5" requestValidationMode="2.0"/>
    </system.web>
    

    如果你只想要单页,那么在你的aspx文件中你应该把第一行放在这样:

    <%@ Page EnableEventValidation="false" %>
    

    如果您已经有类似<%@ Page的内容,那么只需添加其余=> EnableEventValidation="false" %>

    我建议不要这样做 .

  • 13

    只要这些是 only "<"和">"(而不是双引号本身)字符,并且你在<input value =“this”/>这样的上下文中使用它们,你就是安全的(而对于<textarea>这个< / textarea>当然你会很脆弱) . 这可能会简化您的情况,但对于 anything 更多使用其他发布的解决方案 .

  • 13

    我认为你是通过尝试编码所有发布的数据从错误的角度攻击它 .

    请注意,“ < ”也可能来自其他外部源,如数据库字段,配置,文件,订阅源等 .

    此外,“ < ”本质上并不危险 . 它被编码为HTML输出(因为XSS) .

    在其他情况下,不同的子字符串是危险的,例如,如果您将用户提供的URL写入链接,则子字符串“ javascript: ”可能是危险的 . 另一方面,单引号字符在SQL查询中插入字符串时很危险,但如果它是从表单提交的名称的一部分或从数据库字段读取,则非常安全 .

    底线是:您无法过滤危险字符的随机输入,因为在适当的情况下任何字符都可能是危险的 . 您应该在某些特定字符可能变得危险的位置编码,因为它们会跨越到具有特殊含义的不同子语言 . 将字符串写入HTML时,应使用Server.HtmlEncode对HTML中具有特殊含义的字符进行编码 . 如果将字符串传递给动态SQL语句,则应编码不同的字符(或者更好,让框架通过使用预处理语句等为您完成) .

    如果您确定在任何地方进行HTML编码,则将字符串传递给HTML,然后在 .aspx 文件的 <%@ Page ... %> 指令中设置 validateRequest="false" .

    在.NET 4中,您可能需要做更多的事情 . 有时需要将 <httpRuntime requestValidationMode="2.0" /> 添加到web.config(reference) .

  • 45

    如果您确实需要特殊字符,如 > ,, < 等,请禁用页面验证 . 然后确保在显示用户输入时,数据是HTML编码的 .

    页面验证存在安全漏洞,因此可以绕过它 . 此外,不应仅依赖页面验证 .

    见:http://web.archive.org/web/20080913071637/http://www.procheckup.com:80/PDFs/bypassing-dot-NET-ValidateRequest.pdf

  • 1020

    我想你可以在一个模块中做到这一点;但这留下了一些问题;如果要将输入保存到数据库怎么办?突然之间,因为你将编码数据保存到数据库,你最终信任它的输入,这可能是一个坏主意 . 理想情况下,您每次都会将原始未编码数据存储在数据库中并进行编码 .

    禁用每页级别的保护,然后每次编码是一个更好的选择 .

    您应该从Microsoft ACE团队中查看更新,更完整的Anti-XSS library,而不是使用Server.HtmlEncode .

  • 206

    你可以HTML encode文本框内容,但不幸的是,赢了't stop the exception from happening. In my experience there is no way around, and you have to disable page validation. By doing that you'重新说:"I'll be careful, I promise."

  • 106

    请记住,某些.NET控件会自动对输出进行HTML编码 . 例如,在TextBox控件上设置.Text属性将自动对其进行编码 . 这特别意味着将 < 转换为 &lt;> 转换为 &gt; ,将 & 转换为 &amp; . 所以要小心这样做......

    myTextBox.Text = Server.HtmlEncode(myStringFromDatabase); // Pseudo code
    

    但是,HyperLink,Literal和Label的.Text属性不会对HTML进行编码,因此包装Server.HtmlEncode();如果您想阻止 <script> window.location = "http://www.google.com"; </script> 输出到您的页面并随后执行,那么必须在这些属性上设置任何内容 .

    做一些实验,看看什么编码,什么不编码 .

  • 70

    在web.config文件中,在标记内插入带有属性requestValidationMode =“2.0”的httpRuntime元素 . 还要在pages元素中添加validateRequest =“false”属性 .

    例:

    <configuration>
      <system.web>
       <httpRuntime requestValidationMode="2.0" />
      </system.web>
      <pages validateRequest="false">
      </pages>
    </configuration>
    
  • 48

    在ASP.NET中,您可以捕获异常并对其执行某些操作,例如显示友好消息或重定向到另一个页面...还有可能您可以自己处理验证...

    显示友好消息:

    protected override void OnError(EventArgs e)
    {
        base.OnError(e);
        var ex = Server.GetLastError().GetBaseException();
        if (ex is System.Web.HttpRequestValidationException)
        {
            Response.Clear();
            Response.Write("Invalid characters."); //  Response.Write(HttpUtility.HtmlEncode(ex.Message));
            Response.StatusCode = 200;
            Response.End();
        }
    }
    
  • 33

    我在每次回发之前都使用JavaScript来检查你不想要的字符,例如:

    <asp:Button runat="server" ID="saveButton" Text="Save" CssClass="saveButton" OnClientClick="return checkFields()" />
    
    function checkFields() {
        var tbs = new Array();
        tbs = document.getElementsByTagName("input");
        var isValid = true;
        for (i=0; i<tbs.length; i++) {
            if (tbs(i).type == 'text') {
                if (tbs(i).value.indexOf('<') != -1 || tbs(i).value.indexOf('>') != -1) {
                    alert('<> symbols not allowed.');
                    isValid = false;
                }
            }
        }
        return isValid;
    }
    

    当然,我的页面主要是数据输入,并且很少有元素可以进行回发,但至少保留了他们的数据 .

  • 23

    对于ASP.NET 4.0,您可以将标记作为特定页面的输入而不是整个站点,将其全部放在 <location> 元素中 . 这将确保您的所有其他页面都是安全的 . 您不需要在.aspx页面中放置 ValidateRequest="false" .

    <configuration>
    ...
      <location path="MyFolder/.aspx">
        <system.web>
          <pages validateRequest="false" />
          <httpRuntime requestValidationMode="2.0" />
        </system.web>
      </location>
    ...
    </configuration>
    

    在web.config中控制它更安全,因为您可以在站点级别看到哪些页面允许标记作为输入 .

    You still need to programmatically validate input on pages where request validation is disabled.

  • 20

    这个问题的答案很简单:

    var varname = Request.Unvalidated["parameter_name"];
    

    这将禁用特定请求的验证 .

  • 17

    之前的答案很棒,但没有人说过如何排除单个字段的HTML / JavaScript注入验证 . 我不知道以前的版本,但在MVC3 Beta中你可以这样做:

    [HttpPost, ValidateInput(true, Exclude = "YourFieldName")]
    public virtual ActionResult Edit(int id, FormCollection collection)
    {
        ...
    }
    

    这仍然验证除被排除的字段之外的所有字段 . 关于这一点的好处是你的验证属性仍然验证该字段,但您只是没有得到“从客户端检测到一个潜在危险的Request.Form值”异常 .

    我用它来验证正则表达式 . 我已经创建了自己的ValidationAttribute来查看正则表达式是否有效 . 由于正则表达式可以包含看起来像脚本的东西,我应用了上面的代码 - 如果正则表达式有效,它仍然被检查,但如果它包含脚本或HTML则不会被检查 .

  • 12

    另一种解决方案是

    protected void Application_Start()
    {
        ...
        RequestValidator.Current = new MyRequestValidator();
    }
    
    public class MyRequestValidator: RequestValidator
    {
        protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex)
        {
            bool result = base.IsValidRequestString(context, value, requestValidationSource, collectionKey, out validationFailureIndex);
    
            if (!result)
            {
                // Write your validation here
                if (requestValidationSource == RequestValidationSource.Form ||
                    requestValidationSource == RequestValidationSource.QueryString)
    
                    return true; // Suppress error message
            }
            return result;
        }
    }
    
  • 10

    如果您使用的是ASP.NET MVC,则会出现此错误的不同解决方案:

    C#样本:

    [HttpPost, ValidateInput(false)]
    public ActionResult Edit(FormCollection collection)
    {
        // ...
    }
    

    Visual Basic示例:

    <AcceptVerbs(HttpVerbs.Post), ValidateInput(False)> _
    Function Edit(ByVal collection As FormCollection) As ActionResult
        ...
    End Function
    
  • 9

    您还可以使用JavaScript的escape(string)函数替换特殊字符 . 然后服务器端使用Server . URLDecode(string)将其切换回来 .

    这样您就不必关闭输入验证,其他程序员可以更清楚地知道字符串可能包含HTML内容 .

  • 9

    对于MVC,通过添加忽略输入验证

    [ValidateInput(false)]

    在控制器中的每个动作之上 .

  • 6

    这里的其他解决方案都很不错,但是后面必须将[AllowHtml]应用于每个Model属性,这是一个很大的痛苦,特别是如果你在一个体面的网站上有超过100个模型 .

    如果像我一样,你想在网站范围内转换这个(恕我直言,毫无意义)功能,你可以覆盖基本控制器中的Execute()方法(如果你还没有基本控制器,我建议你制作一个,它们可以是对于应用常用功能非常有用) .

    protected override void Execute(RequestContext requestContext)
        {
            // Disable requestion validation (security) across the whole site
            ValidateRequest = false;
            base.Execute(requestContext);
        }
    

    只要确保你是HTML编码从用户输入的视图中抽出的所有内容(无论如何,它是带有Razor的ASP.NET MVC 3中的默认行为,所以除非出于某些奇怪的原因你使用的是Html.Raw()不应该要求此功能 .

  • 4

    我找到了一个使用JavaScript对数据进行编码的解决方案,该解析在.NET中解码(并且不需要jQuery) .

    • 使文本框成为HTML元素(如textarea)而不是ASP元素 .

    • 添加隐藏字段 .

    • 将以下JavaScript函数添加到 Headers 中 .
      function boo(){targetText = document.getElementById("HiddenField1"); sourceText = document.getElementById("userbox"); targetText.value = escape(sourceText.innerText); }

    在你的textarea中,包含一个调用boo()的onchange:

    <textarea id="userbox"  onchange="boo();"></textarea>
    

    最后,在.NET中,使用

    string val = Server.UrlDecode(HiddenField1.Value);
    

    我知道这是单向的 - 如果你需要双向,你必须要有创意,但如果你不能编辑web.config,这就提供了一个解决方案 .

    这是我(MC9000)通过jQuery提出并使用的一个例子:

    $(document).ready(function () {
    
        $("#txtHTML").change(function () {
            var currentText = $("#txtHTML").text();
            currentText = escape(currentText); // Escapes the HTML including quotations, etc
            $("#hidHTML").val(currentText); // Set the hidden field
        });
    
        // Intercept the postback
        $("#btnMyPostbackButton").click(function () {
            $("#txtHTML").val(""); // Clear the textarea before POSTing
                                   // If you don't clear it, it will give you
                                   // the error due to the HTML in the textarea.
            return true; // Post back
        });
    
    
    });
    

    和标记:

    <asp:HiddenField ID="hidHTML" runat="server" />
    <textarea id="txtHTML"></textarea>
    <asp:Button ID="btnMyPostbackButton" runat="server" Text="Post Form" />
    

    这很好用 . 如果黑客试图通过绕过JavaScript发布,他们只会看到错误 . 您也可以保存在数据库中编码的所有这些数据,然后将其(在服务器端)取消,并在显示在其他地方之前解析并检查攻击 .

  • 7

    似乎没有人提到下面的内容,但它解决了我的问题 . 在任何人说是的之前它是Visual Basic ...哎呀 .

    <%@ Page Language="vb" AutoEventWireup="false" CodeBehind="Example.aspx.vb" Inherits="Example.Example" **ValidateRequest="false"** %>
    

    我不知道是否有任何缺点,但对我来说,这真的很棒 .

  • 30

    在ASP.NET MVC(从版本3开始)中,您可以将AllowHtml属性添加到模型的属性中 .

    它允许请求在模型绑定期间通过跳过属性的请求验证来包含HTML标记 .

    [AllowHtml]
    public string Description { get; set; }
    
  • 4

    这些建议都不适合我 . 我无论如何都不想为整个网站关闭此功能,因为99%的时间我不希望我的用户在网络表单上放置HTML . 我只是创建了自己的方法,因为我是唯一一个使用这个特定应用程序的人 . 我将输入转换为后面代码中的HTML并将其插入到我的数据库中 .

相关问题