Integralność podzasobów (Subresource Integrity)

Subresource Integrity (SRI), w wolnym tłumaczeniu "integralność podzasobów", to funkcja bezpieczeństwa umożliwiająca przeglądarkom weryfikowanie, czy zasoby, które przechwytują (np. z CDN) docierają do nich bez nieporządanych zmian. Działanie takie jest możliwe dzięki używaniu hasha kryptograficznego, z którym przechwycony zasób musi być zgodny.

Notka: W celu weryfikacji integralności podzasobów danych przekazywanych ze źródła innego, niż dokument w którym są osadzane przeglądarki dodatkowo sprawdzają źródło poprzez międzyźródłowe udostępnianie zasobów, tzw. Cross-Origin Resource Sharing (CORS). Dzięki temu upewniają się, że pochodzenie (origin) oferujące dane zasoby pozwala na udostępnianie ich z innym, sprecyfizowanym originem.

Korzyści wynikające z "Subresource Integrity"

Używając Content Delivery Networks (CDNs) do hostowania plików, jak np. skrypty czy arkusze stylów, które są udostępnianie pośród licznych stron WWW można polepszyć wydajność strony i zachować przepustowość łącza. Jednakże, używając CDNów ryzykujemy, że jeśli atakujący przejmie kontrolę nad CDNem to może wprowadzić szkodliwą zawartość do plików na CDNie (lub zupełnie je zastąpić) i przez to potencjalnie może zaatakować wszystkie strony, które przechwytują pliki z tego CDNu.

"Subresource Integrity" pozwala na ograniczenie ryzyka ataków tego typu poprzez zapewnienie, że pliki które dana aplikacja, bądź dokument WWW przechwytują (m. in. z CDNu) zostały dostarczone bez udziału trzeciej strony, która "wzbogaciła" nasze dane o dodatkową treść oraz bez żadnych, jakichkolwiek innych zmian w przesyłanych plikach.

Używanie "Subresource Integrity"

Korzystanie z funkcji "Subresource Integrity" jest możliwe przez określenie hasha zakodowanego kryptograficznie w base64 zasobu (pliku), który przeglądarka ma przechwycić, z wartością atrybutu integrity danego elementu <script> or <link>.

Wartość integrity zaczyna się od co najmniej jednego stringu, przy czym każdy string zawiera prefiks wskazujący na konkretny algorytm hashowy (obecnie dozwolonymi prefiksami są sha256, sha384, i sha512), następnie opatrzony myślnikiem i zakończony aktualnym hashem zakodowanym w base64.

Notka: Wartość integrity może zawierać liczne hashe oddzielone białymi znakami. Zasób zostanie załadowany, jeśli dopasuje się z jednym z tych hashów.

Przykładowy string integrity z hashem sha384 zakodowanym w base64:

sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC

Więc oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC to część "hashowa", a prefiks sha384 wskazuje, że jest to hash sha384.

Notka: Część "hashowa" wartości integrity jest, mówić ściśle, skrótem kryptograficznym formowanym przez zastosowanie określonych funkcji hashowych do danego outputu (np. skryptu lub arkuszu stylów). Zwykle używa się skrótu "hash" do określania skrótu kryptograficznego, więc w taki sposób to określenie jest używane w niniejszym artykule.

Narzędzia do generowania hashów SRI

Możesz generować hashe SRI z konsoli z openssl używając wywołania polecenia, jak:

cat FILENAME.js | openssl dgst -sha384 -binary | openssl base64 -A

lub z shasum używając wywołania polecenia, jak:

shasum -b -a 384 FILENAME.js | awk '{ print $1 }' | xxd -r -p | base64

Notka:

  • Krok z xxd pobiera dane wyjściowe w postaci heksadecymalnej z shasum i zamienia je na zapis binarny.
  • Krok z awk jest niezbędny, ponieważ shasum w danych wyjściowych przekazuje zahashowaną nazwę pliku do xxd. Trzeba liczyć się z katastrofalnymi konsekwencjami, jeśli nazwa pliku zawiera znaki występujące w zapisie heksadecymalnym - xxd odkoduje ten zapis i przekaże go do base64.

Warto wiedzieć, że dostępny na https://www.srihash.org/ SRI Hash Generator to narzędzie online umożliwiające generowanie hashy SRI.

Zasady bezpieczeństwa zawartości i Integralności podzasobów(Content Security Policy & Subresource Integrity)

Możesz skorzystać z Zasad bezpieczeństwa zawartości (Content Security Policy), by skonfigurować swój serwer, żeby wymuszał by określone typy plików wymagały stosowania Subresource Integrity. Aby to zrobić użyj dyrektywy require-sri-for w swoim nagłówku CSP, np.:

Content-Security-Policy: require-sri-for script;

Dzięki temu zapisowi każda próba załadowania JavaScript powiedzie się jedynie, jeśli informacja o Subresource Integrity znajduje się na miejscu, a testy integralności zakończą się sukcesem.

Możesz również określić, że SRI powinno być stosowane podczas ładowania arkuszy stylów:

Content-Security-Policy: require-sri-for style;

Możesz również określić zarówno script, jak i style aby wymagać SRI przy obu typach plików.

Udostępnianie zasobów między źródłami i Integralności podzasobów (Cross-Origin Resource Sharing & Subresource Integrity)

Celem weryfikacji integralności podzasobów danych pochodzących z originu innego, niż dokument, w którym są osadzone, przeglądarki dodatkowo sprawdzają dane za pomocą CORS (Cross-Origin Resource Sharing). Upewniają się, że origin dostarczający dane pozwala na udostępnianie wnioskującemu originowi. Wtedy dane muszą zostać dostarczone z nagłówkiem Access-Control-Allow-Origin, co pozwala na udostępnienie danych wnioskującemu originowi, np.:

Access-Control-Allow-Origin: *

Przykłady

W poniższych przykładach przyjmimy, że oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC to oczekiwany hash SHA-384 (skrót) określonego skryptu example-framework.js i że istnieje kopia skryptu hostowana na https://example.com/example-framework.js.

Subresource Integrity with the <script> element

Możesz użyć niniejszego elementu <script>, by nakazać przeglądarce, aby przed wywołaniem skryptu https://example.com/example-framework.js najpierw porównała skrypt z oczekiwanym hashem i zweryfikowała, że są dopasowane.

<script src="https://example.com/example-framework.js"
        integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
        crossorigin="anonymous"></script>

Notka: By dowiedzieć się więcej nt. zastosowania atrybutu crossorigin sprawdź atrybuty ustawień CORS.

Jak przeglądarki radzą sobie z "Subresource Integrity"

Przeglądarki radzą sobie z SRI poprzez podjęcie poniższych działań:

  1. Kiedy przeglądarka napotka element <script> lub <link> z atrybutem integrity, przed wywołaniem skryptu lub przed zastosowaniem jakiegokolwiek arkusza stylów określonego przez element <link>, przeglądarka musi najpierw porównać skrypt lub arkusz stylów do oczekiwanego hasha podanego w wartości integrity.

    Notka: Celem weryfikacji integralności podzasobów danych dostarczanych z originu innego, niż dokument, w którym zostały osadzone, przeglądarki dodatkowo sprawdzają dane poprzez stosowanie CORS, aby upewnić się, że origin dostarczający dane pozwala na udostępnianie ich z wnioskującym originem.

  2. Jeśli skrypt lub arkusz stylów nie pasuje do odpowiadającej mu wartości integrity, przeglądarka musi odmówić wywołania skryptu lub uwzględnienia arkusza stylów i zamiast tego musi zwrócić błąd sieciowy wskazujący, że nie powiodło się przechwycenie tego skryptu lub arkusza stylów.

Specyfikacje

Specyfikacja Status Komentarz
Subresource Integrity Recommendation
Fetch Living Standard

Kompatybilność z przeglądarkami

<script integrity>

Update compatibility data on GitHub
DesktopMobile
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidFirefox for AndroidOpera for AndroidSafari on iOSSamsung Internet
integrityChrome Full support 45Edge Partial support 17Firefox Full support 43IE No support NoOpera Full support YesSafari Full support YesWebView Android Full support 45Chrome Android Full support 45Firefox Android Full support 43Opera Android ? Safari iOS No support NoSamsung Internet Android Full support 5.0

Legend

Full support  
Full support
Partial support  
Partial support
No support  
No support
Compatibility unknown  
Compatibility unknown

CSP: require-sri-for

No compatibility data found. Please contribute data for "http.headers.csp.require-sri-for" (depth: 1) to the MDN compatibility data repository.

Zobacz również