http://tools.ietf.org/html/draft-ietf-oauth-v2-30#section-10.12 dit:
Le client DOIT implémenter la protection CSRF [...] généralement réalisée en exigeant que toute demande envoyée au point de terminaison URI de redirection inclue une valeur qui lie la demande à l'état authentifié de l'agent utilisateur (par exemple un hachage du cookie de session [...] ]
Cela ne dit pas grand chose sur la mise en œuvre, cependant. Cela ne fait que mettre en lumière le fonctionnement du CSRF:
Une attaque CSRF contre l'URI de redirection du client permet à un attaquant d'injecter son propre code d'autorisation ou jeton d'accès, ce qui peut amener le client à utiliser un jeton d'accès associé aux ressources protégées de l'attaquant plutôt que celui de la victime (par exemple, enregistrer les informations de compte bancaire de la victime dans une ressource protégée contrôlée par l'attaquant)
Mais l'utilisation du mot "plutôt" rend plutôt la déclaration sans valeur.
Je réfléchis à l'implémentation de "l'état" dans GAE (en utilisant Webapp2). Il serait plus simple de commencer à savoir comment un pirate pourrait utiliser un CSRF contre OAuth2. Je n'ai trouvé qu'un seul bon article à ce sujet: "Cross Site Request Forgery and OAuth2" .
Malheureusement, bien que ce billet de blog soit bien écrit, il n'y a pas beaucoup d'informations à part expliquer OAuth2. Les exemples ne fonctionnent pas et je ne connais pas Spring. Pourtant, j'ai trouvé une recommandation intéressante: le serveur se connectant à un fournisseur OAuth2 devrait stocker "state" comme une clé de session aléatoire (par exemple "this_is_the_random_state": "this_doesn't_matter") , et non une valeur sous une clé statique (par exemple "état": "random_state_string").
Ma question est, quelle est la mise en œuvre sensée de l '"état"?
Je vais simplifier ce problème. Cross-Site Request Forgery et Clikjacking les attaques sont utiles car elles peuvent forcer le navigateur d'une victime à effectuer des actions contre sa volonté.
La mention de 10.12. Cross-Site Request Forgery
et 10.13. Clickjacking
dans le OAuth v2 RFC ont fondamentalement la même préoccupation. Si un attaquant peut forcer le navigateur d'une victime à s'authentifier, il s'agit d'une étape utile pour forcer le navigateur de la victime à effectuer d'autres actions.
in a clickjacking attack, an attacker registers a legitimate client
and then constructs a malicious site in which it loads the
authorization server's authorization endpoint web page in a
transparent iframe overlaid on top of a set of dummy buttons, which
are carefully constructed to be placed directly under important
buttons on the authorization page. When an end-user clicks a
misleading visible button, the end-user is actually clicking an
invisible button on the authorization page (such as an "Authorize"
button). This allows an attacker to trick a resource owner into
granting its client access without their knowledge.
Source: 10.13. Détournement de clics
Par exemple, Stack Overflow utilise OAuth et est vulnérable à cette attaque. Si vous visitez StackOverflow et que vous êtes actuellement connecté à votre fournisseur OAuth, vous serez automatiquement connecté à StackOverflow. Par conséquent, un attaquant pourrait automatiquement connecter une victime en chargeant Stack Oveflow dans un iframe. Si Stack Overflow avait également une vulnérabilité CSRF ( et il l'a eu! ), alors un attaquant pourrait authentifier automatiquement le navigateur d'une victime et effectuer une attaque CSRF (Session Riding), Clickjacking ou XSS contre stackoverflow.com dans une attaque en chaîne .
Voyons comment cette attaque fonctionne.
Je visite certains site Web du client et entame le processus d'autorisation de ce client pour accéder à certains fournisseur de services en utilisant OAuth
Le client demande au fournisseur de services l'autorisation de demander l'accès en mon nom, ce qui lui est accordé
Je suis redirigé vers le site Web du fournisseur de services, où j'entrerais normalement mon nom d'utilisateur/mot de passe afin d'autoriser l'accès
Au lieu de cela, je piège/empêche cette demande et enregistre son URL
Je vous demande en quelque sorte de visiter cette URL à la place. Si vous êtes connecté au fournisseur de services avec votre propre compte, alors vos informations d'identification seront utilisées pour émettre un code d'autorisation
Le code d'autorisation est échangé contre un jeton d'accès
Maintenant mon compte sur le client est autorisé à accéder à votre compte sur le fournisseur de services
Alors, comment pouvons-nous empêcher cela en utilisant le paramètre state
?
Le client doit créer une valeur qui est en quelque sorte basée sur le compte de l'utilisateur d'origine (un hachage de la clé de session de l'utilisateur, par exemple). Peu importe ce que c'est tant qu'il est unique et généré en utilisant des informations privées sur l'utilisateur d'origine.
Cette valeur est transmise au fournisseur de services dans la redirection de l'étape trois ci-dessus
Maintenant, je vous invite à visiter l'URL que j'ai enregistrée (étape cinq ci-dessus)
Le code d'autorisation est émis et renvoyé au client dans votre session avec le paramètre state
Le client génère une valeur state
basée sur vos informations de session et la compare à la valeur state
qui a été renvoyée de la demande d'autorisation au prestataire de services. Cette valeur ne correspond pas au paramètre state
de la demande, car cette valeur state
a été générée en fonction de ma session informations, il est donc rejeté.
Le fait est que l'attaquant ne devrait pas être en mesure de générer une valeur d'état spécifique à un utilisateur donné. Cela devrait être impossible à deviner.
Je ne pense pas que cela compte (si je vous comprends bien)
Je ne sais pas ce que ça veut dire.
Oui, l'état doit avoir une expiration. Cela ne doit pas nécessairement être lié à la session, mais cela pourrait l'être.
Tiré de L'importance du paramètre d'état dans OAuth2 :
C'est là que l'objet "état" dans OAuth 2 entre en jeu. En soumettant toujours un état non devinable lors du POSTage au point de terminaison d'autorisation, l'application cliente peut être certaine que le code d'accès obtenu du serveur d'autorisation sont en réponse à des demandes faites par lui plutôt qu'à une autre application cliente.
Exemple:
https://example.com/as/authorization?client_id=client1&response_type=code&scope=openid &state=7tvPJiv8StrAqo9IQE9xsJaDso4
Pour que le paramètre d'état soit utile pour empêcher des attaques CSRF comme celle-ci, toutes les demandes adressées au serveur OAuth doivent inclure un paramètre d'état que le client peut utiliser pour s'authentifier. Lors de l'envoi d'un paramètre d'état, la spécification OAuth stipule que le serveur d’autorisations doit le renvoyer textuellement au client. Cela se fera en le plaquant sur l’URL de rappel du client. Le client doit recevoir cet état et être programmé pour accepte uniquement les redirections avec un état vérifiable. S'il s'agit d'un dictionnaire conservé en mémoire ou si une valeur recalculable appartient au programmeur client.
Pour décider comment implémenter cela, une suggestion est d'utiliser une clé privée avec quelques variables facilement vérifiables, par exemple, l'ID client et un cookie de session, pour calculer une valeur hachée. Cela se traduira par une valeur d'octet qui sera difficile à deviner sans la clé privée. Après avoir calculé un tel HMAC, codez en base 64 et transmettez-le au serveur OAuth comme paramètre d'état. Une autre suggestion est de hacher la date et l'heure actuelles. Cela nécessite que votre application économise le temps de transmission afin de le vérifier ou pour permettre une période mobile de validité (par exemple, en utilisant TOTP).
Le sien est un simple Python qui utilise la deuxième suggestion en utilisant datetime:
def generate_state_parameter(client_id, private_key):
date = datetime.datetime.today()
raw_state = str(date) + client_id
hashed = hmac.new(private_key, raw_state, sha1) state = base64.b64encode(hashed.digest())
return (state, date)