web-dev-qa-db-fra.com

Erreur XSRF lorsque le lien est ouvert via une balise <a> avec l'attribut cible défini sur "_blank"

J'ai rencontré un bogue particulier que je n'ai jamais rencontré auparavant. Je peux fournir tous les détails nécessaires, mais je vais essayer d'être aussi générique que possible.

Nous avons un portail intranet qui relie d'autres applications dans différents domaines. Chaque lien de la page de portail ouvre l'application correspondante dans un nouvel onglet via un target = "_ blank" dans sa balise. Une de ces applications externes est MS Exchange via Outlook Web App (OWA). L'URL de cette application est https: // exchange. company.com OWA contient en son sein un lien qui charge un iframe avec un contenu provenant de https://exchange.company.com/ecp .

Voici le bogue: si un utilisateur clique sur le lien OWA sur la page de portail, ouvrant ainsi un nouvel onglet, les contenus iframe ne parviennent pas à être insérés. Ceci est un extrait du message d'erreur que l'utilisateur reçoit:

Informations techniques: Uncaught SecurityError: Blocage d'un cadre avec l'origine " https://exchange.company.com " pour accéder à un cadre d'origine croisée.

Ce comportement est évident dans les dernières versions de Chrome et de Firefox, mais n'est pas présent dans les dernières versions d'Internet Explorer.

Ce qui est étrange, c’est que l’iframe se charge correctement à 100% si l’utilisateur saisit manuellement l’URL dans son navigateur OR si target = "_ blank" est supprimé de la balise.

Pour tester, j'ai essayé de créer une page intermédiaire contenant uniquement un lien vers un nouvel onglet vers https: // exchange. entreprise. com, puis changer le lien du portail pour qu'il pointe vers cette page - le même bogue.

Je pense que cette faille de sécurité a été corrigée par Chrome/FF et que le navigateur fonctionne en fait comme prévu - mais la clé de cette logique est "alors pourquoi fonctionne-t-il sans erreur lorsque l'utilisateur saisit manuellement dans l'URL ou atteint l'URL via une balise w/o target = "_ blank"? L'iframe est sur le même domaine que le serveur d'origine (https : // exchange. company. com) donc, autant que je sache, cela ne devrait pas entraîner d'erreur XSRF.

Je suis un gars de LAMP/Drupal et je me suis laissé entraîner à ce sujet parce que cela est apparu dans notre système de vente de billets en tant que problème avec notre page de portail. J'ai demandé son avis à notre administrateur Exchange et lui aussi est désemparé. Je prévois de faire appel au consultant MS avec lequel l'équipe des systèmes avait l'habitude d'installer Exchange au téléphone, mais je me demandais si quelqu'un ici pourrait avoir une idée de ce qui pourrait causer cela. Quelles données sont conservées (ou non maintenues) par le navigateur lors de l’utilisation d’un lien avec target = "_ blank" qui n’est pas maintenu (ou maintenu) lors de l’ouverture de ce lien dans le même onglet? Tout conseil est grandement appréciée. Je suis perdu sur celui-ci pour le moment.

Merci d'avoir lu.

EDIT: Vous vous demandez peut-être pourquoi nous devons ouvrir Exchange dans une nouvelle fenêtre. Disons simplement que c'est une exigence absolue. Nous utilisons un service d'authentification unique qui demande à l'utilisateur de fermer complètement la post-déconnexion de son navigateur. Nous avons donc une convention pour que tous les liens de portail s'ouvrent dans un nouvel onglet afin que la page de portail d'origine reste ouverte, rappelant à l'utilisateur qu'ils sont toujours connectés. Étant donné que nous avons de nombreux postes de travail à utilisation partagée, si nous autorisons Exchange à s'ouvrir dans le même onglet et si un utilisateur le ferme, ils risquent de ne pas se rendre compte qu'ils sont toujours connectés au portail, ce qui peut entraîner le piratage de leur session par un autre utilisateur. En laissant la fenêtre du portail d'origine ouverte à tout moment, il est au moins rappelé à l'utilisateur que sa session est toujours active lorsqu'il ferme les onglets à la fin du temps imparti.

Cela dit, si quelqu'un connaît un autre moyen d'ouvrir une URL dans un nouvel onglet qui n'utilise pas target = "_ blank" (ainsi, ce qui est causé par le target = "_ blank" provoquant le bogue), cela suffirait. réparer aussi (bien que j'aimerais bien aller à la cause fondamentale).

4
Tim

Lors de mes tests, Firefox 41 et Chrome 45 ​​sont concernés. IE 11 et Safari 8 ne le sont pas. Je n'ai pas testé d'autres versions de ces navigateurs.

Apparemment, lorsqu'une page en ouvre une autre dans une nouvelle fenêtre/un nouvel onglet, ils ont une capacité limitée d'interaction les uns avec les autres; dans la fenêtre enfant, il s'agit de l'objet JavaScript window.opener. [Voir " reverse tabnapping ".] Quoi qu'il en soit, Firefox et Chrome semblent se croiser avec "l'origine" de cette nouvelle fenêtre, ce qui pose problème lorsque, par exemple. OWA essaie de s'ouvrir et d'interagir avec son iframe sur différentes pages Options. Le problème n’est pas spécifique à target="_blank", cependant: Vous pouvez également appliquer un nouvel onglet/fenêtre en spécifiant une cible nommée non existante, par exemple. target="newExchangeWindow", mais cela entraîne toujours le même comportement que celui observé avec target="_blank".

Il est intéressant de noter que ce comportement persistera apparemment sur de nombreuses pages intermédiaires: je peux cliquer sur un lien qui ouvre un nouvel onglet, naviguer sur plusieurs sites différents, puis sur notre OWA, et le problème persiste - il ne s'agit pas simplement d'un problème. avec des liens qui ouvrent OWA dans un nouvel onglet! Il ne peut pas non plus être résolu en tapant directement l'URL - l'onglet reste "cassé" apparemment pendant toute la durée de son existence.

J'ai réussi à trouver plusieurs façons de résoudre ce problème:

Option 0:
Supprimez le target="_blank" de vos liens.
Évidemment, l’inconvénient est que cela ne résout pas votre exigence (ni la mienne), mais au moins vos utilisateurs peuvent définir leurs signatures et autres!

Option 1:
Ajouter rel="noreferrer" à vos liens:
<a href="https://exchange.company.com" target="_blank" rel="noreferrer">OWA</a>
Cela fonctionne dans les versions actuelles de Firefox et de Chrome; J'ai vu des suggestions selon lesquelles cela ne fonctionnerait pas dans Safari, bien que lors de mes tests, le problème original n'existe pas dans Safari. Néanmoins, cela peut indiquer que cela pourrait ne pas être fiable.

Option 2:
Écrasez l’objet window.opener sur une page intermédiaire, par exemple:

<html>
  <head><title>Clobbering window.opener...</title></head>
  <body onload="window.opener=null;window.location='https://exchange.company.com/'">
  </body>
</html>

Soyons clairs: cette page intermédiaire correspond à ce que vous ouvririez avec votre lien target="_blank": son travail consiste ensuite à encombrer l’objet window.opener avant de diriger l’utilisateur vers OWA. Vous voudrez peut-être ajouter une balise meta-refresh et/ou un lien dans le corps au cas où vous auriez un utilisateur qui a du JavaScript désactivé (mais là encore, ils ne pourront pas utiliser très bien OWA de toute façon ...).

Option 3:
Frimez l’objet window.opener en injectant du code directement dans OWA.

Ce n'est pas la chose la plus facile à faire pour injecter du code dans OWA; dans mon cas, comme notre OWA est derrière un équilibreur de charge Big-Ip, j'ai écrit une iRule qui remplace la balise </head> par <script type="text/javascript">window.opener = null;</script></head>. Je ne fais cela que sur la page /ecp/ elle-même, car c'est là que réside le problème, même si on peut le faire sur la page /owa/ puisqu'il s'agit de la "page de destination" pour tous ceux qui arrivent dans l'application. Faites juste attention à ne pas le faire globalement: il y a plusieurs fichiers .js qui incluent également cette chaîne, et faites-moi confiance quand je dis que Bad Things® se produira si votre remplaçant fonctionne dans ceux-là!


Dans mes tests, encore une fois, Firefox et Chrome ont ce problème, mais pas Safari et IE. (Je n'ai pas testé Opera car nous n'avons aucun utilisateur qui l'utilise.) Dans ces deux navigateurs, toutes/toutes ces options sont efficaces pour remédier au problème. Vous pouvez même utiliser n'importe quelle combinaison des deux: L'attribut rel peut bien sûr aller sur n'importe quel/tous vos liens, et il n'y a aucun mal à casser l'objet window.opener s'il n'existe pas ou n'a pas déjà été clobber.

4
Kromey