asp.net - posible - Se detectó un valor Request.Form potencialmente peligroso del cliente
se detectó un posible valor request.path peligroso en el cliente web api (30)
Cada vez que un usuario publica algo que contiene <
o >
en una página de mi aplicación web, se produce esta excepción.
No quiero entrar en la discusión sobre la inteligencia de lanzar una excepción o bloquear una aplicación web completa porque alguien ingresó un personaje en un cuadro de texto, pero estoy buscando una forma elegante de manejar esto.
Atrapando la excepción y mostrando
Se ha producido un error, vuelva atrás y vuelva a escribir todo el formulario, pero esta vez no utilice <
no me parece lo suficientemente profesional
Deshabilitar la validación posterior ( validateRequest="false"
) definitivamente evitará este error, pero dejará la página vulnerable a una serie de ataques.
Idealmente: cuando se produzca una devolución que contenga caracteres restringidos de HTML, ese valor publicado en la colección de Formularios se codificará automáticamente en HTML. Así que la propiedad .Text
de mi cuadro de texto será something & lt; html & gt;
something & lt; html & gt;
¿Hay alguna manera de hacer esto desde un controlador?
Creo que lo estás atacando desde el ángulo equivocado al intentar codificar todos los datos publicados.
Tenga en cuenta que un " <
" también podría provenir de otras fuentes externas, como un campo de base de datos, una configuración, un archivo, una fuente, etc.
Además, " <
" no es inherentemente peligroso. Solo es peligroso en un contexto específico: al escribir cadenas que no se han codificado en la salida HTML (debido a XSS).
En otros contextos, diferentes sub-cadenas son peligrosas, por ejemplo, si escribe una URL proporcionada por el usuario en un enlace, la sub-cadena " javascript:
" puede ser peligrosa. El carácter de comillas simples, por otro lado, es peligroso al interpolar cadenas en consultas SQL, pero es perfectamente seguro si es parte de un nombre enviado desde un formulario o leído desde un campo de base de datos.
La conclusión es: no puede filtrar entradas aleatorias para caracteres peligrosos, porque cualquier carácter puede ser peligroso en las circunstancias adecuadas. Debe codificar en el punto en el que algunos caracteres específicos puedan volverse peligrosos porque se cruzan en un sublenguaje diferente donde tienen un significado especial. Cuando escribe una cadena en HTML, debe codificar los caracteres que tienen un significado especial en HTML, utilizando Server.HtmlEncode. Si pasa una cadena a una declaración de SQL dinámico, debe codificar diferentes caracteres (o mejor, deje que el marco lo haga por usted utilizando instrucciones preparadas o similares).
Cuando esté seguro de que codifica en HTML en todos los lugares donde pasa cadenas a HTML, establezca validateRequest="false"
en la directiva <%@ Page ... %>
en sus archivos .aspx
.
En .NET 4 puede que tengas que hacer un poco más. A veces también es necesario agregar <httpRuntime requestValidationMode="2.0" />
a web.config ( reference ).
Desactive la validación de la página si realmente necesita los caracteres especiales como, >
, <
, etc. Luego, asegúrese de que cuando se muestre la entrada del usuario, los datos estén codificados en HTML.
Existe una vulnerabilidad de seguridad con la validación de la página, por lo que se puede omitir. Además, la validación de la página no debe basarse únicamente en.
En ASP.NET MVC (a partir de la versión 3), puede agregar el atributo AllowHtml
a una propiedad en su modelo.
Permite que una solicitud incluya el marcado HTML durante el enlace del modelo omitiendo la validación de solicitud para la propiedad.
[AllowHtml]
public string Description { get; set; }
En ASP.NET MVC, debe establecer requestValidationMode = "2.0" y validateRequest = "false" en web.config, y aplicar un atributo ValidateInput a su acción de controlador:
<httpRuntime requestValidationMode="2.0"/>
<configuration>
<system.web>
<pages validateRequest="false" />
</system.web>
</configuration>
y
[Post, ValidateInput(false)]
public ActionResult Edit(string message) {
...
}
En ASP.NET, puede detectar la excepción y hacer algo al respecto, como mostrar un mensaje amigable o redirigir a otra página ... También existe la posibilidad de que pueda manejar la validación por sí mismo ...
Mostrar mensaje amigable:
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();
}
}
En el archivo web.config, dentro de las etiquetas, inserte el elemento httpRuntime con el atributo requestValidationMode = "2.0". También agregue el atributo validateRequest = "false" en el elemento pages.
Ejemplo:
<configuration>
<system.web>
<httpRuntime requestValidationMode="2.0" />
</system.web>
<pages validateRequest="false">
</pages>
</configuration>
Encontré una solución que utiliza JavaScript para codificar los datos, que se decodifica en .NET (y no requiere jQuery).
- Convierta el cuadro de texto en un elemento HTML (como textarea) en lugar de un ASP.
- Añade un campo oculto.
Agregue la siguiente función de JavaScript a su encabezado.
function boo () {targetText = document.getElementById ("HiddenField1"); sourceText = document.getElementById ("userbox"); targetText.value = escape (sourceText.innerText); }
En tu área de texto, incluye un onchange que llame a boo ():
<textarea id="userbox" onchange="boo();"></textarea>
Finalmente, en .NET, use
string val = Server.UrlDecode(HiddenField1.Value);
Soy consciente de que esto es unidireccional: si necesita dos vías, tendrá que ser creativo, pero esto proporciona una solución si no puede editar el archivo web.config
Aquí hay un ejemplo que se me ocurrió (MC9000) y uso a través de 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
});
});
Y el marcado:
<asp:HiddenField ID="hidHTML" runat="server" />
<textarea id="txtHTML"></textarea>
<asp:Button ID="btnMyPostbackButton" runat="server" Text="Post Form" />
Esto funciona muy bien. Si un hacker intenta publicar a través de JavaScript sin pasar, solo verán el error. También puede guardar todos estos datos codificados en una base de datos, luego, eliminarlos (en el lado del servidor) y analizar y verificar si hay ataques antes de mostrarlos en otro lugar.
Hay una solución diferente a este error si está utilizando ASP.NET MVC:
- ASP.NET MVC: las páginas validateRequest = false no funciona?
- ¿Por qué no funciona ValidateInput (False)?
- ASP.NET MVC RC1, VALIDATEINPUT, UNA SOLICITUD PELIGROSA POTENCIAL Y EL PITFALL
Muestra de C #:
[HttpPost, ValidateInput(false)]
public ActionResult Edit(FormCollection collection)
{
// ...
}
Ejemplo de Visual Basic:
<AcceptVerbs(HttpVerbs.Post), ValidateInput(False)> _
Function Edit(ByVal collection As FormCollection) As ActionResult
...
End Function
La respuesta a esta pregunta es simple:
var varname = Request.Unvalidated["parameter_name"];
Esto deshabilitaría la validación para la solicitud particular.
Las otras soluciones aquí son agradables, sin embargo, es un poco de un dolor real en la parte trasera tener que aplicar [AllowHtml] a cada propiedad del Modelo, especialmente si tiene más de 100 modelos en un sitio de tamaño decente.
Si, como yo, desea desactivar esta característica (IMHO bastante inútil) fuera del sitio, puede anular el método Execute () en su controlador base (si aún no tiene un controlador base, le sugiero que haga uno, pueden ser bastante útil para aplicar funcionalidad común).
protected override void Execute(RequestContext requestContext)
{
// Disable requestion validation (security) across the whole site
ValidateRequest = false;
base.Execute(requestContext);
}
Solo asegúrate de que estás codificando en HTML todo lo que se bombea a las vistas que provienen de la entrada del usuario (de todos modos, es el comportamiento predeterminado en ASP.NET MVC 3 con Razor, así que a menos que por alguna extraña razón estés usando Html.Raw ()) No debería requerir esta característica.
Las respuestas anteriores son excelentes, pero nadie dijo cómo excluir un solo campo para que no sea validado para inyecciones de HTML / JavaScript. No sé acerca de las versiones anteriores, pero en MVC3 Beta puedes hacer esto:
[HttpPost, ValidateInput(true, Exclude = "YourFieldName")]
public virtual ActionResult Edit(int id, FormCollection collection)
{
...
}
Esto todavía valida todos los campos excepto el excluido. Lo bueno de esto es que sus atributos de validación aún validan el campo, pero simplemente no obtiene las excepciones de "Se ha detectado un valor de Request.Form potencialmente peligroso desde el cliente".
He usado esto para validar una expresión regular. He creado mi propio ValidationAttribute para ver si la expresión regular es válida o no. Como las expresiones regulares pueden contener algo que se parece a un script, apliqué el código anterior: la expresión regular todavía se está verificando si es válida o no, pero no si contiene scripts o HTML.
Otra solución es:
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;
}
}
Para ASP.NET 4.0, puede permitir el marcado como entrada para páginas específicas en lugar de todo el sitio colocándolo todo en un elemento <location>
. Esto asegurará que todas tus otras páginas estén seguras. NO es necesario que ponga ValidateRequest="false"
en su página .aspx.
<configuration>
...
<location path="MyFolder/.aspx">
<system.web>
<pages validateRequest="false" />
<httpRuntime requestValidationMode="2.0" />
</system.web>
</location>
...
</configuration>
Es más seguro controlar esto dentro de su web.config, porque puede ver a nivel de sitio qué páginas permiten el marcado como entrada.
Aún necesita validar mediante programación la entrada en las páginas donde la validación de solicitudes está deshabilitada.
Para MVC, ignore la validación de entrada agregando
[ValidateInput (falso)]
por encima de cada acción en el controlador.
Parece que nadie ha mencionado lo siguiente todavía, pero soluciona el problema para mí. Y antes de que alguien diga sí, es Visual Basic ... asco.
<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="Example.aspx.vb" Inherits="Example.Example" **ValidateRequest="false"** %>
No sé si hay alguna desventaja, pero para mí esto funcionó de maravilla.
Puede codificar HTML en el contenido del cuadro de texto, pero desafortunadamente eso no detendrá la excepción. En mi experiencia, no hay manera de evitarlo, y tienes que deshabilitar la validación de la página. Al hacer eso estás diciendo: "Tendré cuidado, lo prometo".
Puedes atrapar ese error en Global.asax. Todavía quiero validar, pero mostrar un mensaje apropiado. En el blog que figura a continuación, una muestra como esta estaba disponible.
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();
}
}
Redirigir a otra página también parece ser una respuesta razonable a la excepción.
http://www.romsteady.net/blog/2007/06/how-to-catch-httprequestvalidationexcep.html
Si está en .NET 4.0, asegúrese de agregar esto en su archivo web.config dentro de las etiquetas <system.web>
:
<httpRuntime requestValidationMode="2.0" />
En .NET 2.0, la validación de solicitud solo se aplica a las solicitudes aspx
. En .NET 4.0 esto se expandió para incluir todas las solicitudes. Puede volver a realizar solo la validación XSS al procesar .aspx
especificando:
requestValidationMode="2.0"
Puede deshabilitar la validación de la solicitud por completo especificando:
validateRequest="false"
Si está utilizando framework 4.0, la entrada en web.config (<pages validateRequest = "false" />)
<configuration>
<system.web>
<pages validateRequest="false" />
</system.web>
</configuration>
Si está utilizando framework 4.5, la entrada en web.config (requestValidationMode = "2.0")
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" requestValidationMode="2.0"/>
</system.web>
Si solo desea una sola página, en su archivo aspx debe poner la primera línea así:
<%@ Page EnableEventValidation="false" %>
Si ya tienes algo como <% @ Page, solo agrega el resto => EnableEventValidation="false"
%>
Recomiendo no hacerlo.
Si no desea desactivar ValidateRequest, debe implementar una función de JavaScript para evitar la excepción. No es la mejor opción, pero funciona.
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;
}
}
Luego, en el código detrás, en el evento PageLoad, agregue el atributo a su control con el siguiente código:
Me.TextBox1.Attributes.Add("OnKeyPress", "return AlphanumericValidation(event);")
Siempre que estos sean solo los caracteres "<" y ">" (y no la comilla doble en sí) y los esté usando en el contexto como <input value = " this " />, estará seguro (mientras que para <textarea > esta </textarea> serias vulnerable por supuesto). Eso puede simplificar su situación, pero para algo más use una de las otras soluciones publicadas.
Supongo que podrías hacerlo en un módulo; pero eso deja abiertas algunas preguntas; ¿Qué pasa si desea guardar la entrada en una base de datos? De repente, debido a que está guardando datos codificados en la base de datos, terminará confiando en los datos de entrada que probablemente sean una mala idea. Lo ideal es almacenar los datos sin codificar sin procesar en la base de datos y la codificación cada vez.
Deshabilitar la protección en un nivel por página y luego codificar cada vez es una mejor opción.
En lugar de utilizar Server.HtmlEncode, debe consultar la biblioteca Anti-XSS más nueva y completa del equipo de Microsoft ACE.
También puede usar la función de escape(string) JavaScript para reemplazar los caracteres especiales. Entonces el lado del servidor utiliza el servidor. URLDecode(string) para volver a cambiarlo.
De esta manera, no tiene que desactivar la validación de entrada y será más claro para otros programadores que la cadena puede tener contenido HTML.
Tenga en cuenta que algunos controles .NET codificarán automáticamente la salida en HTML. Por ejemplo, establecer la propiedad .Text en un control TextBox lo codificará automáticamente. Eso significa específicamente convertir <
en <
, >
en >
y &
en &
. Así que ten cuidado de hacer esto ...
myTextBox.Text = Server.HtmlEncode(myStringFromDatabase); // Pseudo code
Sin embargo, la propiedad .Text para HyperLink, Literal y Label no codificará HTML, por lo que envuelve Server.HtmlEncode (); alrededor de cualquier cosa que se establezca en estas propiedades es una necesidad si desea evitar que <script> window.location = "http://www.google.com"; </script>
<script> window.location = "http://www.google.com"; </script>
de ser enviado a su página y posteriormente ejecutado.
Haga un poco de experimentación para ver qué se codifica y qué no.
Terminé usando JavaScript antes de cada devolución para verificar los caracteres que no querías, como:
<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;
}
Concedido, mi página es en su mayoría entrada de datos, y hay muy pocos elementos que hacen devoluciones de datos, pero al menos se conservan sus datos.
Yo también estaba recibiendo este error.
En mi caso, un usuario ingresó un carácter acentuado en un Nombre de rol (con respecto al proveedor de membresía de ASP.NET).
Pasé el nombre del rol a un método para otorgar a los usuarios ese rol y la solicitud de publicación de $.ajax
falló estrepitosamente ...
Hice esto para resolver el problema:
En lugar de
data: { roleName: ''@Model.RoleName'', users: users }
Hacer esto
data: { roleName: ''@Html.Raw(@Model.RoleName)'', users: users }
@Html.Raw
hizo el truco.
roleName="Cadastro bás"
el nombre del rol como valor HTML roleName="Cadastro bás"
. Este valor con entidad HTML á
estaba siendo bloqueado por ASP.NET MVC. Ahora obtengo el valor del parámetro roleName
como debe ser: roleName="Cadastro Básico"
y el motor ASP.NET MVC ya no bloqueará la solicitud.
Porque
Por defecto, ASP.NET valida todos los controles de entrada para contenidos potencialmente inseguros que pueden conducir a scripts entre sitios (XSS) e inyecciones de SQL . Por lo tanto, no permite dicho contenido lanzando la excepción anterior. De forma predeterminada, se recomienda permitir que se realice esta comprobación en cada devolución.
Solución
En muchas ocasiones, debe enviar contenido HTML a su página a través de Rich TextBoxes o Rich Text Editors. En ese caso, puede evitar esta excepción estableciendo la etiqueta ValidateRequest en la directiva @Page
en falso.
<%@ Page Language="C#" AutoEventWireup="true" ValidateRequest = "false" %>
Esto deshabilitará la validación de solicitudes para la página que ha establecido el indicador ValidateRequest en falso. Si desea deshabilitar esto, revise toda su aplicación web; deberá configurarlo como falso en su sección web.config <system.web>
<pages validateRequest ="false" />
Para marcos .NET 4.0 o superiores, también deberá agregar la siguiente línea en la sección <system.web> para que funcione lo anterior.
<httpRuntime requestValidationMode = "2.0" />
Eso es. Espero que esto te ayude a deshacerte del problema anterior.
Referencia por: Error de ASP.Net: Se detectó un valor Request.Form potencialmente peligroso del cliente
Puedes usar algo como:
var nvc = Request.Unvalidated().Form;
Más tarde, nvc["yourKey"]
debería funcionar.
Si solo quiere decirles a sus usuarios que <y> no deben usarse, PERO, no quiere que todo el formulario sea procesado / publicado de nuevo (y pierde toda la información) de antemano. ¿Validador alrededor del campo para seleccionar esos personajes (y quizás otros potencialmente peligrosos)?
Ninguna de las sugerencias funcionó para mí. No quería desactivar esta función para todo el sitio web de todos modos porque el 99% del tiempo no quiero que mis usuarios coloquen HTML en formularios web. Acabo de crear mi propio método de trabajo ya que soy el único que usa esta aplicación en particular. Convierto la entrada a HTML en el código que está detrás y la inserto en mi base de datos.