Потенциально опасный запрос.От клиента было обнаружено значение формы

StackOverflow https://stackoverflow.com/questions/81991

Вопрос

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

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

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

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

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

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

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

Есть ли способ, которым я могу сделать это с помощью обработчика?

Это было полезно?

Решение

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

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

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

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

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

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

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

Другие советы

Существует другое решение этой ошибки, если вы используете 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

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

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

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

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

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

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

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

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

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

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

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

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

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

[ValidateInput(ложь)]

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

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

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

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

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

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

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

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

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

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

Пример:

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

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

Затем в code behind, в событии PageLoad, добавьте атрибут к вашему элементу управления со следующим кодом:

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

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

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

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

Другим решением является:

protected void Application_Start()
{
    ...
    RequestValidator.Current = new MyRequestValidator();
}

public class MyRequestValidator: RequestValidator
{
    protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex)
    {
        bool result = base.IsValidRequestString(context, value, requestValidationSource, collectionKey, out validationFailureIndex);

        if (!result)
        {
            // Write your validation here
            if (requestValidationSource == RequestValidationSource.Form ||
                requestValidationSource == RequestValidationSource.QueryString)

                return true; // Suppress error message
        }
        return result;
    }
}

Если вы используете framework 4.0, то запись в web.config (<pages validateRequest="false" />)

<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" %>

если у вас уже есть что-то вроде <%@ Страница, так что просто добавьте остальное => EnableEventValidation="false" %>

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

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

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

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

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

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

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

    функция boo() { targetText = document.getElementById("Скрытое поле 1");Исходный текст = document.getElementById("userbox");targetText.value = escape(исходный текст.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, он просто увидит ошибку.Вы также можете сохранить все эти данные, закодированные в базе данных, затем отменить их экранирование (на стороне сервера) и проанализировать и проверить на наличие атак, прежде чем отображать в другом месте.

Потому что

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

Решение

Во многих случаях вам необходимо разместить HTML-контент на своей странице с помощью форматированных текстовых полей или редакторов форматированного текста.В этом случае вы можете избежать этого исключения, установив тег 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.Чистая ошибка:Потенциально опасный запрос.От клиента было обнаружено значение формы

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

Если, как и я, вы хотите отключить эту (ИМХО довольно бессмысленную) функцию от всего сайта, вы можете переопределить метод 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(), вам не должна требоваться эта функция.

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

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

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

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

Вместо того, чтобы

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 больше не будет блокировать запрос.

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

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

Видишь: http://web.archive.org/web/20080913071637/http://www.procheckup.com:80/PDFs/bypassing-dot-NET-ValidateRequest.pdf

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

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

В итоге я использовал 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;
}

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

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

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

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

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

var nvc = Request.Unvalidated().Form;

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top