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

发布于 2024-07-04 07:18:09 字数 535 浏览 10 评论 0原文

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

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

捕获异常并显示

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

对我来说似乎不够专业。

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

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

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

Every time a user posts something containing < or > in a page in my web application, I get this exception thrown.

I don't want to go into the discussion about the smartness of throwing an exception or crashing an entire web application because somebody entered a character in a text box, but I am looking for an elegant way to handle this.

Trapping the exception and showing

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

doesn't seem professional enough to me.

Disabling post validation (validateRequest="false") will definitely avoid this error, but it will leave the page vulnerable to a number of attacks.

Ideally: When a post back occurs containing HTML restricted characters, that posted value in the Form collection will be automatically HTML encoded.
So the .Text property of my text-box will be something & lt; html & gt;

Is there a way I can do this from a handler?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(30

方圜几里 2024-07-11 07:18:10

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

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

I ended up using JavaScript before each postback to check for the characters you didn't want, such as:

<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;
}

Granted my page is mostly data entry, and there are very few elements that do postbacks, but at least their data is retained.

酒与心事 2024-07-11 07:18:10

这里的其他解决方案很好,但是必须将 [AllowHtml] 应用于每个模型属性,这有点麻烦,特别是如果您在一个规模不错的网站上有超过 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() )不应该需要这个功能。

The other solutions here are nice, however it's a bit of a royal pain in the rear to have to apply [AllowHtml] to every single Model property, especially if you have over 100 models on a decent sized site.

If like me, you want to turn this (IMHO pretty pointless) feature off site wide you can override the Execute() method in your base controller (if you don't already have a base controller I suggest you make one, they can be pretty useful for applying common functionality).

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

Just make sure that you are HTML encoding everything that is pumped out to the views that came from user input (it's default behaviour in ASP.NET MVC 3 with Razor anyway, so unless for some bizarre reason you are using Html.Raw() you shouldn't require this feature.

江南烟雨〆相思醉 2024-07-11 07:18:10

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

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

You could also use JavaScript's escape(string) function to replace the special characters. Then server side use Server.URLDecode(string) to switch it back.

This way you don't have to turn off input validation and it will be more clear to other programmers that the string may have HTML content.

国粹 2024-07-11 07:18:10

另一个解决方案是:

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;
    }
}

Another solution is:

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;
    }
}
远昼 2024-07-11 07:18:10

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

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

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

Disable the page validation if you really need the special characters like, >, , <, etc. Then ensure that when the user input is displayed, the data is HTML-encoded.

There is a security vulnerability with the page validation, so it can be bypassed. Also the page validation shouldn't be solely relied on.

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

飘然心甜 2024-07-11 07:18:10

我也遇到了这个错误。

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

我将角色名称传递给一个方法来向用户授予该角色,而 $.ajax post 请求惨败...

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

而不是

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

这样做

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

@ Html.Raw 成功了。

我将角色名称作为 HTML 值 roleName="Cadastro bás" 获取。 HTML 实体 á 的该值被 ASP.NET MVC 阻止。 现在,我以应有的方式获取 roleName 参数值:roleName="Cadastro Básico" 并且 ASP.NET MVC 引擎将不再阻止该请求。

I was getting this error too.

In my case, a user entered an accented character á in a Role Name (regarding the ASP.NET membership provider).

I pass the role name to a method to grant Users to that role and the $.ajax post request was failing miserably...

I did this to solve the problem:

Instead of

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

Do this

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

@Html.Raw did the trick.

I was getting the Role name as HTML value roleName="Cadastro bás". This value with HTML entity á was being blocked by ASP.NET MVC. Now I get the roleName parameter value the way it should be: roleName="Cadastro Básico" and ASP.NET MVC engine won't block the request anymore.

凉城凉梦凉人心 2024-07-11 07:18:10

原因

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

解决方案

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

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

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

<pages validateRequest ="false" />

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

<httpRuntime requestValidationMode = "2.0" />

就是这样。 我希望这可以帮助您摆脱上述问题。

参考来源: ASP.Net 错误:从客户端检测到潜在危险的 Request.Form 值

Cause

ASP.NET by default validates all input controls for potentially unsafe contents that can lead to cross-site scripting (XSS) and SQL injections. Thus it disallows such content by throwing the above exception. By default it is recommended to allow this check to happen on each postback.

Solution

On many occasions you need to submit HTML content to your page through Rich TextBoxes or Rich Text Editors. In that case you can avoid this exception by setting the ValidateRequest tag in the @Page directive to false.

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

This will disable the validation of requests for the page you have set the ValidateRequest flag to false. If you want to disable this, check throughout your web application; you’ll need to set it to false in your web.config <system.web> section

<pages validateRequest ="false" />

For .NET 4.0 or higher frameworks you will need to also add the following line in the <system.web> section to make the above work.

<httpRuntime requestValidationMode = "2.0" />

That’s it. I hope this helps you in getting rid of the above issue.

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

玩心态 2024-07-11 07:18:10

如果您不想禁用 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);")

If you don't want to disable ValidateRequest you need to implement a JavaScript function in order to avoid the exception. It is not the best option, but it works.

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;
    }
}

Then in code behind, on the PageLoad event, add the attribute to your control with the next code:

Me.TextBox1.Attributes.Add("OnKeyPress", "return AlphanumericValidation(event);")
你是暖光i 2024-07-11 07:18:10

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

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

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

我建议不要这样做。

If you're using framework 4.0 then the entry in the web.config (<pages validateRequest="false" />)

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

If you're using framework 4.5 then the entry in the web.config (requestValidationMode="2.0")

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

If you want for only single page then, In you aspx file you should put the first line as this :

<%@ Page EnableEventValidation="false" %>

if you already have something like <%@ Page so just add the rest => EnableEventValidation="false" %>

I recommend not to do it.

贱贱哒 2024-07-11 07:18:10

对于那些不使用模型绑定、从 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; 

请查找 UrlDecodeUnescapeDataString 之间的差异

For those who are not using model binding, who are extracting each parameter from the Request.Form, who are sure the input text will cause no harm, there is another way. Not a great solution but it will do the job.

From client side, encode it as uri then send it.
e.g:

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

From server side, accept it and decode it as uri.
e.g:

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

or

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

please look for the differences between UrlDecode and UnescapeDataString

白龙吟 2024-07-11 07:18:10

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

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

    函数 boo() {
    targetText = document.getElementById("HiddenField1");
    sourceText = document.getElementById("用户框");
    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 进行发布,他们只会看到错误。 您也可以将所有这些编码的数据保存在数据库中,然后对其进行转义(在服务器端),并解析和保存。 在其他地方显示之前检查攻击。

I found a solution that uses JavaScript to encode the data, which is decoded in .NET (and doesn't require jQuery).

  • Make the textbox an HTML element (like textarea) instead of an ASP one.
  • Add a hidden field.
  • Add the following JavaScript function to your header.

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

In your textarea, include an onchange that calls boo():

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

Finally, in .NET, use

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

I am aware that this is one-way - if you need two-way you'll have to get creative, but this provides a solution if you cannot edit the web.config

Here's an example I (MC9000) came up with and use via 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
    });


});

And the markup:

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

This works great. If a hacker tries to post via bypassing JavaScript, they they will just see the error. You can save all this data encoded in a database as well, then unescape it (on the server side), and parse & check for attacks before displaying elsewhere.

月野兔 2024-07-11 07:18:10

在 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();
    }
}

In ASP.NET, you can catch the exception and do something about it, such as displaying a friendly message or redirect to another page... Also there is a possibility that you can handle the validation by yourself...

Display friendly message:

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();
    }
}
云醉月微眠 2024-07-11 07:18:10

就我而言,使用 asp:Textbox 控件 (Asp.net 4.5),而不是将所有页面设置为 validateRequest="false"

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

在导致异常的文本框中使用。

in my case, using asp:Textbox control (Asp.net 4.5), instead of setting the all page for validateRequest="false"
i used

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

on the Textbox that caused the exception.

祁梦 2024-07-11 07:18:10

您可以使用类似的内容:

var nvc = Request.Unvalidated().Form;

稍后,nvc["yourKey"] 应该可以工作。

You can use something like:

var nvc = Request.Unvalidated().Form;

Later, nvc["yourKey"] should work.

傾城如夢未必闌珊 2024-07-11 07:18:10

您可以在自定义 Model Binder 中自动对字段进行 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;
        }
    }
}

ErrorController:

public class ErrorController : Controller
 {
   public ActionResult InvalidUrl()
   {
      return View();
   }
}   

You can automatically HTML encode field in custom Model Binder. My solution some different, I put error in ModelState and display error message near the field. It`s easy to modify this code for automatically encode

 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);
        }
    }

In Application_Start:

ModelBinders.Binders.DefaultBinder = new AppModelBinder();

Note that it works only for form fields. Dangerous value not passed to controller model, but stored in ModelState and can be redisplayed on form with error message.

Dangerous chars in URL may be handled this way:

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;
        }
    }
}

ErrorController:

public class ErrorController : Controller
 {
   public ActionResult InvalidUrl()
   {
      return View();
   }
}   
或十年 2024-07-11 07:18:10

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

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

我不知道是否有任何缺点,但对我来说这非常有效。

It seems no one has mentioned the below yet, but it fixes the issue for me. And before anyone says yeah it's Visual Basic... yuck.

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

I don't know if there are any downsides, but for me this worked amazing.

依 靠 2024-07-11 07:18:10

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

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

您应该查看更新、更完整的 来自 Microsoft ACE 团队的反 XSS 库

I guess you could do it in a module; but that leaves open some questions; what if you want to save the input to a database? Suddenly because you're saving encoded data to the database you end up trusting input from it which is probably a bad idea. Ideally you store raw unencoded data in the database and the encode every time.

Disabling the protection on a per page level and then encoding each time is a better option.

Rather than using Server.HtmlEncode you should look at the newer, more complete Anti-XSS library from the Microsoft ACE team.

街道布景 2024-07-11 07:18:09

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

[验证输入(假)]

控制器中每个操作上方的

For MVC, ignore input validation by adding

[ValidateInput(false)]

above each Action in the Controller.

感情洁癖 2024-07-11 07:18:09

这个问题的答案很简单:

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

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

The answer to this question is simple:

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

This would disable validation for the particular request.

野却迷人 2024-07-11 07:18:09

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

You can HTML encode text box content, but unfortunately that won'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're saying: "I'll be careful, I promise."

那片花海 2024-07-11 07:18:09

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

You can catch that error in Global.asax. I still want to validate, but show an appropriate message. On the blog listed below, a sample like this was available.

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();
    }
}

Redirecting to another page also seems like a reasonable response to the exception.

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

酒几许 2024-07-11 07:18:09

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

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

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

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

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

您确定使用 HTML - 在将字符串传递给 HTML 的所有位置进行编码,然后在 中的 <%@ Page ... %> 指令中设置 ValidateRequest="false"。 aspx 文件。

在 .NET 4 中,您可能需要做更多的事情。 有时还需要将 添加到 web.config (参考)。

I think you are attacking it from the wrong angle by trying to encode all posted data.

Note that a "<" could also come from other outside sources, like a database field, a configuration, a file, a feed and so on.

Furthermore, "<" is not inherently dangerous. It's only dangerous in a specific context: when writing strings that haven't been encoded to HTML output (because of XSS).

In other contexts different sub-strings are dangerous, for example, if you write a user-provided URL into a link, the sub-string "javascript:" may be dangerous. The single quote character on the other hand is dangerous when interpolating strings in SQL queries, but perfectly safe if it is a part of a name submitted from a form or read from a database field.

The bottom line is: you can't filter random input for dangerous characters, because any character may be dangerous under the right circumstances. You should encode at the point where some specific characters may become dangerous because they cross into a different sub-language where they have special meaning. When you write a string to HTML, you should encode characters that have special meaning in HTML, using Server.HtmlEncode. If you pass a string to a dynamic SQL statement, you should encode different characters (or better, let the framework do it for you by using prepared statements or the like)..

When you are sure you HTML-encode everywhere you pass strings to HTML, then set ValidateRequest="false" in the <%@ Page ... %> directive in your .aspx file(s).

In .NET 4 you may need to do a little more. Sometimes it's necessary to also add <httpRuntime requestValidationMode="2.0" /> to web.config (reference).

混浊又暗下来 2024-07-11 07:18:09

如果您使用 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

There's a different solution to this error if you're using ASP.NET MVC:

C# sample:

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

Visual Basic sample:

<AcceptVerbs(HttpVerbs.Post), ValidateInput(False)> _
Function Edit(ByVal collection As FormCollection) As ActionResult
    ...
End Function
柠檬色的秋千 2024-07-11 07:18:09

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

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

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

In ASP.NET MVC (starting in version 3), you can add the AllowHtml attribute to a property on your model.

It allows a request to include HTML markup during model binding by skipping request validation for the property.

[AllowHtml]
public string Description { get; set; }
可爱咩 2024-07-11 07:18:09

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

<httpRuntime requestValidationMode="2.0" />

在 .NET 2.0 中,仅请求验证应用于 aspx 请求。 在 .NET 4.0 中,此范围已扩展为包括所有请求。 您可以通过指定恢复在处理 .aspx 时执行 XSS 验证:

requestValidationMode="2.0"

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

validateRequest="false"

If you are on .NET 4.0 make sure you add this in your web.config file inside the <system.web> tags:

<httpRuntime requestValidationMode="2.0" />

In .NET 2.0, request validation only applied to aspx requests. In .NET 4.0 this was expanded to include all requests. You can revert to only performing XSS validation when processing .aspx by specifying:

requestValidationMode="2.0"

You can disable request validate entirely by specifying:

validateRequest="false"
橙幽之幻 2024-07-11 07:18:09

对于 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 中控制这一点更安全,因为您可以在站点级别查看哪些页面允许标记作为输入。

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

For ASP.NET 4.0, you can allow markup as input for specific pages instead of the whole site by putting it all in a <location> element. This will make sure all your other pages are safe. You do NOT need to put ValidateRequest="false" in your .aspx page.

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

It is safer to control this inside your web.config, because you can see at a site level which pages allow markup as input.

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

忘你却要生生世世 2024-07-11 07:18:09

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

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

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

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

The previous answers are great, but nobody said how to exclude a single field from being validated for HTML/JavaScript injections. I don't know about previous versions, but in MVC3 Beta you can do this:

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

This still validates all the fields except for the excluded one. The nice thing about this is that your validation attributes still validate the field, but you just don't get the "A potentially dangerous Request.Form value was detected from the client" exceptions.

I've used this for validating a regular expression. I've made my own ValidationAttribute to see if the regular expression is valid or not. As regular expressions can contain something that looks like a script I applied the above code - the regular expression is still being checked if it's valid or not, but not if it contains scripts or HTML.

迷雾森÷林ヴ 2024-07-11 07:18:09

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

例子:

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

In the web.config file, within the tags, insert the httpRuntime element with the attribute requestValidationMode="2.0". Also add the validateRequest="false" attribute in the pages element.

Example:

<configuration>
  <system.web>
   <httpRuntime requestValidationMode="2.0" />
  </system.web>
  <pages validateRequest="false">
  </pages>
</configuration>
浅笑轻吟梦一曲 2024-07-11 07:18:09

请记住,某些 .NET 控件会自动对输出进行 HTML 编码。 例如,在 TextBox 控件上设置 .Text 属性将自动对其进行编码。 这具体意味着将 < 转换为 <,将 > 转换为 >& 变为 &。 因此,这样做要小心...

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

但是,HyperLink、Literal 和 Label 的 .Text 属性不会对内容进行 HTML 编码,因此请包装 Server.HtmlEncode(); 如果您想阻止 被输出到您的页面并随后执行。

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

Please bear in mind that some .NET controls will automatically HTML encode the output. For instance, setting the .Text property on a TextBox control will automatically encode it. That specifically means converting < into <, > into > and & into &. So be wary of doing this...

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

However, the .Text property for HyperLink, Literal and Label won't HTML encode things, so wrapping Server.HtmlEncode(); around anything being set on these properties is a must if you want to prevent <script> window.location = "http://www.google.com"; </script> from being output into your page and subsequently executed.

Do a little experimenting to see what gets encoded and what doesn't.

不奢求什么 2024-07-11 07:18:09

在 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) {
    ...
}

In ASP.NET MVC you need to set requestValidationMode="2.0" and validateRequest="false" in web.config, and apply a ValidateInput attribute to your controller action:

<httpRuntime requestValidationMode="2.0"/>

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

and

[Post, ValidateInput(false)]
public ActionResult Edit(string message) {
    ...
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文