Jak domyślnie chronić przed CSRF w ASP.NET MVC 4?

Czy jest sposób na zapewnienie ASP.NET formularze MVC 4 są domyślnie chronione przed CSRF?

Na przykład, czy istnieje sposób, aby AntiForgeryToken Automatycznie zastosować do wszystkich form zarówno w widokach, jak i akcjach kontrolera?

Kontekst tego pytania: zapobieganie fałszowaniu żądań między stronami (CSRF) przy użyciu ASP.NET MVC ' s AntiForgeryToken() helperi Anatomy of a Cross-site Request Forgery Attack .

Author: Fernando Correia, 2012-04-01

4 answers

aby dodać do doskonałej odpowiedzi osoviejo, instrukcje poniżej, z mojego ostatniego blog post na CSRF , umieścić swoją pracę wraz z informacjami na blogu Phila w jednej kompleksowej odpowiedzi.

ASP.NET/MVC zapewnia mechanizm tego: możesz dodać do kolekcji filtrów w globalnym obiekcie FilterProviders. Pozwala to na kierowanie na niektóre kontrolery, a nie na inne, dodając wymaganą funkcję zabezpieczeń.

Najpierw musimy zaimplementować IFilterProvider. Poniżej, możesz znaleźć klasę Phila Haacka Conditional Filter Provider . Zacznij od dodania tej klasy do swojego projektu.

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

Następnie dodaj kod do Application_Start, który dodaje nową ConditionalFilterProvider do kolekcji global FilterProviders, która zapewnia, że wszystkie metody kontrolera POST będą wymagały 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);

Jeśli zaimplementujesz dwa fragmenty kodu powyżej, Twoja aplikacja MVC powinna wymagać AntiForgeryToken dla każdego posta na stronie. Możesz wypróbować na Przykładowa strona internetowa Phila Haacka CSRF - po zabezpieczeniu atak CSRF rzuci System.Web.Mvc.HttpAntiForgeryException bez konieczności dodawania adnotacji [ValidateAntiForgeryToken]. To wyklucza cały szereg luk związanych z "zapominalskim programistą".

 22
Author: Kyle Hodgson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-10 04:28:00

Można użyć dostawcy filtrów z warunkiem, że filtr ValidateAntiForgeryTokenAttribute() będzie stosowany za każdym razem, gdy HttpContext.Prośba.HttpMethod = = "POST".

Zasadniczo zastosowałem podejście ogólne opisane przez Phila Haacka i dodałem odpowiedni warunek:

// Ensure all POST actions are automatically decorated with the ValidateAntiForgeryTokenAttribute.
( c, a ) => string.Equals( c.HttpContext.Request.HttpMethod, "POST", StringComparison.OrdinalIgnoreCase ) ?
 new ValidateAntiForgeryTokenAttribute() : null
 11
Author: osoviejo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-15 20:21:09

Użyłem FXCop do napisania dwóch reguł analizy kodu. jedna z nich wymaga, aby atrybut HttpMethod był stosowany do wszystkich akcji kontrolera, a druga, która wymaga każdej akcji, która ma atrybut HttpPost, musi mieć również atrybut Requieresantiforgerytoken.

To działało dobrze dla nas. Zasady nie są szczególnie trudne do napisania

 2
Author: martin308,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-02 09:40:56

Jednym ze sposobów na to byłoby zmodyfikowanie szablonów T4 w ASP.NET MVC, które tworzą formularze, aby automatycznie wstawiły ten kod:

<% using(Html.Form("UserProfile", "SubmitUpdate")) { %>
    <%= Html.AntiForgeryToken() %>
    <!-- rest of form goes here -->
<% } %>

I oczywiście potrzebny jest odpowiedni atrybut w metodzie kontrolera:

[ValidateAntiForgeryToken]
public ViewResult SubmitUpdate()
{
    // ... etc
}

To naprawdę nie jest takie trudne do modernizacji aplikacji w ten sposób, chyba że jest niezwykle duża. Ostatnia aplikacja, którą napisałem w MVC, zajęłaby mi prawdopodobnie kilka godzin na modernizację.

 0
Author: Robert Harvey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-01 15:58:31