1545

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

我不想讨论由于有人在文本框中输入了一个字符而引发异常或使整个 Web 应用程序崩溃的聪明之处,但我正在寻找一种优雅的方式来处理这个问题。

捕获异常并显示

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

对我来说似乎不够专业。

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

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

有没有办法从处理程序中做到这一点?

4

47 回答 47

1124

我认为您通过尝试对所有发布的数据进行编码来从错误的角度对其进行攻击。

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

此外,“ <”本身并不危险。它仅在特定上下文中是危险的:当编写尚未编码为 HTML 输出的字符串时(因为 XSS)。

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

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

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

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

于 2008-09-17T11:26:23.030 回答
524

如果您使用的是 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
于 2009-10-08T22:56:30.173 回答
433

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

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

[AllowHtml]
public string Description { get; set; }
于 2011-09-05T09:33:36.187 回答
218

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

<httpRuntime requestValidationMode="2.0" />

在 .NET 2.0 中,请求验证仅适用于aspx请求。在 .NET 4.0 中,这被扩展为包括所有请求。您可以在处理时恢复为执行 XSS 验证,方法.aspx是指定:

requestValidationMode="2.0"

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

validateRequest="false"
于 2010-07-30T04:51:29.697 回答
118

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

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

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

您仍然需要以编程方式验证禁用请求验证的页面上的输入。

于 2012-11-27T17:22:15.530 回答
73

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

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

这仍然会验证除排除字段之外的所有字段。这样做的好处是您的验证属性仍然验证该字段,但您只是没有收到“从客户端检测到潜在危险的 Request.Form 值”异常。

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

于 2010-11-06T14:58:46.003 回答
53

在 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) {
    ...
}
于 2010-11-30T12:56:45.707 回答
50

您可以对文本框内容进行 HTML 编码,但不幸的是,这并不能阻止异常的发生。根据我的经验,没有办法,您必须禁用页面验证。这样做是在说:“我会小心的,我保证。”

于 2008-09-17T11:20:03.653 回答
47

这个问题的答案很简单:

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

这将禁用对特定请求的验证。

于 2013-04-25T20:56:17.357 回答
43

您可以在 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

于 2009-10-13T22:37:18.767 回答
43

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

[验证输入(假)]

在Controller中的每个Action之上。

于 2014-01-29T09:40:05.307 回答
35

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

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

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

做一些实验,看看什么被编码,什么没有。

于 2008-09-17T14:40:25.717 回答
29

在 web.config 文件的标记中,插入属性为 requestValidationMode="2.0" 的 httpRuntime 元素。还要在 pages 元素中添加 validateRequest="false" 属性。

例子:

<configuration>
  <system.web>
   <httpRuntime requestValidationMode="2.0" />
  </system.web>
  <pages validateRequest="false">
  </pages>
</configuration>
于 2012-03-14T22:20:43.247 回答
24

如果您不想禁用 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);")
于 2009-01-12T17:35:03.980 回答
21

似乎还没有人提到以下内容,但它为我解决了这个问题。在有人说是之前,它是 Visual Basic ......糟糕。

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

我不知道是否有任何缺点,但对我来说,这太棒了。

于 2012-01-27T15:01:37.053 回答
21

另一种解决方案是:

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;
    }
}
于 2013-12-08T05:39:56.990 回答
15

如果您使用的是框架 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"%>

我建议不要这样做。

于 2015-12-10T07:35:47.357 回答
14

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

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

与其使用 Server.HtmlEncode,不如查看 Microsoft ACE 团队提供的更新、更完整的 Anti-XSS 库

于 2008-09-17T11:26:53.433 回答
14

在 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();
    }
}
于 2012-07-17T20:19:11.183 回答
12

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

  • 使文本框成为 HTML 元素(如 textarea)而不是 ASP 元素。
  • 添加隐藏字段。
  • 将以下 JavaScript 函数添加到您的标头。

    函数 boo() { targetText = document.getElementById("HiddenField1"); sourceText = document.getElementById("userbox"); targetText.value = escape(sourceText.innerText); }

在您的文本区域中,包含一个调用 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 来发帖,他们只会看到错误。您也可以将所有这些编码的数据保存在数据库中,然后将其取消转义(在服务器端),并在显示其他位置之前解析和检查攻击。

于 2014-09-16T15:31:21.020 回答
12

原因

默认情况下,ASP.NET 会针对可能导致跨站点脚本(XSS) 和SQL 注入的潜在不安全内容验证所有输入控件。因此,它通过抛出上述异常来禁止此类内容。默认情况下,建议允许在每次回发时进行此检查。

解决方案

在许多情况下,您需要通过富文本框或富文本编辑器将 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 错误:从客户端检测到潜在危险的 Request.Form 值

于 2015-06-15T06:44:17.133 回答
10

这里的其他解决方案很好,但是必须将 [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()不应该需要这个功能。

于 2012-03-16T14:34:52.413 回答
9

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

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

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

于 2008-09-17T11:32:43.297 回答
9

我也收到了这个错误。

在我的例子中,用户在角色名称中输入了一个重音字符á(关于 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"。带有 HTML 实体的这个值&#225;被 ASP.NET MVC 阻止。现在我以应有roleName的方式获取参数值:roleName="Cadastro Básico"并且 ASP.NET MVC 引擎将不再阻止请求。

于 2012-08-14T15:27:07.107 回答
8

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

这样您就不必关闭输入验证,并且其他程序员会更清楚字符串可能包含 HTML 内容。

于 2012-02-11T02:33:11.943 回答
7

我最终在每次回发之前使用 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;
}

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

于 2012-08-03T15:22:12.793 回答
6

你可以使用类似的东西:

var nvc = Request.Unvalidated().Form;

后来,nvc["yourKey"]应该工作。

于 2013-05-31T22:55:36.583 回答
5

对于那些不使用模型绑定,从 Request.Form 中提取每个参数,确定输入文本不会造成伤害的人,还有另一种方法。不是一个很好的解决方案,但它会完成这项工作。

从客户端,将其编码为 uri 然后发送。
例如:

encodeURIComponent($("#MsgBody").val());  

从服务器端,接受它并将其解码为 uri。
例如:

string temp = !string.IsNullOrEmpty(HttpContext.Current.Request.Form["MsgBody"]) ?
System.Web.HttpUtility.UrlDecode(HttpContext.Current.Request.Form["MsgBody"]) : 
null;  

或者

string temp = !string.IsNullOrEmpty(HttpContext.Current.Request.Form["MsgBody"]) ?
System.Uri.UnescapeDataString(HttpContext.Current.Request.Form["MsgBody"]) : 
null; 

UrlDecode请寻找和之间的区别UnescapeDataString

于 2018-07-24T05:17:31.443 回答
4

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

于 2008-09-17T11:28:22.807 回答
4

如果您只是想告诉您的用户不要使用 < 和 >,那么您不希望事先处理/回发整个表单(并丢失所有输入),您可以不简单地放入字段周围的验证器来筛选那些(可能还有其他潜在危险的)字符?

于 2008-09-17T11:41:07.597 回答
4

没有任何建议对我有用。无论如何,我不想为整个网站关闭此功能,因为 99% 的时间我不希望我的用户将 HTML 放在 Web 表单上。我刚刚创建了自己的解决方法,因为我是唯一使用此特定应用程序的人。我在后面的代码中将输入转换为 HTML 并将其插入到我的数据库中。

于 2013-02-17T19:40:01.127 回答
4

正如我对Sel 的回答所指出的,这是我们对自定义请求验证器的扩展。

public class SkippableRequestValidator : RequestValidator
{
    protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex)
    {
        if (collectionKey != null && collectionKey.EndsWith("_NoValidation"))
        {
            validationFailureIndex = 0;
            return true;
        }

        return base.IsValidRequestString(context, value, requestValidationSource, collectionKey, out validationFailureIndex);
    }
}
于 2014-05-01T20:04:07.207 回答
4

您可以在自定义模型绑定器中自动对字段进行 HTML 编码。我的解决方案有些不同,我在 ModelState 中输入错误并在字段附近显示错误消息。修改此代码以自动编码很容易

 public class AppModelBinder : DefaultModelBinder
    {
        protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
        {
            try
            {
                return base.CreateModel(controllerContext, bindingContext, modelType);
            }
            catch (HttpRequestValidationException e)
            {
                HandleHttpRequestValidationException(bindingContext, e);
                return null; // Encode here
            }
        }
        protected override object GetPropertyValue(ControllerContext controllerContext, ModelBindingContext bindingContext,
            PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder)
        {
            try
            {
                return base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder);
            }
            catch (HttpRequestValidationException e)
            {
                HandleHttpRequestValidationException(bindingContext, e);
                return null; // Encode here
            }
        }

        protected void HandleHttpRequestValidationException(ModelBindingContext bindingContext, HttpRequestValidationException ex)
        {
            var valueProviderCollection = bindingContext.ValueProvider as ValueProviderCollection;
            if (valueProviderCollection != null)
            {
                ValueProviderResult valueProviderResult = valueProviderCollection.GetValue(bindingContext.ModelName, skipValidation: true);
                bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
            }

            string errorMessage = string.Format(CultureInfo.CurrentCulture, "{0} contains invalid symbols: <, &",
                     bindingContext.ModelMetadata.DisplayName);

            bindingContext.ModelState.AddModelError(bindingContext.ModelName, errorMessage);
        }
    }

在 Application_Start 中:

ModelBinders.Binders.DefaultBinder = new AppModelBinder();

请注意,它仅适用于表单字段。危险值未传递给控制器​​模型,但存储在 ModelState 中,并且可以在表单上重新显示并显示错误消息。

URL 中的危险字符可以这样处理:

private void Application_Error(object sender, EventArgs e)
{
    Exception exception = Server.GetLastError();
    HttpContext httpContext = HttpContext.Current;

    HttpException httpException = exception as HttpException;
    if (httpException != null)
    {
        RouteData routeData = new RouteData();
        routeData.Values.Add("controller", "Error");
        var httpCode = httpException.GetHttpCode();
        switch (httpCode)
        {
            case (int)HttpStatusCode.BadRequest /* 400 */:
                if (httpException.Message.Contains("Request.Path"))
                {
                    httpContext.Response.Clear();
                    RequestContext requestContext = new RequestContext(new HttpContextWrapper(Context), routeData);
                    requestContext.RouteData.Values["action"] ="InvalidUrl";
                    requestContext.RouteData.Values["controller"] ="Error";
                    IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory();
                    IController controller = factory.CreateController(requestContext, "Error");
                    controller.Execute(requestContext);
                    httpContext.Server.ClearError();
                    Response.StatusCode = (int)HttpStatusCode.BadRequest /* 400 */;
                }
                break;
        }
    }
}

错误控制器:

public class ErrorController : Controller
 {
   public ActionResult InvalidUrl()
   {
      return View();
   }
}   
于 2016-02-25T08:17:06.400 回答
4

在我的情况下,使用 asp:Textbox 控件(Asp.net 4.5),而不是设置validateRequest="false" 我使用的所有页面

<asp:TextBox runat="server" ID="mainTextBox"
            ValidateRequestMode="Disabled"
 ></asp:TextBox>

在导致异常的文本框上。

于 2018-12-03T08:54:35.213 回答
3

您应该使用 Server.HtmlEncode 方法来保护您的站点免受危险输入。

更多信息在这里

于 2008-09-17T11:21:33.230 回答
3

一个办法

我不喜欢关闭帖子验证 (validateRequest="false")。另一方面,应用程序崩溃只是因为无辜的用户碰巧键入<x或其他东西是不可接受的。

因此,我编写了一个客户端 javascript 函数 (xssCheckValidates) 进行初步检查。当尝试发布表单数据时调用此函数,如下所示:

<form id="form1" runat="server" onsubmit="return xssCheckValidates();">

该功能非常简单,可以改进,但它正在发挥作用。

请注意,这样做的目的不是为了保护系统免受黑客攻击,而是为了保护用户免受不良体验。在服务器上完成的请求验证仍然处于打开状态,这是系统保护的(部分)(在它能够做到的范围内)。

我在这里说“部分”的原因是因为我听说内置的请求验证可能还不够,因此可能需要其他补充手段来获得全面保护。但是,我在这里介绍的 javascript 函数与保护系统无关。只是为了确保用户不会有糟糕的体验。

你可以在这里试试:

    function xssCheckValidates() {
      var valid = true;
      var inp = document.querySelectorAll(
          "input:not(:disabled):not([readonly]):not([type=hidden])" +
          ",textarea:not(:disabled):not([readonly])");
      for (var i = 0; i < inp.length; i++) {
        if (!inp[i].readOnly) {
          if (inp[i].value.indexOf('<') > -1) {
            valid = false;
            break;
          }
          if (inp[i].value.indexOf('&#') > -1) {
            valid = false;
            break;
          }
        }
      }
      if (valid) {
        return true;
      } else {
        alert('In one or more of the text fields, you have typed\r\nthe character "<" or the character sequence "&#".\r\n\r\nThis is unfortunately not allowed since\r\nit can be used in hacking attempts.\r\n\r\nPlease edit the field and try again.');
        return false;
      }
    }
<form onsubmit="return xssCheckValidates();" >
  Try to type < or &# <br/>
  <input type="text" /><br/>
  <textarea></textarea>
  <input type="submit" value="Send" />
</form>

于 2018-04-03T21:44:58.837 回答
2

我看到有很多关于这个的文章......我没有看到提到这个。这从 .NET Framework 4.5 开始可用

控件的ValidateRequestMode设置是一个很好的选择。这样页面上的其他控件仍然受到保护。无需更改 web.config。

 protected void Page_Load(object sender, EventArgs e)
 {
     txtMachKey.ValidateRequestMode = ValidateRequestMode.Disabled;
 }
于 2018-03-30T14:06:40.393 回答
2

我知道这个问题是关于表单发布的,但我想为在其他情况下收到此错误的人添加一些详细信息。它也可能发生在用于实现 Web 服务的处理程序上。

假设您的 Web 客户端使用 ajax 发送 POST 或 PUT 请求,并将 json 或 xml 文本或原始数据(文件内容)发送到您的 Web 服务。因为您的 Web 服务不需要从 Content-Type 标头中获取任何信息,所以您的 JavaScript 代码没有将此标头设置为您的 ajax 请求。但是,如果您没有在 POST/PUT ajax 请求中设置此标头,Safari 可能会添加此标头:“Content-Type: application/x-www-form-urlencoded”。我在 iPhone 上的 Safari 6 上观察到,但其他 Safari 版本/操作系统或 Chrome 可能会这样做。因此,当接收到这个 Content-Type 标头时,.NET Framework 的某些部分假定请求正文数据结构对应于一个 html 表单发布,而它不对应,并引发 HttpRequestValidationException 异常。

我还发现了这个细节:
在这些情况下,当您的代码尝试访问 HttpRequest.Params 集合时,会出现 HttpRequestValidationException 异常。但令人惊讶的是,当它访问 HttpRequest.ServerVariables 集合时,并没有出现这个异常。这表明虽然这两个集合看起来几乎相同,但一个通过安全检查访问请求数据,而另一个则没有。

于 2018-05-04T11:43:37.570 回答
1

使用Server.HtmlEncode("yourtext");

于 2016-04-19T14:27:05.170 回答
1

对于我们这些仍然停留在网络表单上的人,我发现了以下解决方案,使您只能禁用一个字段的验证!(我不想为整个页面禁用它。)

VB.NET:

Public Class UnvalidatedTextBox
    Inherits TextBox
    Protected Overrides Function LoadPostData(postDataKey As String, postCollection As NameValueCollection) As Boolean
        Return MyBase.LoadPostData(postDataKey, System.Web.HttpContext.Current.Request.Unvalidated.Form)
    End Function
End Class

C#:

public class UnvalidatedTextBox : TextBox
{
    protected override bool LoadPostData(string postDataKey, NameValueCollection postCollection)
    {
        return base.LoadPostData(postDataKey, System.Web.HttpContext.Current.Request.Unvalidated.Form);
    }
}

现在只需使用<prefix:UnvalidatedTextBox id="test" runat="server" />而不是<asp:TextBox,它应该允许所有字符(这对于密码字段来说是完美的!)

于 2017-01-16T14:48:57.993 回答
1

最后但同样重要的是,请注意 ASP.NET 数据绑定控件在数据绑定期间自动对值进行编码。这会更改ItemTemplate. 以下示例演示(ValidateRequest设置为 false):

aspx

<%@ Page Language="C#" ValidateRequest="false" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication17._Default" %> <html> <body>
    <form runat="server">
        <asp:FormView ID="FormView1" runat="server" ItemType="WebApplication17.S" SelectMethod="FormView1_GetItem">
            <ItemTemplate>
                <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
                <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
                <asp:Label ID="Label1" runat="server" Text="<%#: Item.Text %>"></asp:Label>
                <asp:TextBox ID="TextBox2" runat="server" Text="<%#: Item.Text %>"></asp:TextBox>
            </ItemTemplate>
        </asp:FormView>
    </form> 

后面的代码

public partial class _Default : Page
{
    S s = new S();

    protected void Button1_Click(object sender, EventArgs e)
    {
        s.Text = ((TextBox)FormView1.FindControl("TextBox1")).Text;
        FormView1.DataBind();
    }

    public S FormView1_GetItem(int? id)
    {
        return s;
    }
}

public class S
{
    public string Text { get; set; }
}
  1. 案例提交值:&#39;

Label1.Text价值:&#39;

TextBox2.Text价值:&amp;#39;

  1. 案例提交值:<script>alert('attack!');</script>

Label1.Text价值:<script>alert('attack!');</script>

TextBox2.Text价值:&lt;script&gt;alert(&#39;attack!&#39;);&lt;/script&gt;

于 2018-01-27T20:10:44.100 回答
0

在 .Net 4.0 及更高版本(通常情况下)中,将以下设置放入 system.web

<system.web>
     <httpRuntime requestValidationMode="2.0" />
于 2018-03-15T19:16:55.987 回答
0

如何为 ASP.NET 4.6.2 中的 AjaxExtControls 解决此问题:

我们在使用 AjaxExtControls 富文本编辑器时遇到了同样的问题。此问题在从 .NET 2.0 升级到 .NET 4.5 后立即开始。我查看了所有 SOF 答案,但找不到不损害 .NET 4.5 提供的安全性的解决方案。

修复 1(不推荐,因为它会降低应用程序的安全性):我在更改此属性后进行了测试 requestValidationMode = "2.0,它有效,但我担心安全功能。所以这个修复就像降低整个应用程序的安全性。

修复 2(推荐):由于此问题仅发生在 AjaxExtControl 之一中,因此我终于能够使用以下简单代码解决此问题:

editorID.value = editorID.value.replace(/>/g, "&gt;");
editorID.value = editorID.value.replace(/</g, "&lt;");

在将请求发送到服务器之前,此代码在客户端(javascript)上执行。请注意,editorID 不是我们在 html/aspx 页面上的 ID,而是 AjaxExtControl 内部使用的富文本编辑器的 ID。

于 2020-05-06T16:33:48.407 回答
0

我有一个 Web 表单应用程序,它的文本框评论字段存在此问题,用户有时会在其中粘贴电子邮件文本,并且电子邮件标题信息中的“<”和“>”字符会潜入其中并引发此异常。

我从另一个角度解决了这个问题……我已经在使用 Ajax Control Toolkit,所以我能够使用 FilteredTextBoxExtender 来防止这两个字符进入文本框中。然后,用户复制粘贴文本将得到他们所期望的,减去这些字符。

<asp:TextBox ID="CommentsTextBox" runat="server" TextMode="MultiLine"></asp:TextBox>
<ajaxToolkit:FilteredTextBoxExtender ID="ftbe" runat="server" TargetControlID="CommentsTextBox" filterMode="InvalidChars" InvalidChars="<>" />
于 2021-04-08T16:18:39.397 回答
0

没有一个答案对我有用。然后我发现如果我删除以下代码,我可以让它工作:

//Register action filter via Autofac rather than GlobalFilters to allow dependency injection
builder.RegisterFilterProvider();
builder.RegisterType<OfflineActionFilter>()
    .AsActionFilterFor<Controller>()
    .InstancePerLifetimeScope();

我只能得出结论,Autofac 的 RegisterFilterProvider 中的某些内容会破坏或覆盖 validateRequest 属性

于 2021-12-13T09:41:03.483 回答
0

即使在添加<httpRuntime requestValidationMode="2.0">到 web.config 之后,我仍然在使用 WIF 进行身份验证的应用程序中不断收到错误消息。
为我解决的问题是在元素<sessionState mode="InProc" cookieless="UseUri"/>内部添加。<system.web>

于 2022-01-26T16:33:22.250 回答
-1

尝试

Server.Encode

Server.HtmlDecode 在发送和接收时。

于 2015-03-31T10:50:19.623 回答