Reguła tego samego pochodzenia (Same-origin policy)
Same-origin policy (reguła tego samego pochodzenia) to istotny mechanizm bezpieczeństwa, który określa sposób, w jaki dokument lub skrypt jednego pochodzenia (origin (en-US)) może komunikować się z zasobem innego pochodzenia. Pozwala to na odizolowanie potencjalnie szkodliwych dokumentów i tym samym redukowane są czynniki sprzyjające atakom.
Definicja "origin"
Dwa URLe są tego samego pochodzenia, jeśli protocol (en-US), port (en-US) (jeśli wyszczególniony) oraz host (en-US) są takie same dla obu. Tego typu charakterystykę nazywa się "krotką schematu/hosta/portu" ("scheme/host/port tuple") lub po prostu "krotką" ("Krotka" to kolekcja elementów tworzących zbiór - generyczna forma, która może być podwójna/potrójna/poczwórna itd.).
Poniższa tabela zawiera przykłady zestawień "originów" z URLem http://store.company.com/dir/page.html
:
URL | Wynik | Powód |
---|---|---|
http://store.company.com/dir2/other.html |
Same origin | Różni się tylko ścieżka |
http://store.company.com/dir/inner/another.html |
Same origin | Różni się tylko ścieżka |
https://store.company.com/page.html |
Niepowodzenie | Inny protokół |
http://store.company.com:81/dir/page.html |
Niepowodzenie | Inny port (http:// domyślnie jest portem 80) |
http://news.company.com/dir/page.html |
Niepowodzenie | Inny host |
Zobacz również definicję "origin" dla URLów file:
, ich zestawienie jest bardziej złożone.
Odziedziczone "origin"
Skrypty wywoływane przez strony z URLami about:blank
lub javascript:
dziedziczą "origin" dokumentu zawierającego ten URL, ponieważ tego typu URLe nie zawierają informacji o serwerze źródłowym.
Przykładowo, about:blank
jest często używany jako URL nowego, pustego, wyskakującego okienka, w którym skrypt-rodzic umieszcza treść (np. przez mechanizm Window.open()
). Jeśli dane okienko zawiera również JavaScript, skrypt odziedziczy ten sam "origin" jak skrypt, który je utworzył.
data:
URLe zyskują nowy, pusty kontekst bezpieczeństwa.
Wyjątki w Internet Explorer
W Internecie Explorerze istnieją dwa wyjątki od reguły same-origin:
- Strefy Zaufania
- Jeśli obie domeny znajdują się w strefie wysokiego zaufania (np. firmowe domeny intranetu), wówczas ograniczenia same-origin nie są stosowane.
- Port
- IE nie bierze pod uwagę portów w trakcie sprawdzania obecności tego samego pochodzenia. Przykładowo,
https://company.com:81/index.html
ihttps://company.com/index.html
są uznawane za posiadające ten sam "origin", więc nie są implementowane żadne ograniczenia .
Wspomniane wyjątki są niestandardowe i nie są wspierane przez inne przeglądarki.
Zmiana origin
Strona może zmieniać swoje pochodzenie przy zachowaniu pewnych ograniczeń. Skrypt może nadać wartość document.domain
równą swojej obecnej domenie lub superdomenie swojej obecnej domeny. Jeśli odwołuje się do superdomeny obecnej domeny, wówczas krótsza superdomena jest brana pod uwagę przy kontroli same-origin.
Załóżmy, że skrypt z dokumentu pod adresem http://store.company.com/dir/other.html
wywołuje poniższą linijkę:
document.domain = "company.com";
Następnie strona może przejść pomyślnie kontrolę same-origin mając adres http://company.com/dir/page.html
(przyjmując, że http://company.com/dir/page.html
ma document.domain
równe "company.com
" by wskazać, że chce na to zezwalać - sprawdź: document.domain
). Jednakże, company.com
nie może ustawić document.domain
na othercompany.com
, ponieważ nie jest to superdomena company.com
.
Numer portu jest sprawdzany oddzielnie przez przeglądarkę. Każde odwołanie do document.domain
, w tym document.domain = document.domain
, spowoduje przypisanie numerowi portu wartości null
. Jednakże, nie uda się nawiązać komunikacji company.com:8080
z company.com
tylko poprzez umieszczenie document.domain = "company.com"
w pierwszym z nich. Taki zapis musi znajdować się w obu dokumentach, aby ich porty były równocześnie równe null
.
Zauważ: Używając document.domain
, żeby pozwolić subdomenie na bezpieczny dostęp do rodzica potrzebujesz ustawić document.domain
na tę samą wartość jednocześnie w domenie rodzica i w subdomenie. Jest to wymagane nawet podczas zwykłego przywracania domeny rodzica do pierwotnej wartości. Niepowodzenie może skutkować błędami dostępu.
Dostęp sieciowy cross-origin (międzyźródłowy)
Reguła tego samego pochodzenia kontroluje interakcje pomiędzy dwoma różnymi "originami", np. kiedy używasz elementu XMLHttpRequest
czy <img>
(en-US). Tego typu interakcje przeważnie dzielą się na trzy kategorie:
- zapisy cross-origin przeważnie są dopuszczane. Przykłady to: linki, przekierowania i wypełnienia formularzy. Niektóre zapytania HTTP wymagają preflightu.
- osadzanie cross-origin jest przeważnie dopuszczane. (przykłady zostały wylistowane poniżej)
- odczyty cross-origin przeważnie nie są dopuszczane, ale dostęp do odczytu jest zwykle możliwy przez osadzanie. Przykładowo, możliwy jest odczyt wymiarów osadzonego obrazka, działanie osadzonego skryptu czy dostępność osadzonego źródła.
Poniżej znajdują się przykłady zasobów, które można osadzać międzyźródłowo:
- JavaScript z
<script src="…"></script>
. Szczegóły dot. błędu dla błędów składniowych są dostępne wyłącznie dla skryptów same-origin. - CSS podpinany poprzez
<link rel="stylesheet" href="…">
. Zgodnie z luźniejszymi zasadami składni CSS, cross-originowy CSS wymaga poprawnego nagłówkaContent-Type
. Ograniczenia różnią się w zależności od przeglądarki: IE, Firefox, Chrome, Safari (przewiń do CVE-2010-0051) i Opera. - Obrazki wyświetlane poprzez
<img>
(en-US). - Media odtwarzane poprzez
<video>
i<audio>
(en-US). - Wtyczki osadzane za pomocą
<object>
(en-US),<embed>
(en-US) oraz<applet>
. - Czcionki używane poprzez
@font-face
(en-US). Niektóre przeglądarki zezwalają na czcionki cross-origin, inne wymagają same-origin. - Cokolwiek osadzane poprzez
<frame>
(en-US) i<iframe>
. Strony mogą używać nagłówka X-Frame-Options (en-US), by zapobiegać framingowi cross-origin.
Jak umożliwić dostęp cross-origin
Poprzez CORS można zezwolić na dostęp cross-origin. CORS jest częścią HTTP (en-US), co pozwala serwerom na określanie, które hosty są upoważnione do ładowania treści z tego serweru.
Jak zablokować dostęp cross-origin
- By uniemożliwić zapisy cross-origin należy sprawdzić token w żądaniu — chodzi konkretniej o token Cross-Site Request Forgery (CSRF). Odczyty typu cross-origin muszą być zablokowane na stronach używających tego typu tokenu.
- By uniemożliwić odczyty cross-origin należy upewnić się, że dane zasoby nie są osadzalne. Często koniecznym jest uniemożliwienie osadzania, ponieważ osadzanie źródła zawsze ujawnia jakieś informacje o nim.
- By uniemożliwić osadzanie cross-origin należy upewnić się, że dane zasoby nie mogą być interpretowane jako jeden z osadzanych formatów wylistowanych poniżej. Przeglądarki mogą ignorować nagłówki
Content-Type
. Przykładowo, jeśli w dokumencie HTML umieszczony zostanie tag<script>
, przeglądarka będzie próbować parsować HTML jako JavaScript. Jeśli zasób nie jest głównym podprogramem strony do zapobiegania osadzaniu można dodatkowo użyć tokenu CSRF.
Dostęp cross-origin API skryptu
API JavaScriptu, jak iframe.contentWindow
(en-US), window.parent
(en-US), window.open
i window.opener
pozwalają dokumentom na bezpośrednią, wzajemną referencję. Jeśli dwa dokumenty nie są tego samego pochodzenia, referencje te umożliwiają bardzo ograniczony dostęp do obiektów Window
i Location
, jako opisano w następnych dwóch sekcjach.
Do komunikacji pomiędzy dokumentami o różnym pochodzeniu stosuje się window.postMessage
(en-US).
Specyfikacja: Standard HTML § Obiekty cross-origin.
Window
Poniższy dostęp cross-origin jest dopuszczany w przypadku wymienionych właściwości Window
:
Własności | |
---|---|
window.closed |
Tylko do odczytu. |
window.frames |
Tylko do odczytu. |
window.length (en-US) |
Tylko do odczytu. |
window.location (en-US) |
Odczyt/Zapis. |
window.opener |
Tylko do odczytu. |
window.parent (en-US) |
Tylko do odczytu. |
window.self (en-US) |
Tylko do odczytu. |
window.top (en-US) |
Tylko do odczytu. |
window.window (en-US) |
Tylko do odczytu. |
Niektóre przeglądarki zezwalają na dostęp większej ilości właściwości, niż wypisane powyżej.
Location
Poniższy dostęp cross-origin jest dopuszczany w przypadku właściwości Location
:
Metody |
---|
location.replace (en-US) |
Atrybuty | |
---|---|
URLUtils.href |
Tylko do zapisu. |
Niektóre przeglądarki umożliwiają dostęp do większej liczby właściwości, niż wymienione powyżej.
Dostęp cross-origin do danych pamięci
Dostęp do danych przechowywanych w przeglądarce, jak localStorage czy IndexedDB są odseparowane pochodzeniem. Każdy origin otrzymuje własną, odseparowaną pamięć i JavaScript jednego pochodzenia nie może odczytywać lub wpisywać niczego do pamięci należącej do innego originu.
Ciasteczka (cookies) używają oddzielnej definicji originów. Strona może ustalić ciasteczko dla własnej domeny lub domeny-rodzica dopóki, gdy domena-rodzic nie jest sufiksem publicznym. Firefox i Chrome używają listy sufiksów publicznych (Public Suffix List), by zweryfikować czy domena jest sufiksem publicznym. Internet Explorer używa własnej, wewnątrznej metody weryfikacji czy domena jest sufiksem publicznym. Przeglądarka udostępni ciasteczko podanej domenie zawierającej jakiekolwiek subdomeny, niezależnie jaki protokół (HTTP/HTTPS) czy port jest używany. Przy ustalaniu ciasteczka możliwe jest określenie limitu dostępności używając flag domeny (Domain), ścieżki (Path), bezpiecznej (Secure) i Http-Only. Gdy odczytywane jest ciasteczko nie można zobaczyć, gdzie zostało ustalone. Nawet jeśli używane są wyłącznie bezpieczne połączenia https dane ciasteczko mogło zostać ustalone poprzez połączenie niebezpieczne.
Zobacz również
- Reguła same-origin dla file: URIy
- Reguła Same-Origin na W3C
- https://web.dev/secure/same-origin-policy
Informacje dot. dokumentu źródłowego
- Author(s): Jesse Ruderman