mozilla
Wyniki wyszukiwania

    Bezpieczny dostęp do składników DOM z poziomu chrome

    Wprowadzenie

    Podczas tworzenia aplikacji i rozszerzeń, w których kodzie JavaScript używane są interfejsy DOM odwołujące się do treści niezaufanych (np. pochodzących ze stron internetowych), należy zachować ostrożność i sprawdzać, czy pobierane informacje rzeczywiście pochodzą z interfejsu API modelu DOM, czy też ich źródłem są własności JavaScript oraz metody pobierania i ustawiania zdefiniowane w kodzie destrukcyjnej strony. W programach Firefox 1.0.3 i Mozilla 1.7.7 wprowadzono mechanizmy utrudniające przesłanie fałszywych danych do aplikacji XUL i rozszerzeń — obecnie, gdy w kodzie JavaScript działającym na poziomie chrome uzyskiwany jest dostęp do własności lub metody DOM danego obiektu, zwracana jest własność lub metoda DOM, a nie zastępujące je niestandardowe własności lub metody zdefiniowane na stronie internetowej. W programie Firefox 1.5 zastosowano jeszcze bardziej ogólne rozwiązanie (aktywne w domyślnej konfiguracji): aby uzyskać niezabezpieczony dostęp do składników DOM z poziomu rozszerzenia, w jego kodzie należy jawnie wyłączyć blokadę.

    Istnieją tylko dwa „poprawne” sposoby uzyskiwania dostępu do składników DOM z kodu chrome: dostęp bezpośredni lub jawne użycie obiektu XPCNativeWrapper. Powszechnie stosowana metoda polegająca na użyciu własności __proto__ nie jest bezpieczna w żadnej z wersji programu (patrz poniżej Przykłady NIEPOPRAWNEGO kodu).

    W poniższej tabeli podsumowano kwestie bezpieczeństwa związane z zastosowaniem dwóch „poprawnych” sposobów:

    Dostęp bezpośredni Jawne użycie obiektu XPCNativeWrapper
    Firefox 1.0.2 lub starszy niebezpieczne bezpieczne
    Firefox 1.0.3 lub nowszy (1.0.x) bezpieczne, gdy zagwarantowano istnienie własności bezpieczne
    Firefox 1.5 bezpieczne, gdy ustawiono preferencję xpcnativewrappers=yes (wartość domyślna) bezpieczne

    Dostęp bezpośredni

    W skryptach, które zaprojektowano do uruchamiania wyłącznie w Firefoksie w wersji 1.0.3 oraz nowszych wersjach z serii 1.0.x, a także w skryptach działających w Firefoksie 1.5 lub nowszym przy ustawionej preferencji xpcnativewrappers=yes, wystarczy użyć następującego kodu:

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

    Dostęp bezpośredni w Firefoksie 1.0.3 (oraz nowszych wersjach z serii 1.0.x) jest bezpieczny dopóki, dopóty gwarantowane jest posiadanie przez obiekt danej własności lub metody, do której dostęp jest uzyskiwany za pośrednictwem deklaracji IDL obiektu. Na przykład własność foo.nodeType jest bezpieczna, jeżeli jest pewne, że zmienna foo jest obiektem typu Node; z kolei metoda foo.getSelection() jest bezpieczna, dopóki jest pewne, że zmienna foo reprezentuje okno (obiekt window). Przestrzeganie tych zasad może nie być łatwe — o ile na przykład obiekt nsIDOMNSHTMLDocument posiada metodę open(), o tyle nie ma jej obiekt nsIDOMXULDocument; użycie metody document.open() w Firefoksie 1.0.3 NIE jest więc bezpieczne, ponieważ obiekt document może reprezentować dokument XUL. W takich przypadkach należy skorzystać z operatora instanceof, aby określić, czy obiekt obsługuje dany interfejs IDL (w omawianym przykładzie jest to interfejs nsIDOMNSHTMLDocument).

    W Firefoksie 1.5 dostęp bezpośredni jest zawsze bezpieczny, chyba że w pliku manifestu rozszerzenia użyto wskaźnika xpcnativewrappers=no. W przypadku braku tego wskaźnika obiekty XPCNativeWrapper stosowane są domyślnie.

    Jawne użycie obiektu XPCNativeWrapper

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

    Należy zwrócić uwagę, że w powyższym przykładzie zastosowano dwa obiekty opakowujące, aby uzyskać dostęp do własności window.document.title — jeden do uzyskania dostępu do własności document obiektu window, natomiast drugi do odczytania własności title obiektu document.

    Korzystanie z obiektów XPCNativeWrapper jest bezpieczne we wszystkich wersjach Firefoksa, choć zmniejsza czytelność kodu i wymaga opakowania każdego obiektu DOM.

    Więcej informacji o stosowanej składni można znaleźć w artykule na temat obiektów XPCNativeWrapper w bazie wiedzy witryny MozillaZine.

    Obiekty XPCNativeWrapper

    Obiekty XPCNativeWrapper służą do opakowywania innych obiektów, tak aby można było do nich uzyskać bezpieczny dostęp z poziomu kodu uprzywilejowanego.

    Istnieją dwa sposoby korzystania z obiektów XPCNativeWrapper. Starszy sposób polega na jawnym użyciu ich w kodzie. Sposób nowszy (zastosowanie preferencji xpcnativewrappers=yes) jest dostępny w programie Firefox 1.5 i w nowszych wersjach (a także we wstępnych wydaniach alfa o nazwie Deer Park oraz edycjach beta).

    Przykłady NIEPOPRAWNEGO kodu

    NIEPOPRAWNE w Firefoksie 1.0.2 i starszych — skrypt może zastąpić metodę pobierania nodeType:

    return targetNode.nodeType == 1;
    

    NIEPOPRAWNE w Firefoksie 1.0.2 i starszych — skrypt może zastąpić metodę getSelection:

    return contentWindow.getSelection();
    

    NIEPOPRAWNE we wszystkich wersjach. Niektórzy programiści korzystali kiedyś z tego niepewnego sposobu. W starszych wersjach przeglądarki skrypt może zastąpić metodę getSelection, a ponadto sposób ten w ogóle nie działa w programach Firefox 1.0.3 i Mozilla 1.7.7:

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

    NIEPOPRAWNE w Firefoksie 1.0.2 i starszych — skrypt może zastąpić wewnętrzną metodę pobierania, nawet jeżeli metoda zewnętrzna jest bezpieczna:

    var winWrapper = new XPCNativeWrapper(contentWindow, 'document');
    // dostęp do obiektu contentWindow.document jest teraz bezpieczny, ale odczytywanie własności .title  
    // spoza zwracanego dokumentu wciąż nie jest bezpieczne.
    return winWrapper.document.title;
    

    NIEPOPRAWNE w Firefoksie w wersjach starszych niż 1.5 — skrypt może ustawić metodę document.open dla dokumentów innych niż dokumenty HTML, w których nie istnieje metoda DOM document.open:

    return contentWindow.document.open();
    

    Autorzy i etykiety dokumentu

    Contributors to this page: Flaneur, gandalf, Killerowski, Mgjbot, Ptak82, Dria
    Ostatnia aktualizacja: Flaneur,