net - csrf c#
¿Cómo proteger contra CSRF por defecto en ASP.NET MVC 4? (4)
¿Hay alguna forma de garantizar que los formularios ASP.NET MVC 4 estén protegidos contra CSRF de forma predeterminada?
Por ejemplo, ¿hay alguna manera de que AntiForgeryToken se aplique automáticamente a todos los formularios tanto en las vistas como en las acciones del controlador?
Antecedentes de esta pregunta: Impedir la falsificación de solicitudes entre sitios (CSRF) mediante el asistente AntiForgeryToken () de ASP.NET MVC y la Anatomía de un ataque de falsificación de solicitudes entre sitios .
He usado FXCop para escribir dos reglas de análisis de código, una que requiere que se aplique un atributo HttpMethod a todas las acciones del controlador y una segunda que requiere que cualquier acción que tenga un atributo HttpPost también deba tener un atributo RequiresAntiForgeryToken.
Esto funcionó bien para nosotros. Las reglas no son particularmente difíciles de escribir
Puede usar un proveedor de filtros con la condición de que el filtro ValidateAntiForgeryTokenAttribute () se aplique siempre que HttpContext.Request.HttpMethod == "POST".
Básicamente, seguí el enfoque genérico descrito por Phil Haack y agregué la condición apropiada:
// Ensure all POST actions are automatically decorated with the ValidateAntiForgeryTokenAttribute.
( c, a ) => string.Equals( c.HttpContext.Request.HttpMethod, "POST", StringComparison.OrdinalIgnoreCase ) ?
new ValidateAntiForgeryTokenAttribute() : null
Una forma de hacerlo sería modificar las plantillas T4 en ASP.NET MVC que crean formularios, para que inserten este código automáticamente:
<% using(Html.Form("UserProfile", "SubmitUpdate")) { %>
<%= Html.AntiForgeryToken() %>
<!-- rest of form goes here -->
<% } %>
Y, por supuesto, necesita el atributo correspondiente en el método del controlador:
[ValidateAntiForgeryToken]
public ViewResult SubmitUpdate()
{
// ... etc
}
Realmente no es tan difícil adaptar una aplicación de esta manera, a menos que sea inusualmente grande. La última aplicación que escribí en MVC probablemente me lleve un par de horas para actualizarla.
Para agregar a la excelente respuesta de osoviejo, las instrucciones a continuación, de mi reciente publicación de blog en CSRF , ponen su trabajo junto con la información en el blog de Phil en una respuesta integral.
ASP.NET/MVC proporciona un mecanismo para esto: puede agregar a una colección de filtros en el objeto FilterProviders
global. Esto le permite dirigirse a algunos controladores y no a otros, agregando la función de seguridad necesaria.
Primero, necesitamos implementar un IFilterProvider. A continuación, puede encontrar la clase Proveedor de filtro condicional de Phil Haack. Comience agregando esta clase a su proyecto.
public class ConditionalFilterProvider : IFilterProvider
{
private readonly
IEnumerable<Func<ControllerContext, ActionDescriptor, object>> _conditions;
public ConditionalFilterProvider(
IEnumerable<Func<ControllerContext, ActionDescriptor, object>> conditions)
{
_conditions = conditions;
}
public IEnumerable<Filter> GetFilters(
ControllerContext controllerContext,
ActionDescriptor actionDescriptor)
{
return from condition in _conditions
select condition(controllerContext, actionDescriptor) into filter
where filter != null
select new Filter(filter, FilterScope.Global, null);
}
}
A continuación, agregue el código a Application_Start que agrega un nuevo ConditionalFilterProvider
a la colección global FilterProviders que garantiza que todos los métodos de control POST requerirán AntiForgeryToken.
IEnumerable<Func<ControllerContext, ActionDescriptor, object>> conditions =
new Func<ControllerContext, ActionDescriptor, object>[] {
// Ensure all POST actions are automatically
// decorated with the ValidateAntiForgeryTokenAttribute.
( c, a ) => string.Equals( c.HttpContext.Request.HttpMethod, "POST",
StringComparison.OrdinalIgnoreCase ) ?
new ValidateAntiForgeryTokenAttribute() : null
};
var provider = new ConditionalFilterProvider(conditions);
// This line adds the filter we created above
FilterProviders.Providers.Add(provider);
Si implementa los dos códigos anteriores, su aplicación MVC debería requerir AntiForgeryToken para cada POST del sitio. Puede probarlo en el sitio web de ejemplo CSRF de Phil Haack: una vez protegido, el ataque CSRF lanzará System.Web.Mvc.HttpAntiForgeryException
sin tener que agregar la anotación [ValidateAntiForgeryToken]
. Esto descarta una gran cantidad de vulnerabilidades relacionadas con "programadores olvidadizos".