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

1289

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

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

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

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

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

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

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

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

  • 66
    Обратите внимание, что вы можете получить эту ошибку, если у вас также есть имена сущностей HTML (& amp;) или номера сущностей (& # 39;).
  • 17
    Ну, так как это мой вопрос, я чувствую, что могу определить, в чем суть: срывать весь процесс приложения и возвращать общее сообщение об ошибке, потому что кто-то набрал '<', это излишне. Тем более, что вы знаете, что большинство людей просто «validateRequest = false», чтобы избавиться от него, тем самым вновь открывая уязвимость
Показать ещё 4 комментария
Теги:
validation
asp.net-mvc
html-encode

43 ответа

1067
Лучший ответ

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

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

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

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

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

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

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

  • 0
    @Hightechrider спасибо за эту ссылку. Простая настройка validateRequest = "false" не работает для представления в ASP.Net MVC @olavk - Nice. Джоэл нашел время, чтобы прокомментировать ваш ответ.
  • 71
    Тем, кто приходит позже: validateRequest = "false" идет в директиве Page (первая строка вашего файла .aspx)
Показать ещё 19 комментариев
476

Там есть другое решение этой ошибки, если вы используете 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
  • 0
    проблема может возникнуть, когда это необходимо на одной странице всего приложения
  • 3
    Вы также можете добавить атрибут [ValidateInput (false)] на уровне класса. Если вы добавите его в базовый класс контроллера, он будет применяться ко всем действиям метода контроллера.
Показать ещё 2 комментария
361

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

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

[AllowHtml]
public string Description { get; set; }
  • 11
    Гораздо лучше сделать это декларативно, чем в контроллере!
  • 23
    Единственно правильный ответ! Отключение проверки действия контроллера является хакерским. И для отключения проверки на уровне приложения, разработчики должны быть повешены!
Показать ещё 8 комментариев
216

Если вы используете .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"
  • 30
    Внутри тегов <system.web> .
  • 7
    Я поместил это в web.config, но все равно с ошибкой «Потенциально опасное значение Request.Form»
Показать ещё 2 комментария
106

Для 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, потому что вы можете видеть на уровне сайта, какие страницы позволяют разметку в качестве входных данных.

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

  • 0
    Более подробная информация о requestValidationMode = 2 | 4 здесь: msdn.microsoft.com/en-us/library/…
  • 0
    К сожалению, это не будет работать с ASP.net 2.0 как есть. Удалите строку httpRuntime, и она будет работать.
Показать ещё 2 комментария
73

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

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

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

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

  • 10
    К сожалению, похоже, что функция исключения была удалена из MVC 3 RTW :(
  • 2
    Также он не был включен в MVC 4
Показать ещё 5 комментариев
48

В 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) {
    ...
}
  • 2
    Для меня validateRequest="false" не было необходимости, только requestValidationMode="2.0"
  • 0
    requestValidationMode = "2.0" по-прежнему генерирует ошибку с HTML-кодированными данными. Никакого решения, кроме как все кодировать в base64, а затем отправить его вместе.
43

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

    void Application_Error(object sender, EventArgs e)
    {
        Exception ex = Server.GetLastError();

        if (ex is HttpRequestValidationException)
        {
            Response.Clear();
            Response.StatusCode = 200;
            Response.Write(@"[html]");
            Response.End();
        }
    }

Перенаправление на другую страницу также представляется разумным ответом на исключение.

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

  • 0
    кажется простой вещью, но ее было трудно найти, поэтому я проголосовал ...
43

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

40

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

[ValidateInput (ложь)]

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

  • 0
    Похоже, это не работает в том случае, если он попадает в метод контроллера через настроенный маршрут.
  • 0
    На самом деле, техническое объяснение состоит в том, что это работает только тогда, когда оскорбительный символ находится в «строке запроса» ... если он находится в пути запроса, атрибут проверки не работает
33

Пожалуйста, имейте в виду, что некоторые элементы управления .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> не выводился на вашу страницу и впоследствии выполнялся.

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

29

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

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

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

  • 1
    Применимо только для ASP.NET 4.5 (и, по-видимому, что будет после него). Pre 4.5 не поддерживает это.
  • 3
    Я хотел бы столкнуться с этим. Я использую .NET 4.5, и это именно то, что мне было нужно, так как я не использую MVC и не могу изменить web.config.
Показать ещё 4 комментария
28

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

Пример:

<configuration>
  <system.web>
   <httpRuntime requestValidationMode="2.0" />
  </system.web>
  <pages validateRequest="false">
  </pages>
</configuration>
  • 1
    Для меня validateRequest = "false" не было необходимости, только requestValidationMode = "2.0"
  • 3
    Раздел «pages» должен находиться в разделе «system.web».
Показать ещё 2 комментария
23

Если вы не хотите отключать 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);")
  • 4
    Это по-прежнему оставляет приложение уязвимым от готовых запросов POST. У обычного пользователя будут проблемы с вводом символов, таких как, или: кавычки, но у обычного хакера не возникнет проблем с отправкой искаженных данных на сервер. Я бы об этом сказал.
  • 11
    @ Radu094: Это решение позволяет вам сохранить ValidateRequest = true, что означает, что хакеры по-прежнему будут поражать эту стену. Голосуйте ВВЕРХ, так как это делает вас менее уязвимым, чем отключение ValidateRequest.
19

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

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

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

  • 0
    Работает для веб-форм C # или VB
17

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

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;
    }
}
  • 0
    Ницца! Не было известно о возможности заменить запросчик проверки. Вместо того чтобы просто сказать «хорошо», как вы, я расширил эту идею, чтобы не проверять поля, заканчивающиеся на «_NoValidation» в качестве их имени. Код ниже.
  • 0
    Walden Leverich, для этого смотрите атрибуцию [AllowHtml]
Показать ещё 1 комментарий
13

В 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

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

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

  • 0
    работал как шарм для меня !!!
12

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

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

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

10

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

9

Причина

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 было обнаружено у клиента

9

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

  • 0
    Это хорошее решение. Это правильный ручной способ управлять им самостоятельно, а не аннулировать весь сайт или страницу
  • 0
    Убедитесь, что для текстовой области используется разметка HTML, а не элемент управления ASP.Net (т.е. нет runat = "server"), а затем используйте скрытый элемент управления ASP.Net для скрытого. Это лучшее решение, которое я видел без компромиссов. Естественно, вы хотите проанализировать ваши данные для XSS, SQL-инъекций на стороне сервера, но, по крайней мере, вы можете публиковать HTML
Показать ещё 1 комментарий
9

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

В моем случае пользователь ввел имя с символом á в имени роли (в отношении поставщика членства ASP.NET).

Я передаю имя роли методу предоставления пользователям этой роли, а запрос на отправку $.ajax терпел неудачу...

Я сделал это, чтобы решить проблему:

Вместо

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

Сделайте это

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

@Html.Raw сделал трюк.

Я получил имя роли как значение HTML roleName="Cadastro b&#225;s". Это значение с объектом HTML &#225; блокировалось ASP.NET MVC. Теперь я получаю значение параметра roleName так, как должно быть: roleName="Cadastro Básico" и механизм ASP.NET MVC больше не будет блокировать запрос.

9

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

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

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

  • 0
    Ссылка не работает.
7

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

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

6

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

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

  • 0
    Там должны быть большие скобки вместо маленьких скобок. Например, `if (tbs [i] .type == 'text') {` вместо `if (tbs (i) .type == 'text') {`
4

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

var nvc = Request.Unvalidated().Form;

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

4

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

4

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

  • 0
    пост сказал "валидатор" пожалуйста
4

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

3

Вы можете автоматически закодировать поле HTML в пользовательском приложении Binding. Мое решение несколько отличается, я помещаю ошибку в 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();
   }
}   
  • 0
    Пришел сюда просто чтобы опубликовать это. Жаль, что он останется навсегда похороненным на второй странице - это, ИМХО, лучшее решение.
3

Вам следует использовать метод Server.HtmlEncode для защиты вашего сайта от опасного ввода.

Дополнительная информация здесь

  • 2
    Используйте библиотеку Anti-XSS, чтобы предотвратить эту ошибку ... это неполно.
  • 0
    Дать немного больше объяснений о том, как это сделать, может быть полезно.
2

Как указано в моем комментарии к Sel answer, это наше расширение для персонализатора запроса.

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

Для тех, кто не использует привязку к модели, кто извлекает каждый параметр из Request.Form, которые уверены, что входной текст не причинит никакого вреда, есть другой способ. Не отличное решение, но оно выполнит эту работу.

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

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

Со стороны сервера, примите его и расшифруйте его как uri.
например:

var temp = HttpUtility.UrlDecode(HttpContext.Current.Request.Form["MsgBody"]);
  • 0
    Отлично, спасибо!
  • 0
    Рад помочь :) Кстати, ответ обновляется.
1

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

Предположим, что ваш веб-клиент отправляет запросы POST или PUT с помощью ajax и отправляет в ваш веб-сервис либо текстовые файлы json, либо xml, либо необработанные данные (содержимое файла). Поскольку вашему веб-сервису не требуется получать какую-либо информацию из заголовка Content-Type, ваш код JavaScript не задавал этот заголовок для вашего запроса ajax. Но если вы не установите этот заголовок в запросе ajax POST/PUT, Safari может добавить этот заголовок: "Content-Type: application/x-www-form-urlencoded". Я заметил, что на Safari 6 на iPhone, но другие версии Safari/OS или Chrome могут сделать то же самое. Поэтому, получая этот заголовок Content-Type, некоторые части.NET Framework предполагают, что структура данных тела запроса соответствует публикации в виде html-формы, а это не так, и возникает исключение HttpRequestValidationException. Первое, что нужно сделать, - это, очевидно, всегда устанавливать заголовок Content-Type на все, кроме формы MIME, на запрос ajax POST/PUT, даже если это бесполезно для вашего веб-сервиса.

Я также обнаружил эту деталь:
В этих обстоятельствах исключение HttpRequestValidationException увеличивается, когда ваш код пытается получить доступ к коллекции HttpRequest.Params. Но удивительно, что это исключение не увеличивается, когда он обращается к коллекции HttpRequest.ServerVariables. Это показывает, что, хотя эти две коллекции кажутся почти идентичными, один получает данные запроса через проверки безопасности, а другой - нет.

1

В.Net 4.0 и далее, что является обычным случаем, установите следующий параметр в system.web

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

1

И последнее, но не менее важное: обратите внимание, что элементы управления привязкой ASP.NET Data Data Binding автоматически кодируют значения во время привязки данных. Это изменяет поведение по умолчанию для всех элементов управления ASP.NET(TextBox, Label и т.д.), ItemTemplate в ItemTemplate. Следующий пример демонстрирует (значение ValidateRequest равно false):

ASPX

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

код за

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

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

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

public class S
{
    public string Text { get; set; }
}
  1. Значение представления аргумента: &#39;

Значение Label1.Text: &#39;

Значение TextBox2.Text: &amp;#39;

  1. Case submit: <script>alert('attack!');</script>

Значение Label1.Text: <script>alert('attack!');</script>

Значение TextBox2.Text: &lt;script&gt;alert(&#39;attack!&#39;);&lt;/script&gt;

1

Для тех из нас, кто все еще застрял в веб-формах, я нашел следующее решение, которое позволяет отключить проверку только в одном поле! (Я бы не хотел отключать его для всей страницы.)

VB.NET:

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

С#:

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

Теперь просто используйте <prefix:UnvalidatedTextBox id="test" runat="server" /> вместо <asp:TextBox, и он должен разрешить все символы (это идеально подходит для полей пароля!)

0

в моем случае, используя asp: Textbox control (Asp.net 4.5), вместо установки всей страницы для validateRequest="false" я использовал

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

в текстовом поле, которое вызвало исключение.

0

Решение

Мне не нравится отключать проверку сообщений (validateRequest = "false"). С другой стороны, неприемлемо, что приложение вылетает из-за того, что невинный пользователь набирает <x или что-то еще.

Поэтому я написал функцию javascript на стороне клиента (xssCheckValidates), которая делает предварительную проверку. Эта функция вызывается при попытке опубликовать данные формы, например:

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

Функция довольно проста и может быть улучшена, но она выполняет свою работу.

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

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

Вы можете попробовать это здесь:

    function xssCheckValidates() {
      var valid = true;
      var inp = document.querySelectorAll(
          "input:not(:disabled):not([readonly]):not([type=hidden])" +
          ",textarea:not(:disabled):not([readonly])");
      for (var i = 0; i < inp.length; i++) {
        if (!inp[i].readOnly) {
          if (inp[i].value.indexOf('<') > -1) {
            valid = false;
            break;
          }
          if (inp[i].value.indexOf('&#') > -1) {
            valid = false;
            break;
          }
        }
      }
      if (valid) {
        return true;
      } else {
        alert('In one or more of the text fields, you have typed\r\nthe character "<" or the character sequence "&#".\r\n\r\nThis is unfortunately not allowed since\r\nit can be used in hacking attempts.\r\n\r\nPlease edit the field and try again.');
        return false;
      }
    }
<form onsubmit="return xssCheckValidates();" >
  Try to type < or &# <br/>
  <input type="text" /><br/>
  <textarea></textarea>
  <input type="submit" value="Send" />
</form>
  • 0
    Вы должны предполагать, что любой код, который выполняется на клиенте, будет извращен.
  • 0
    @ user169771, прочитайте мой ответ еще раз, особенно часть, которая начинается с "Пожалуйста, обратите внимание, что цель этого состоит не в том, чтобы защитить систему от взлома ..."
0

Я вижу, что об этом много написано... и я не видел этого. Это было доступно с.NET Framework 4.5

Параметр ValidateRequestMode для элемента управления - отличный вариант. Таким образом, другие элементы управления на странице все еще защищены. Изменений в web.config не требуется.

 protected void Page_Load(object sender, EventArgs e)
    {
             txtMachKey.ValidateRequestMode = ValidateRequestMode.Disabled;
    }
  • 1
    @PruTahan .... а вам нужно комментировать каждый пост, потому что? Сообщение об ошибке OP вызвано одной из нескольких причин.
0

Используйте Server.HtmlEncode("yourtext");

-1

Попробуйте

Server.Encode

и

Server.HtmlDecode  при отправке и получении.

  • 1
    не работает с <или>
  • 1
    Вы даже не можете зайти так далеко (то есть вы не можете отправить обратно, так что ничего, что вы делаете с выделенным кодом, не будет работать) с проверкой на - вопрос пользователя.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню