web-dev-qa-db-fra.com

Rails 4 ignorer protect_from_forgery pour les actions d'API

J'ai implémenté une application Rails 4 avec une API. Je veux pouvoir appeler l'API à partir des téléphones mobiles et de la webapp elle-même. Je suis tombé sur cette note = pendant la recherche protect_from_forgery:

Il est important de se rappeler que les requêtes XML ou JSON sont également affectées et si vous créez une API, vous aurez besoin de quelque chose comme:

class ApplicationController < ActionController::Base
  protect_from_forgery
  skip_before_action :verify_authenticity_token, if: :json_request?

  protected

  def json_request?
    request.format.json?
  end
end

J'envisageais de faire cela, mais j'ai quelques réserves/questions:

  1. Cette solution semble laisser le trou CSRF ouvert car maintenant un attaquant pourrait créer un lien avec un onclick javascript qui publie du JSON?
  2. La vérification d'un jeton d'API serait-elle un substitut raisonnable? c'est-à-dire, si au lieu de sauter le contrôle d'authenticité, lui permettant d'échouer le contrôle et de récupérer dans handle_unverified_request si le jeton api est présent et correct pour l'utilisateur actuel?
  3. Ou peut-être que je devrais simplement faire la webapp et les appareils mobiles envoyer le jeton CSRF dans les en-têtes HTTP ? Est-ce sûr? Comment le téléphone mobile pourrait-il même obtenir le jeton CSRF, étant donné qu'il ne rend pas les formulaires HTML pour commencer?

Modifier pour clarification:

Je suis plus préoccupé par le fait que l'utilisateur de l'application Web clique sur un lien CSRF spécialement conçu. Les utilisateurs mobiles sont authentifiés, autorisés et disposent d'une clé API, donc je ne suis pas concerné par eux. Mais en activant la protection CSRF pour les utilisateurs d'applications Web, les utilisateurs mobiles ne peuvent pas utiliser l'API protégée. Je veux connaître la bonne stratégie pour gérer cela, et je ne pense pas que la documentation Rails donne la bonne réponse.

32
user44484

Un attaquant pourrait CURL sur vos contrôleurs tout ce qu'ils veulent, mais si votre API nécessite une authentification, ils n'iront nulle part.

Faire en sorte que les consommateurs d'API envoient un CSRF n'est pas vraiment ce que fait CSRF. Pour ce faire, vous devez implémenter un type de mécanisme de frappe dans lequel votre client atteint d'abord un point de terminaison d'autorisation pour obtenir le code (aka CSRF), puis le soumettre dans le POST. cela craint pour les clients mobiles car il utilise leur bande passante, leur puissance et est lent.

Et de toute façon, est-ce réellement de la contrefaçon (c'est-à-dire le F dans CSRF) si c'est un client autorisé qui frappe votre contrôleur après tout?

9
Oren Mazor

L'envoi du jeton CSRF dans un en-tête HTTP est en effet une approche courante. Il garantit que le client a en quelque sorte obtenu un jeton valide. Par exemple, un lien CSRF spécialement conçu sera envoyé avec des cookies d'informations d'identification mais l'en-tête n'inclura pas le jeton CSRF. Votre propre javascript sur le client aura accès aux cookies de domaine et pourra copier le jeton d'un cookie vers l'en-tête sur toutes les demandes XHR.

AngularJS suit cette approche, comme expliqué ici .

Quant à vos deux premières questions:

  1. Cette solution semble laisser le trou CSRF ouvert ...

En effet, c'est pourquoi vous ne devez pas désactiver le jeton CSRF également dans votre API.

  1. La vérification d'un jeton d'API serait-elle un substitut raisonnable? ...

Probablement pas. Tenez compte des éléments suivants (de OWASP ):

Les jetons CSRF dans les demandes GET sont potentiellement divulgués à plusieurs emplacements: historique du navigateur, fichiers journaux HTTP, appliances réseau qui mettent un point d'honneur à consigner la première ligne d'une demande HTTP et en-têtes de référent si le site protégé est lié à un site externe.

Recommandation générale : N'essayez pas d'inventer la roue. OWASP a une page appelée REST Security Cheat Sheet ainsi que celle à laquelle j'ai lié auparavant. Vous pouvez suivre l'approche Angular (copier le jeton d'un cookie vers un en-tête sur chaque demande XHR) et pour les formulaires non ajax réguliers, assurez-vous d'utiliser uniquement POST et un champ caché comme cela se fait normalement dans la protection CSRF des formulaires de serveur statiques.

6
sinelaw