Comment les cookies HttpOnly fonctionnent-ils avec les requêtes AJAX?

195

JavaScript doit avoir accès aux cookies si AJAX est utilisé sur un site avec des restrictions d'accès basées sur les cookies. Les cookies HttpOnly fonctionneront-ils sur un site AJAX?

Modifier: Microsoft a créé un moyen de prévenir les attaques XSS en interdisant l'accès JavaScript aux cookies si HttpOnly est spécifié. FireFox l'a ensuite adopté. Ma question est donc la suivante: si vous utilisez AJAX sur un site, comme StackOverflow, les cookies Http-Only sont-ils une option?

Edit 2: Question 2. Si le but de HttpOnly est d'empêcher l'accès JavaScript aux cookies et que vous pouvez toujours récupérer les cookies via JavaScript via l'objet XmlHttpRequest, quel est l'intérêt de HttpOnly ?

Edit 3: Voici une citation de Wikipedia:

Lorsque le navigateur reçoit un tel cookie, il est censé l'utiliser comme d'habitude dans les échanges HTTP suivants, mais pas pour le rendre visible aux scripts côté client. [32] Le HttpOnlydrapeau ne fait partie d'aucune norme et n'est pas implémenté dans tous les navigateurs. Notez qu'il n'y a actuellement aucune prévention de lecture ou d'écriture du cookie de session via une requête XMLHTTPRequest. [33].

Je comprends que cela document.cookieest bloqué lorsque vous utilisez HttpOnly. Mais il semble que vous puissiez toujours lire les valeurs des cookies dans l'objet XMLHttpRequest, permettant XSS. Comment HttpOnly vous rend-il plus sûr que? En rendant les cookies essentiellement en lecture seule?

Dans votre exemple, je ne peux pas écrire sur votre document.cookie, mais je peux toujours voler votre cookie et le publier sur mon domaine à l'aide de l'objet XMLHttpRequest.

<script type="text/javascript">
    var req = null;
    try { req = new XMLHttpRequest(); } catch(e) {}
    if (!req) try { req = new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) {}
    if (!req) try { req = new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) {}
    req.open('GET', 'http://stackoverflow.com/', false);
    req.send(null);
    alert(req.getAllResponseHeaders());
</script>

Edit 4: Désolé, je voulais dire que vous pouviez envoyer XMLHttpRequest au domaine StackOverflow, puis enregistrer le résultat de getAllResponseHeaders () dans une chaîne, regexer le cookie, puis le publier dans un domaine externe. Il semble que Wikipedia et ha.ckers soient d'accord avec moi sur celui-ci, mais j'aimerais être rééduqué ...

Édition finale: Ahh, apparemment les deux sites ont tort, c'est en fait un bug dans FireFox . IE6 et 7 sont en fait les seuls navigateurs qui prennent actuellement pleinement en charge HttpOnly.

Pour répéter tout ce que j'ai appris:

  • HttpOnly restreint tout accès à document.cookie dans IE7 et FireFox (pas sûr des autres navigateurs)
  • HttpOnly supprime les informations de cookie des en-têtes de réponse dans XMLHttpObject.getAllResponseHeaders () dans IE7.
  • XMLHttpObjects ne peut être soumis qu'au domaine d'où ils proviennent, il n'y a donc pas de publication inter-domaines des cookies.

modifier: Ces informations ne sont probablement plus à jour.

Shawn
la source
J'ai jeté votre exemple dans un script greasemonkey et il semble que FF n'affiche plus les cookies. Excellente recherche et exemple.
Peut-être qu'avec la même politique d'origine, vous ne pouvez pas faire de requête http à un domaine qui n'est pas le même que le script s'exécute; Cependant, je pense que vous pouvez facilement transmettre les cookies en redirigeant l'utilisateur vers une page en utilisant window.location et en transmettant toutes les informations via les paramètres de la chaîne de requête.
Luca Marzi
@LucaMarzi " vous ne pouvez pas faire de requête http à un domaine différent de celui dans lequel le script s'exécute " Êtes-vous en train de dire qu'un site X ne peut pas inclure une image de l'hôte Y? (une fonctionnalité prise en charge par tous les navigateurs depuis Mosaic?)
curiousguy

Réponses:

64

Oui, les cookies HTTP uniquement conviendraient à cette fonctionnalité. Ils seront toujours fournis avec la demande de XmlHttpRequest au serveur.

Dans le cas de Stack Overflow, les cookies sont automatiquement fournis dans le cadre de la demande XmlHttpRequest. Je ne connais pas les détails d'implémentation du fournisseur d'authentification Stack Overflow, mais ces données de cookies sont probablement utilisées automatiquement pour vérifier votre identité à un niveau inférieur à la méthode du contrôleur "vote".

Plus généralement, les cookies ne sont pas requis pour AJAX. La prise en charge de XmlHttpRequest (ou même la transmission à distance iframe sur les anciens navigateurs) est tout ce qui est techniquement requis.

Cependant, si vous souhaitez assurer la sécurité des fonctionnalités activées par AJAX, les mêmes règles s'appliquent que pour les sites traditionnels. Vous avez besoin d'une méthode pour identifier l'utilisateur derrière chaque demande, et les cookies sont presque toujours le moyen d'y parvenir.

Dans votre exemple, je ne peux pas écrire dans votre document.cookie, mais je peux toujours voler votre cookie et le publier sur mon domaine à l'aide de l'objet XMLHttpRequest.

XmlHttpRequest ne fera pas de demandes inter-domaines (pour exactement le genre de raisons que vous abordez).

Vous pouvez normalement injecter un script pour envoyer le cookie à votre domaine en utilisant iframe remoting ou JSONP, mais HTTP-Only protège à nouveau le cookie car il est inaccessible.

À moins que vous n'ayez compromis StackOverflow.com côté serveur, vous ne pourrez pas voler mon cookie.

Edit 2: Question 2. Si le but de Http-Only est d'empêcher l'accès JavaScript aux cookies et que vous pouvez toujours récupérer les cookies via JavaScript via l'objet XmlHttpRequest, quel est l'intérêt de Http-Only?

Considérez ce scénario:

  • Je trouve un moyen d'injecter du code JavaScript dans la page.
  • Jeff charge la page et mon JavaScript malveillant modifie son cookie pour qu'il corresponde au mien.
  • Jeff soumet une excellente réponse à votre question.
  • Parce qu'il le soumet avec mes données de cookie au lieu des siennes, la réponse deviendra la mienne.
  • Vous votez "ma" réponse stellaire.
  • Mon vrai compte a raison.

Avec les cookies HTTP uniquement, la deuxième étape serait impossible, battant ainsi ma tentative XSS.

Edit 4: Désolé, je voulais dire que vous pouviez envoyer XMLHttpRequest au domaine StackOverflow, puis enregistrer le résultat de getAllResponseHeaders () dans une chaîne, regexer le cookie, puis le publier dans un domaine externe. Il semble que Wikipedia et ha.ckers soient d'accord avec moi sur celui-ci, mais j'aimerais être rééduqué ...

C'est correct. Vous pouvez toujours détourner la session de cette façon. Cependant, cela réduit considérablement le troupeau de personnes qui peuvent exécuter avec succès ce hack XSS contre vous.

Cependant, si vous allez revenir à mon exemple de scénario, vous pouvez voir où HTTP seule ne réussi à réduire les attaques XSS qui reposent sur la modification des cookies du client (pas rare).

Cela se résume au fait que a) aucune amélioration unique ne résoudra toutes les vulnérabilités et b) aucun système ne sera jamais complètement sécurisé. HTTP uniquement est un outil utile pour étayer contre XSS.

De même, même si la restriction interdomaine sur XmlHttpRequest ne réussit pas à 100% à empêcher tous les exploits XSS, vous ne rêveriez toujours pas de supprimer la restriction.

Dave Ward
la source
De nombreux frameworks mettent des csrf jetons dans les cookies . Je suppose que l'appel AJAX qui a besoin d'une csrfvérification ne fonctionnera que si vous placez le jeton csrf dans un élément HTML caché pour que le JS le récupère.
utilisateur
4

Pas nécessairement, cela dépend de ce que vous voulez faire. Pourriez-vous développer un peu? AJAX n'a ​​pas besoin d'accéder aux cookies pour fonctionner, il peut faire lui-même des demandes pour extraire des informations, la demande de page que l'appel AJAX fait pourrait accéder aux données des cookies et les renvoyer au script appelant sans que Javascript doive accéder directement à la biscuits

Glenn Slaven
la source
4

Oui, ils sont une option viable pour un site basé sur Ajax. Les cookies d'authentification ne sont pas destinés à être manipulés par des scripts, mais sont simplement inclus par le navigateur sur toutes les requêtes HTTP adressées au serveur.

Les scripts n'ont pas à se soucier de ce que dit le cookie de session - tant que vous êtes authentifié, toutes les demandes adressées au serveur par un utilisateur ou le script incluront les cookies appropriés. Le fait que les scripts ne puissent pas eux-mêmes connaître le contenu des cookies n'a pas d'importance.

Pour tout cookie utilisé à des fins autres que l'authentification, ceux-ci peuvent être définis sans l'indicateur HTTP uniquement, si vous souhaitez que le script puisse les modifier ou les lire. Vous pouvez choisir quels cookies doivent être HTTP uniquement, donc par exemple tout ce qui n'est pas sensible comme les préférences de l'interface utilisateur (ordre de tri, réduire le volet de gauche ou non) peut être partagé dans les cookies avec les scripts.

J'aime vraiment les cookies HTTP uniquement - c'est l'une de ces extensions de navigateur propriétaires qui était vraiment une bonne idée.

thomasrutter
la source
3

Il y a un peu plus à cela.

Ajax ne nécessite pas strictement de cookies, mais ils peuvent être utiles comme l'ont mentionné d'autres affiches. Marquer un cookie HTTP Uniquement pour le cacher des scripts ne fonctionne que partiellement, car tous les navigateurs ne le prennent pas en charge, mais aussi parce qu'il existe des solutions de contournement courantes.

Il est étrange que les en-têtes XMLHTTPresponse donnent le cookie, techniquement le serveur n'a pas à retourner le cookie avec la réponse. Une fois qu'il est défini sur le client, il reste défini jusqu'à son expiration. Bien qu'il existe des schémas dans lesquels le cookie est modifié à chaque demande pour empêcher la réutilisation. Ainsi, vous pourrez peut-être éviter cette solution de contournement en modifiant le serveur pour ne pas fournir le cookie sur les réponses XMLHTTP.

En général cependant, je pense que HTTPOnly devrait être utilisé avec une certaine prudence. Il existe des attaques de script intersite où un attaquant fait en sorte qu'un utilisateur soumette une demande de type ajax provenant d'un autre site, en utilisant de simples formulaires de publication, sans utiliser XMLHTTP, et le cookie encore actif de votre navigateur authentifierait la demande.

Si vous voulez être sûr qu'une demande AJAX est authentifiée, la demande elle-même ET les en-têtes HTTP doivent contenir le cookie. Par exemple grâce à l'utilisation de scripts ou d'entrées cachées uniques. HTTP n'entraverait que cela.

Habituellement, la raison intéressante de vouloir HTTPOnly est d'empêcher le contenu tiers inclus sur votre page Web de voler des cookies. Mais il existe de nombreuses raisons intéressantes d'être très prudent quant à l'inclusion de contenu tiers et de le filtrer de manière agressive.

davenpcj
la source
1

Les cookies sont automatiquement gérés par le navigateur lorsque vous effectuez un appel AJAX, il n'y a donc pas besoin que votre Javascript s'emballe avec les cookies.

pkchukiss
la source
1

Par conséquent, je suppose que JavaScript doit avoir accès à vos cookies.

Toutes les requêtes HTTP de votre navigateur transmettent vos informations de cookie pour le site en question. JavaScript peut à la fois définir et lire des cookies. Les cookies ne sont pas par définition requis pour les applications Ajax, mais ils sont requis pour la plupart des applications Web pour maintenir l'état de l'utilisateur.

La réponse formelle à votre question telle que formulée - "JavaScript a-t-il besoin d'accéder aux cookies si AJAX est utilisé?" - est donc "non". Pensez aux champs de recherche améliorés qui utilisent des requêtes Ajax pour fournir des options de suggestion automatique, par exemple. Dans ce cas, il n'est pas nécessaire de disposer d'informations sur les cookies.

Polsonby
la source
XmlHttpRequest a besoin de cookies. La recherche avancée que vous mentionnez peut se trouver derrière une page de connexion. Mais si Javascript doit ou non être en mesure d'exposer la valeur du cookie à la machine virtuelle est une question différente.
M. Shiny et New 安 宇
1

À titre de clarification - du point de vue du serveur, la page qui est demandée par une demande AJAX n'est essentiellement pas différente d'une demande HTTP standard get effectuée par l'utilisateur en cliquant sur un lien. Toutes les propriétés normales des requêtes: user-agent, ip, session, cookies, etc. sont transmises au serveur.

Glenn Slaven
la source
La "session" n'est pas un concept HTTP. C'est un concept de haut niveau construit au-dessus des concepts HTTP par un framework.
curiousguy
0

Non, la page demandée par l'appel AJAX a également accès aux cookies et c'est ce qui vérifie si vous êtes connecté.

Vous pouvez faire une autre authentification avec le Javascript, mais je n'y ferais pas confiance, je préfère toujours mettre toute sorte de vérification d'authentification dans le back-end.

Glenn Slaven
la source
0

Oui, les cookies sont très utiles pour Ajax.

Placer l'authentification dans l'URL de demande est une mauvaise pratique. La semaine dernière, il y a eu un article sur l'obtention des jetons d'authentification dans les URL du cache Google.

Non, il n'y a aucun moyen d'empêcher les attaques. Les navigateurs plus anciens permettent toujours un accès trivial aux cookies via javascript. Vous pouvez contourner uniquement http, etc. Tout ce que vous proposez peut être contourné avec suffisamment d'effort. L'astuce consiste à faire trop d'efforts pour en valoir la peine.

Si vous souhaitez rendre votre site plus sûr (il n'y a pas de sécurité parfaite), vous pouvez utiliser un cookie d'authentification qui expire. Ensuite, si le cookie est volé, l'attaquant doit l'utiliser avant son expiration. S'ils ne le font pas, vous avez une bonne indication qu'il y a une activité suspecte sur ce compte. Plus la fenêtre de temps est courte, mieux c'est pour la sécurité, mais plus elle met de charge sur votre serveur pour générer et maintenir des clés.

Geai
la source