От клиента было обнаружено потенциально опасное значение Request.Form - PullRequest
1397 голосов
/ 17 сентября 2008

Каждый раз, когда пользователь публикует что-то, содержащее < или > на странице в моем веб-приложении, я получаю это исключение.

Я не хочу вдаваться в дискуссию о целесообразности создания исключения или сбоя всего веб-приложения, потому что кто-то ввел символ в текстовое поле, но я ищу элегантный способ справиться с этим. *

Перехват исключения и отображение

Произошла ошибка. Вернитесь и введите заново всю форму, но на этот раз, пожалуйста, не используйте <</p>

мне не кажется достаточно профессиональным.

Отключение проверки сообщений (validateRequest="false") определенно позволит избежать этой ошибки, но сделает страницу уязвимой для ряда атак.

В идеале: когда происходит обратная запись, содержащая ограниченные символы HTML, это опубликованное значение в коллекции Form будет автоматически закодировано в HTML. Таким образом, свойство .Text моего текстового поля будет something & lt; html & gt;

Есть ли способ сделать это из обработчика?

Ответы [ 43 ]

33 голосов
/ 17 сентября 2008

Пожалуйста, имейте в виду, что некоторые элементы управления .NET будут автоматически HTML-кодировать выходные данные. Например, установка свойства .Text в элементе управления TextBox автоматически закодирует его. Это, в частности, означает преобразование < в &lt;, > в &gt; и & в &amp;. Так что будьте осторожны с этим ...

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

Однако свойство .Text для HyperLink, Literal и Label не будет кодировать HTML-объекты, поэтому оборачиваем Server.HtmlEncode (); все, что установлено в этих свойствах, является обязательным, если вы хотите предотвратить вывод <script> window.location = "http://www.google.com"; </script> на вашу страницу и последующее выполнение.

Проведите небольшой эксперимент, чтобы увидеть, что кодируется, а что нет.

32 голосов
/ 26 апреля 2013

Ответ на этот вопрос прост:

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

Это отключит проверку для конкретного запроса.

27 голосов
/ 15 марта 2012

В файле web.config в тегах вставьте элемент httpRuntime с атрибутом requestValidationMode = "2.0". Также добавьте атрибут validateRequest = "false" в элементе pages.

Пример:

<configuration>
  <system.web>
   <httpRuntime requestValidationMode="2.0" />
  </system.web>
  <pages validateRequest="false">
  </pages>
</configuration>
23 голосов
/ 12 января 2009

Если вы не хотите отключать 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);")
20 голосов
/ 27 января 2012

Кажется, никто еще не упомянул ниже, но это решает проблему для меня. И прежде чем кто-нибудь скажет: да, это Visual Basic ... блин.

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

Я не знаю, есть ли минусы, но для меня это сработало потрясающе.

18 голосов
/ 08 декабря 2013

Другое решение:

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;
    }
}
14 голосов
/ 10 декабря 2015

Если вы используете 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"%>

Рекомендую не делать этого.

13 голосов
/ 18 июля 2012

В 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();
    }
}
12 голосов
/ 17 сентября 2008

Я думаю, вы могли бы сделать это в модуле; но это оставляет открытыми некоторые вопросы; Что делать, если вы хотите сохранить входные данные в базе данных? Внезапно, поскольку вы сохраняете закодированные данные в базу данных, вы в конечном итоге доверяете вводу данных, что, вероятно, является плохой идеей. В идеале вы должны хранить необработанные незакодированные данные в базе данных и каждый раз кодировать.

Лучше отключить защиту на уровне страницы и затем каждый раз кодировать.

Вместо использования Server.HtmlEncode вы должны взглянуть на более новую, более полную библиотеку Anti-XSS от команды Microsoft ACE.

10 голосов
/ 16 сентября 2014

Я нашел решение, использующее JavaScript для кодирования данных, которое декодируется в .NET (и не требует jQuery).

  • Сделать текстовое поле элементом HTML (например, textarea) вместо элемента ASP.
  • Добавить скрытое поле.
  • Добавьте следующую функцию JavaScript в свой заголовок.

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

В вашей текстовой области включите onchange, который вызывает boo ():

<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, он просто увидит ошибку. Вы также можете сохранить все эти данные, закодированные в базе данных, затем удалить их (на стороне сервера) и проанализировать и проверить на наличие атак, прежде чем отображать их в другом месте.

...