Accès sécurisé au contenu DOM depuis le chrome

Introduction

Les applications et les extensions scriptant des interfaces DOM sur du contenu non fiable (une page Web) doivent être prudentes et s'assurer que les informations utilisées proviennent bien de l'API DOM et non de propriétés JavaScript ou de fonctions getter et setter (accesseur/mutateur) redéfinies par une page malveillante. Firefox 1.0.3 et Mozilla 1.7.7 rendent la tâche plus difficile aux pages Web essayant de tromper les applications XUL en s'assurant que lorsque du JavaScript chrome accède à une propriété ou méthode DOM sur un objet, il obtiendra bien la propriété ou méthode DOM plutôt que la redéfinition faite par la page Web. Firefox 1.5 propose une solution plus générale qui est activée par défaut ; les extensions doivent explicitement le demander pour pouvoir effectuer des accès DOM non sûrs.

Il n'y a que deux manières « correctes » pour le code chrome d'accéder au DOM du contenu : l'accès direct et l'utilisation explicite de XPCNativeWrapper. En particulier, l'astuce __proto__ couramment utilisée n'est sûre dans aucune version (voir « Exemples à ne PAS suivre » ci-dessous).

La table suivante rassemble les propriétés de sécurité des deux méthodes « correctes » :

Accès direct XPCNativeWrapper explicite
Firefox 1.0.2 et antérieur non sécurisé sécurisé
Firefox 1.0.3 et postérieur (1.0.x) sécurisé lorsqu'il est certain que la propriété existe sécurisé
Firefox 1.5 sécurisé avec xpcnativewrappers=yes (qui est le réglage par défaut) sécurisé

Accès direct

Les scripts conçus pour s'exécuter uniquement dans Firefox 1.0.3 et les versions 1.0.x plus récentes ou qui utilisent xpcnativewrappers=yes dans Firefox 1.5 ou plus récent peuvent simplement appeler :

return contentWindow.document.title == contentWindow.getSelection();

L'accès direct est sécurisé dans Firefox 1.0.3 (et les versions 1.0.x suivantes) dans la mesure où l'objet a la garantie de bénéficier de la propriété ou de la méthode accédée par sa déclaration IDL. Par exemple, foo.nodeType est sûr si vous avez l'assurance que foo est de type Node, et foo.getSelection() est sûr si foo ne peut être qu'un objet window. Il peut être complexe d'y arriver -- par exemple, nsIDOMNSHTMLDocument a une méthode open(), mais nsIDOMXULDocument n'en a pas, par conséquent utiliser document.open() n'est PAS sûr dans Firefox 1.0.3, étant donné que document peut être un document XUL. Dans de tels cas, vous pouvez utiliser l'opérateur instanceof pour déterminer si vous avez un objet implémentant une interface IDL donnée (nsIDOMNSHTMLDocument dans ce cas précis).

Dans Firefox 1.5, l'accès direct est toujours sûr, sauf si votre extension utilise le paramètre xpcnativewrappers=no dans son fichier manifest. Si ce paramètre n'est pas défini, l'utilisation de XPCNativeWrapper est implicite.

Utilisation explicite de XPCNativeWrapper

var winWrapper = new XPCNativeWrapper(contentWindow,
                                      'document', 'getSelection()');
var docWrapper = new XPCNativeWrapper(winWrapper.document, 'title');
return docWrapper.title == winWrapper.getSelection();

Notez que cet exemple utilise deux wrappers pour obtenir window.document.title, un wrapper pour obtenir la propriété document de l'objet window, et un wrapper pour obtenir la propriété title du document.

L'utilisation de XPCNativeWrapper est sûre dans toutes les versions de Firefox, mais rend le code plus difficile à lire et vous devez faire attention à envelopper tous les objets DOM.

Pour plus d'informations sur cette syntaxe, consultez l'entrée sur XPCNativeWrapper de la MozillaZine KnowledgeBase.

À propos de XPCNativeWrapper

XPCNativeWrapper est une manière d'envelopper un objet de manière à ce que son accès par du code privilégié soit sûr.

Il y a deux façons d'utiliser XPCNativeWrapper. L'ancienne est de l'appeler explicitement. La nouvelle manière, xpcnativewrappers=yes, est disponible à partir de Firefox 1.5 et ses pré-versions Deer Park alpha et beta.

Exemples à ne PAS suivre

MAUVAIS dans Firefox 1.0.2 et antérieur, car un script pourrait redéfinir l'accesseur nodeType :

return targetNode.nodeType == 1;

MAUVAIS dans Firefox 1.0.2 et antérieur, car un script pourrait redéfinir getSelection :

return contentWindow.getSelection();

MAUVAIS dans toutes les versions. Certains développeurs mal conseillés ont utilisé cette astuce dans le passé. Des scripts peuvent redéfinir getSelection dans d'anciennes versions et cela ne fonctionne plus du tout dans Firefox 1.0.3 et Mozilla 1.7.7 :

return contentWindow.__proto__.getSelection.call(contentWindow);

MAUVAIS dans Firefox 1.0.2 et antérieur, car un script pourrait redéfinir le second accesseur même si le premier est sûr :

var winWrapper = new XPCNativeWrapper(contentWindow, 'document');
// accéder à contentWindow.document est à présent sûr, mais récupérer .title du
// document obtenu ne l'est toujours pas.
return winWrapper.document.title;

MAUVAIS dans les versions antérieurs à Firefox 1.5, car les scripts peuvent définir document.open pour les documents non-HTML, qui n'ont pas la fonction DOM document.open :

return contentWindow.document.open();


Étiquettes et contributeurs liés au document

Contributeurs ayant participé à cette page : BenoitL, Chbok, Mgjbot
Dernière mise à jour par : Mgjbot,