Потенциально опасное значение Request.Form было обнаружено у клиента

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

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

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

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

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

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

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

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

Ответ 1

Я думаю, что вы атакуете его с неправильного угла, пытаясь закодировать все опубликованные данные.

Обратите внимание, что "<" также может поступать из других внешних источников, таких как поле базы данных, конфигурация, файл, фид и т.д.

Кроме того, "<" не является по своей сути опасным. Это опасно только в определенном контексте: при написании строк, которые не были закодированы для вывода HTML (из-за XSS).

В других контекстах разные подстроки опасны, например, если вы пишете URL-адрес, предоставленный пользователем, в ссылку, подстрока "javascript:" может быть опасной. Символ одиночной кавычки, с другой стороны, опасен при интерполяции строк в SQL-запросах, но совершенно безопасен, если он является частью имени, отправленного из формы или считанного из поля базы данных.

Суть в том, что вы не можете фильтровать случайный ввод для опасных символов, потому что любой персонаж может быть опасен при правильных обстоятельствах. Вы должны кодировать в точке, где некоторые конкретные символы могут стать опасными, потому что они пересекаются на другом подязыке, где они имеют особое значение. Когда вы пишете строку в HTML, вы должны кодировать символы, имеющие особое значение в HTML, используя Server.HtmlEncode. Если вы передаете строку в динамический оператор SQL, вы должны кодировать разные символы (или, лучше, пусть фреймворк сделает это для вас с помощью подготовленных операторов или тому подобного).

Когда вы уверены, что вы кодируете HTML-код везде, вы передаете строки в HTML, а затем установите validateRequest="false" в директиве <%@ Page ... %> в ваших файлах .aspx.

В .NET 4 вам может понадобиться немного больше. Иногда необходимо также добавить <httpRuntime requestValidationMode="2.0" /> в web.config(ссылка).

Ответ 2

Там есть другое решение этой ошибки, если вы используете ASP.NET MVC:

Пример С#:

[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

Ответ 3

В ASP.NET MVC (начиная с версии 3) вы можете добавить атрибут AllowHtml к свойству на вашей модели.

Он позволяет запросить включить HTML-разметку во время привязки к модели, пропустив проверку запроса для свойства.

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

Ответ 4

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

Ответ 5

Для ASP.NET 4.0 вы можете разрешить разметку как ввод для определенных страниц вместо всего сайта, поместив все это в элемент <location>. Это обеспечит безопасность всех ваших других страниц. Вам не нужно помещать ValidateRequest="false" на страницу .aspx.

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

Безопаснее контролировать это внутри вашего web.config, потому что вы можете видеть на уровне сайта, какие страницы позволяют разметку в качестве входных данных.

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

Ответ 6

Предыдущие ответы велики, но никто не сказал, как исключить проверку одного поля для встраивания HTML/JavaScript. Я не знаю о предыдущих версиях, но в MVC3 Beta вы можете это сделать:

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

Это все еще проверяет все поля, кроме исключенного. Самое приятное в том, что ваши атрибуты проверки по-прежнему проверяют поле, но вы просто не получаете "исключение из потенциально опасного параметра Request.Form из клиентских" исключений.

Я использовал это для проверки правильного выражения. Я сделал свой собственный ValidationAttribute, чтобы убедиться, что регулярное выражение действительно или нет. Поскольку регулярные выражения могут содержать что-то, что выглядит как script, я применил вышеуказанный код - регулярное выражение все еще проверяется, если оно действительно или нет, но не содержит скриптов или HTML.

Ответ 7

В ASP.NET MVC вам нужно установить requestValidationMode = "2.0" и validateRequest = "false" в web.config и применить атрибут ValidateInput к действию вашего контроллера:

<httpRuntime requestValidationMode="2.0"/>

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

и

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

Ответ 8

Вы можете кодировать текст в текстовом поле HTML, но, к сожалению, это не остановит исключение. По моему опыту нет пути, и вы должны отключить проверку страницы. Делая это, вы говорите: "Я буду осторожен, я обещаю".

Ответ 9

Для MVC игнорируйте проверку ввода, добавив

[ValidateInput (ложь)]

над каждым действием в контроллере.

Ответ 10

Вы можете поймать эту ошибку в 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

Ответ 11

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

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

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

Сделайте немного экспериментов, чтобы увидеть, что закодировано, а что нет.

Ответ 12

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

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

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

Ответ 13

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

Пример:

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

Ответ 14

Если вы не хотите отключать 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);")

Ответ 15

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

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

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

Ответ 16

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

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

Ответ 17

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

Ответ 18

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

Отключение защиты на уровне страницы и последующее кодирование - лучший вариант.

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

Ответ 19

Если вы используете фреймворк 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, так что просто добавьте rest = > EnableEventValidation="false"% >

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

Ответ 20

Другие решения здесь приятны, однако немного королевской боли в тылу приходится применять [AllowHtml] к каждому свойству модели, особенно если у вас более 100 моделей на сайте с приличным размером.

Если мне нравится, вы хотите отключить эту функцию (IMHO довольно бессмысленную) с сайта, вы можете переопределить метод Execute() в вашем базовом контроллере (если у вас еще нет базового контроллера, я предлагаю вам сделать это, они могут быть весьма полезны для применения общей функциональности).

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

Просто убедитесь, что вы являетесь HTML-кодированием всего, что перекачивается в представления, поступающие с пользовательского ввода (это поведение по умолчанию в ASP.NET MVC 3 с Razor в любом случае, поэтому, если только по какой-то странной причине вы используете Html.Raw(), вы не должны использовать эту функцию.

Ответ 21

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

Существует уязвимость безопасности при проверке страницы, поэтому ее можно обойти. Также не следует полагаться только на проверку страницы.

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

Ответ 22

Я тоже получал эту ошибку.

В моем случае пользователь ввел имя с символом á в имени роли (в отношении поставщика членства 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 больше не будет блокировать запрос.

Ответ 23

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

Ответ 24

Причина

ASP.NET по умолчанию проверяет все элементы управления входами для потенциально опасного содержимого, которое может привести к межсайтовому скриптингу (XSS) и SQL-инъекции. Таким образом, он запрещает такое содержимое, бросая вышеуказанное исключение. По умолчанию рекомендуется разрешить эту проверку при каждой обратной передаче.

Решение

Во многих случаях вам нужно отправить HTML-контент на свою страницу через Rich TextBoxes или Rich Text Editors. В этом случае вы можете избежать этого исключения, установив тег ValidateRequest в директиве @Page равным false.

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

Это отключит проверку запросов на страницу, на которую установлен флаг ValidateRequest, на значение false. Если вы хотите отключить это, проверьте всю свою веб-приложение; вам нужно установить его в false в разделе web.config < system.web >

<pages validateRequest ="false" />

Для платформ .NET 4.0 или выше вам также необходимо добавить следующую строку в разделе < system.web > , чтобы сделать вышеприведенную работу.

<httpRuntime requestValidationMode = "2.0" />

Вот оно. Надеюсь, это поможет вам избавиться от вышеуказанной проблемы.

Ссылка на: Ошибка ASP.Net: потенциально опасное значение Request.Form было обнаружено у клиента

Ответ 25

Вы также можете использовать функцию JavaScript escape (string) для замены специальных символов. Затем серверная серверная серверная служба URLDecode (строка), чтобы вернуть его обратно.

Таким образом, вам не нужно отключать проверку ввода, и другим программистам будет понятно, что строка может содержать содержимое HTML.

Ответ 26

Я закончил с использованием 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;
}

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

Ответ 27

Пока это только "<" и " > " (а не только двойные кавычки), и вы используете их в контексте типа < input value = "this"/ > , вы в безопасности (в то время как для <textarea> this </textarea> , вы были бы уязвимы, конечно). Это может упростить вашу ситуацию, но для ничего больше использовать одно из других опубликованных решений.

Ответ 28

Если вы просто хотите сказать своим пользователям, что < и > не должны использоваться НО, вы не хотите, чтобы вся форма обрабатывалась/отправлялась назад (и теряла все входные данные), прежде чем вы могли бы просто не помещать валидатор вокруг поля для экранирования для этих (и, возможно, других потенциально опасных)?

Ответ 29

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

Ответ 30

Вы можете использовать что-то вроде:

var nvc = Request.Unvalidated().Form;

Позже nvc["yourKey"] должен работать.