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:
onclick
javascript qui publie du JSON?handle_unverified_request
si le jeton api est présent et correct pour l'utilisateur actuel?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.
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?
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:
- 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.
- 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.