关于asp.net:从客户端检测到一个潜在危险的Request.Form值

关于asp.net:从客户端检测到一个潜在危险的Request.Form值

A potentially dangerous Request.Form value was detected from the client

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

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

捕获异常并显示

An error has occurred please go back and re-type your entire form again, but this time please do not use <

我觉得不够专业。

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

理想情况下:当出现包含HTML限制字符的回发时,表单集合中的该发布值将自动进行HTML编码。所以我的文本框的EDOCX1[3]属性将是EDOCX1[4]

有没有一种方法可以从一个处理程序做到这一点?


我认为你是从错误的角度攻击它,试图对所有发布的数据进行编码。

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

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

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

底线是:不能过滤危险字符的随机输入,因为在正确的情况下,任何字符都可能是危险的。您应该在某些特定的字符可能变得危险的时候进行编码,因为它们交叉进入一个不同的子语言,在那里它们有特殊的含义。将字符串写入HTML时,应使用server.html encode对HTML中具有特殊含义的字符进行编码。如果将字符串传递给动态SQL语句,则应编码不同的字符(或者更好的做法是,让框架使用准备好的语句或类似语句为您编码)。

当您确定在向HTML传递字符串的任何地方使用HTML编码时,然后在您的.aspx文件中的<%@ Page ... %>指令中设置validateRequest="false"

在.NET 4中,您可能需要再做一点。有时还需要添加Web.CONFIG(参考)的EDOCX1 6。


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

  • ASP.NET MVC–pages validateRequest=false不起作用?
  • 为什么validateInput(false)不起作用?
  • ASP.NET MVC RC1、validateInput、潜在的危险请求和陷阱

C样品:

1
2
3
4
5
[HttpPost, ValidateInput(false)]
public ActionResult Edit(FormCollection collection)
{
    // ...
}

Visual Basic示例:

1
2
3
4
<AcceptVerbs(HttpVerbs.Post), ValidateInput(False)> _
Function Edit(ByVal collection As FormCollection) As ActionResult
    ...
End Function

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

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

1
2
[AllowHtml]
public string Description { get; set; }

如果您在.NET 4.0上,请确保将此项添加到标记内的web.config文件中:

1
<httpRuntime requestValidationMode="2.0" />

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

1
requestValidationMode="2.0"

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

1
validateRequest="false"


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

1
2
3
4
5
6
7
8
9
10
<configuration>
...
  <location path="MyFolder/.aspx">
    <system.web>
      <pages validateRequest="false" />
      <httpRuntime requestValidationMode="2.0" />
    </system.web>
  </location>
...
</configuration>

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

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


前面的答案很好,但是没有人说过如何排除一个字段被验证为HTML/javascript注入。我不知道以前的版本,但在MVC3测试版中,您可以这样做:

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

这仍然会验证除排除字段之外的所有字段。这样做的好处是,验证属性仍然验证字段,但您没有收到"潜在危险的请求。从客户端检测到表单值"异常。

我用它来验证正则表达式。我创建了自己的validationAttribute来查看正则表达式是否有效。因为正则表达式可以包含类似于脚本的内容,所以我应用了上面的代码——如果正则表达式有效与否,它仍然会被检查,但是如果它包含脚本或HTML,则不会被检查。


在ASP.NET MVC中,需要在web.config中设置requestvalidationmode="2.0"和validateRequest="false",并将validateInput属性应用于控制器操作:

1
2
3
4
5
6
7
<httpRuntime requestValidationMode="2.0"/>

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

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

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


对于MVC,通过添加

[ValidateInput(false)]

在控制器中的每个动作上方。


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

1
2
3
4
5
6
7
8
9
10
11
12
    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


请记住,某些.NET控件将自动对输出进行HTML编码。例如,在文本框控件上设置.text属性将自动对其进行编码。具体地说就是把<转换成<>转换成>&转换成&。所以要小心这样做…

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

但是,hyperlink、literal和label的.text属性不会对事物进行HTML编码,因此如果要防止 window.location ="http://www.google.com"; 被输出到您的页面并随后执行,则必须将server.html encode()包装在这些属性上设置的任何内容周围。

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


这个问题的答案很简单:

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

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


在web.config文件的标记中,插入带有属性requestvalidationmode="2.0"的httpruntime元素。同时在pages元素中添加validateRequest="false"属性。

例子:

1
2
3
4
5
6
7
<configuration>
  <system.web>
   <httpRuntime requestValidationMode="2.0" />
  </system.web>
  <pages validateRequest="false">
  </pages>
</configuration>

如果不想禁用validateRequest,则需要实现一个javascript函数以避免出现异常。这不是最好的选择,但很有效。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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事件中,用下一个代码将属性添加到控件中:

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


似乎还没有人提到下面的内容,但它为我解决了这个问题。在有人说是的之前,这是视觉基础…讨厌。

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

我不知道有没有什么不好的地方,但对我来说,这真是太好了。


另一个解决方案是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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;
    }
}

如果您使用的是Framework 4.0,那么web.config中的条目()

1
2
3
4
5
<configuration>
    <system.web>
        <pages validateRequest="false" />
    </system.web>
</configuration>

如果您使用的是框架4.5,那么web.config中的条目(requestvalidationmode="2.0")。

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

如果只需要一页,那么在您的ASPX文件中,您应该将第一行如下所示:

1
<%@ Page EnableEventValidation="false" %>

如果您已经有了<%@页面,那么只需添加其余的=>EnableEventValidation="false"%>

我建议不要这样做。


在ASP.NET中,您可以捕获异常并对其进行一些处理,例如显示友好消息或重定向到另一页…还有一种可能性,你可以自己处理验证…

显示友好消息:

1
2
3
4
5
6
7
8
9
10
11
12
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();
    }
}

我想你可以在一个模块中完成它,但是这会带来一些问题;如果你想把输入保存到数据库中呢?突然,因为您将编码数据保存到数据库中,所以最终信任来自它的输入,这可能是个坏主意。理想情况下,您将原始未编码数据存储在数据库中,并每次编码。

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

与使用server.htmlencode相比,您应该查看来自Microsoft ACE团队的更新、更完整的Anti-XSS库。


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

  • 将文本框设置为HTML元素(如文本区域),而不是ASP元素。
  • 添加隐藏字段。
  • 将以下javascript函数添加到头部。

    函数boo()。{targetText=document.getElementByID("hiddenfield1");sourceText=document.getElementByID("用户框");targetText.value=转义(sourceText.innerText);}

在文本区域中,包括调用boo()的onchange:

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

最后,在.NET中,使用

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

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

下面是一个示例i(mc9000)通过jquery提出并使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$(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
    });


});

和标记:

1
<textarea id="txtHTML"></textarea>

这很管用。如果黑客试图通过绕过javascript来发帖,他们只会看到错误。您还可以将所有这些编码的数据保存在数据库中,然后(在服务器端)对其进行解压缩,并在显示到其他地方之前分析和检查攻击。


这里的其他解决方案也很不错,但是必须将[allowhtml]应用到每一个模型的属性上有点皇家的痛苦,特别是在一个相当大的站点上有超过100个模型的情况下。

如果像我一样,你想把这个(imho-pretty-pointless)功能关闭在站点范围内,你可以覆盖你的基础控制器中的execute()方法(如果你还没有一个基础控制器,我建议你做一个,它们对于应用公共功能非常有用)。

1
2
3
4
5
6
    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(),否则不应需要此功能。


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

页面验证存在安全漏洞,因此可以绕过它。同样,页面验证也不应该单独依赖。

参见:http://web.archive.org/web/20080913071637/http://www.procheckup.com:80/pdfs/bypassing-dot-net-validaterequest.pdf


原因

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

解决方案

在许多情况下,您需要通过富文本框或富文本编辑器向页面提交HTML内容。在这种情况下,可以通过将@Page指令中的validateRequest标记设置为false来避免此异常。

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

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

1
<pages validateRequest ="false" />

对于.NET 4.0或更高版本的框架,您还需要在部分添加以下行,以使上述功能正常工作。

1
<httpRuntime requestValidationMode ="2.0" />

就是这样。我希望这能帮助你解决上述问题。

引用者:ASP.NET错误:潜在危险的请求。从客户端检测到表单值


我也收到了这个错误。

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

我将角色名传递给一个方法,以授予用户该角色,而$.ajaxpost请求失败得很惨…

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

而不是

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

这样做

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

江户十一〔二〕耍了这个花招。

我得到的角色名是html值roleName="Cadastro bás"。该值与HTML实体á一起被ASP.NET MVC阻止。现在我得到了应该的roleName参数值:roleName="Cadastro Básico"和asp.net mvc引擎不再阻塞请求。


您还可以使用javascript的转义(字符串)函数替换特殊字符。然后服务器端使用server.urldecode(string)将其切换回。

这样,您就不必关闭输入验证,而且对于其他程序员来说,字符串可能包含HTML内容将更加清楚。


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;
}

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


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


您可以使用如下内容:

1
var nvc = Request.Unvalidated().Form;

后来,nvc["yourKey"]应该起作用了。


只要这些只是"<"和">"(而不是双引号本身)字符,并且您在上下文中使用它们,如,那么您是安全的(而对于您当然是易受攻击的)。这可能会简化您的情况,但对于更多的问题,请使用其他已发布的解决方案之一。


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


您可以在自定义模型活页夹中自动HTML编码字段。我的解决方案有些不同,我把错误放在ModelState中,并在字段附近显示错误消息。为了自动编码,很容易修改这个代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
 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);
        }
    }

在应用程序中启动:

1
ModelBinders.Binders.DefaultBinder = new AppModelBinder();

请注意,它只适用于表单域。危险值未传递到控制器模型,但存储在ModelState中,可以在窗体上重新显示,并显示错误消息。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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;
        }
    }
}

错误控制器:

1
2
3
4
5
6
7
public class ErrorController : Controller
 {
   public ActionResult InvalidUrl()
   {
      return View();
   }
}

您应该使用server.htmlencode方法来保护站点不受危险输入的影响。

更多信息在这里


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

1
2
3
4
5
6
7
8
9
10
11
12
13
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);
    }
}

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

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

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

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

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

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

请查看UrlDecodeUnescapeDataString之间的差异。


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

VB.NET:

1
2
3
4
5
6
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:

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

现在只需使用而不是,它应该允许所有字符(这对于密码字段是完美的!)


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

假设您的Web客户机使用Ajax发送POST或PUT请求,并向Web服务发送JSON或XML文本或原始数据(文件内容)。因为您的Web服务不需要从内容类型头中获取任何信息,所以您的javascript代码没有将此头设置为Ajax请求。但是,如果您没有在post/put-ajax请求上设置这个头,safari可能会添加这个头:"content-type:application/x-www-form-urlencoded"。我注意到在iPhone上的Safari 6上,但其他Safari版本/OS或Chrome也可以这样做。因此,在接收此内容类型头时,.NET框架的某些部分假定请求主体数据结构与HTML表单发布相对应,而不是,并引发httpRequestValidationException异常。首先要做的显然是,在post/put-ajax请求上,总是将content-type头设置为除表单mime类型之外的任何类型,即使它对您的Web服务没有用处。

我还发现了这个细节:在这些情况下,当代码尝试访问httpRequest.params集合时,httpRequestValidationException异常将上升。但令人惊讶的是,当访问httprequest.servervariables集合时,这个异常并没有增加。这表明,尽管这两个集合看起来几乎相同,但一个通过安全检查访问请求数据,另一个则不相同。


解决方案

我不想关闭后验证(validateRequest="false")。另一方面,应用程序崩溃是不可接受的,因为一个无辜的用户碰巧在或其他类型上发生了故障。

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

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

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

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

我之所以在这里说"是的一部分",是因为我听说内置请求验证可能不够,所以可能需要其他补充方法来进行完全保护。但是,我在这里介绍的javascript函数与保护系统无关。这只是为了确保用户不会有不好的体验。

你可以在这里试试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
    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

the character"<" or the character sequence"&#".



This is unfortunately not allowed since

it can be used in hacking attempts.



Please edit the field and try again.');
        return false;
      }
    }
1
2
3
4
5
6
<form onsubmit="return xssCheckValidates();">
  Try to type < or &# <br/>
  <input type="text" /><br/>
  <textarea></textarea>
  <input type="submit" value="Send" />
</form>


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

1
2
<system.web>
     <httpRuntime requestValidationMode="2.0" />

最后,请注意ASP.NET数据绑定控件在数据绑定期间自动对值进行编码。这将更改包含在ItemTemplate中的所有ASP.NET控件(文本框、标签等)的默认行为。下面的示例演示(ValidateRequest设置为false):

阿斯克斯

1
2
3
4
5
6
7
8
9
10
11
<%@ Page Language="C#" ValidateRequest="false" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication17._Default" %> <html> <body>
    <form runat="server">
       
            <ItemTemplate>
                </asp:TextBox>
               
               "></asp:Label>
               "></asp:TextBox>
            </ItemTemplate>
        </asp:FormView>
    </form>

代码落后

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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; }
}
  • 案件提交值:'
  • Label1.Text值:'

    TextBox2.Text值:&#39;

  • 案件提交值:alert('attack!');
  • Label1.Text值:alert('attack!');

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


    在我的例子中,使用asp:textbox控件(asp.net 4.5),而不是设置validateRequest="false"的所有页面。我用过

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

    在导致异常的文本框上。


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

    控件的validateRequestMode设置是一个很好的选项。这样,页面上的其他控件仍然受到保护。不需要更改web.config。

    1
    2
    3
    4
     protected void Page_Load(object sender, EventArgs e)
        {
                 txtMachKey.ValidateRequestMode = ValidateRequestMode.Disabled;
        }

    使用Server.HtmlEncode("yourtext");


    尝试用

    Server.Encode

    Server.HtmlDecode
    while sending and receiving.


    推荐阅读

      linux命令删除用户组?

      linux命令删除用户组?,管理,密码,系统,用户组,用户,概念,命令,文件,管理员,

      linux中用户创建命令?

      linux中用户创建命令?,密码,系统,用户,软件,命令,联系方式,管理,信息,用户

      linux注销命令用户?

      linux注销命令用户?,系统,服务,密码,地址,工作,命令,状态,工具,信息,基础,lin

      linux命令行创建用户?

      linux命令行创建用户?,系统,密码,软件,新增,用户,联系方式,管理,用户名,命

      linux系统用户命令?

      linux系统用户命令?,系统,工作,地址,信息,管理,命令,目录,时间,电脑,名称,请

      linux同步客户端命令?

      linux同步客户端命令?,时间,网络,服务,系统,认证,状态,管理,信息,分析,地址,l

      linux命令所有用户?

      linux命令所有用户?,系统,密码,信息,情况,名称,命令,用户,时间,地址,位置,如

      linux命令进入用户?

      linux命令进入用户?,系统,密码,用户,地址,信息,软件,命令,用户名,联系方式,

      linux命令用户管理?

      linux命令用户管理?,系统,密码,管理,工作,信息,地址,工具,命令,用户,基础,LIn

      linux用户与组的命令?

      linux用户与组的命令?,管理,系统,名称,用户组,密码,用户,命令,情况,信息,单

      linux添加用户的命令?

      linux添加用户的命令?,密码,系统,软件,联系方式,用户,新增,信息,管理人员,

      linux用户退出的命令?

      linux用户退出的命令?,系统,密码,命令,用户,发行,电脑,第三,地址,软件,信息,l

      linux看系统用户命令?

      linux看系统用户命令?,系统,信息,密码,命令,服务,名称,网络,情况,软件,工具,L

      linux赋权用户命令?

      linux赋权用户命令?,系统,密码,用户,权限,地址,状态,数字,软件,管理,电脑,Lin

      linux组加用户命令?

      linux组加用户命令?,系统,密码,联系方式,用户,软件,管理,命令,用户名,用户

      linux命令中添加用户?

      linux命令中添加用户?,系统,密码,软件,用户,命令,信息,目录,用户名,账号,文

      linux命令更改用户?

      linux命令更改用户?,系统,密码,管理,用户,命令,环境,工作,地址,电脑,文件,lin

      linux修改用户名命令?

      linux修改用户名命令?,系统,密码,查询系统,代码,数字,用户名,命令,第三,电

      linux命令给用户授权?

      linux命令给用户授权?,系统,数字,管理,权限,命令,密码,工具,时间,软件,信息,l