Zrozumienie integralności podzasobów
Opublikowany: 2022-03-10 Jeśli kiedykolwiek korzystałeś z hostowanej przez CDN wersji biblioteki JavaScript, być może zauważyłeś dziwnie wyglądający atrybut integrity
w tagu skryptu. Ten atrybut zawiera pozornie nieskończone alfanumeryczne śmieci, które możesz pokusić się o usunięcie w poszukiwaniu czystszego kodu.
Wszystkie te śmieci to w rzeczywistości naprawdę przydatna funkcja bezpieczeństwa o nazwie Subresource Integrity (SRI), która może pomóc w ochronie Twojej witryny przed niektórymi rodzajami włamań i włamań. W tym artykule przyjrzymy się, czym jest SRI, w jaki sposób może pomóc chronić Cię i jak możesz zacząć go używać we własnych projektach, nie tylko w przypadku plików hostowanych w sieciach CDN.
Trochę historii
Dawno temu, w czasach, gdy JavaScript był znacznie uboższym kuzynem HTML i CSS, nie musieliśmy zbyt wiele zastanawiać się nad tym, jak nasze skrypty mogłyby zostać użyte jako wektor ataku na nasze strony internetowe. Większość witryn była hostowana na jednym fizycznym serwerze, gdzieś w naszej własnej infrastrukturze hostingowej, i był to serwer, o którego obronie myśleliśmy, jeśli chodzi o najlepsze praktyki bezpieczeństwa.
W miarę jak przeglądarki stawały się coraz bardziej wydajne, a połączenia sieciowe stawały się coraz grubsze, zaczęliśmy używać coraz więcej JavaScriptu, a w końcu zaczęły pojawiać się biblioteki JavaScript wielokrotnego użytku. W tamtych czasach biblioteki takie jak script.aculo.us, Prototype i ostatecznie jQuery zaczęły zdobywać popularność wśród programistów chcących dodać więcej interaktywności do swoich stron.
Wraz z dodanymi bibliotekami i kolejnymi wtyczkami pojawiła się waga strony i wkrótce zaczęliśmy poważnie myśleć o wydajności front-endu. Zasoby takie jak Content Delivery Networks (CDN), które wcześniej były zarezerwowane dla gigantycznych korporacji, stały się powszechne w codziennym tworzeniu zgrabnych stron internetowych.
Po drodze pewna błyskotliwa iskra zauważyła, że wszystkie witryny żądały własnych kopii popularnych bibliotek — takich jak najnowsza wersja jQuery — i gdyby istniała wspólna wersja tych bibliotek w CDN, z której mogłaby korzystać każda witryna, użytkownik nie Nie trzeba ciągle pobierać tego samego pliku. Przyjęliby trafienie dla pierwszej witryny, która użyje pliku, ale potem znalazłby się on w pamięci podręcznej ich lokalnej przeglądarki, a pobieranie mogło zostać pominięte dla każdej kolejnej witryny. Geniusz!
Właśnie dlatego zobaczysz łącza CDN do swoich ulubionych bibliotek za pomocą adresów URL, takich jak jsdelivr.com
— korzystają one ze wspólnej sieci CDN do hostowania plików, aby użytkownicy mogli zobaczyć korzyści związane z wydajnością.
Co mogłoby pójść źle?
Pozostaje to dobrym, praktycznym sposobem działania, ale wprowadza potencjalny wektor ataku. Wyobraźmy sobie, że jest rok 2012 i wszyscy używają zupełnie nowego jQuery 1.8. Wracając do tradycyjnego sposobu robienia rzeczy, każdy miałby swój własny plik jQuery 1.8 hostowany jako część własnej witryny na własnym serwerze.
Gdybyś był jakimś złym aktorem — jak jakiś rodzaj Hamburglara opartego na jQuery — i wymyślił podstępny sposób na zhakowanie biblioteki dla własnych złych korzyści, musiałbyś kierować reklamy na każdą witrynę indywidualnie i skompromitować ich serwery, aby mieć jakikolwiek wpływ. To dużo wysiłku.
Ale teraz tak nie jest, ponieważ wszyscy używają jQuery ładowanego ze wspólnego CDN. A kiedy mówię wszyscy, nie mam na myśli setek stron internetowych. Mam na myśli miliony stron internetowych. Nagle ten jeden plik stał się bardzo atrakcyjnym celem dla naszego podejrzanego hakera. Jeśli uda im się złamać ten jeden plik, bardzo szybko mogą uruchomić kod na milionach stron internetowych na całym świecie.
Nie ma znaczenia, jaki to kod. Może to być żart polegający na niszczeniu stron, może to być kod do kradzieży haseł, może to być kod do kopania kryptowaluty lub może to być podstępne narzędzie śledzące, które śledzi Cię w sieci i tworzy profil marketingowy. Ważną rzeczą jest to, że niewinny plik dodany przez programistę do strony został zmieniony i masz teraz złośliwy kod JavaScript działający jako część Twojej witryny. To duży problem.
Wprowadź integralność podzasobów
Zamiast cofać zegary i rezygnować z użytecznego sposobu korzystania z kodu, SRI to rozwiązanie, które dodaje prosty poziom bezpieczeństwa. To, co robi SRI i atrybut integrity
, to upewnienie się, że plik, który łączysz ze stroną, nigdy się nie zmienia. A jeśli to się zmieni, przeglądarka go odrzuci.
Sprawdzanie, czy kod się nie zmienił, jest bardzo starym problemem w informatyce i na szczęście ma kilka bardzo dobrze ugruntowanych rozwiązań. SRI wykonuje dobrą robotę, przyjmując najprostszy — hashowanie plików.
Haszowanie pliku to proces pobierania pliku i przeprowadzania go przez algorytm, który redukuje go do reprezentacji krótkiego ciągu, znanej jako skrót lub suma kontrolna. Bez wchodzenia w chwasty, proces jest albo powtarzalny, albo odwracalny, do tego stopnia, że gdybyś dał komuś plik wraz z hashem, byłby w stanie uruchomić ten sam algorytm, aby sprawdzić, czy te dwa pasują. Jeśli plik ulegnie zmianie lub zmieni się skrót, oznacza to, że nie ma już dopasowania i wiesz, że coś jest nie tak i powinieneś nie ufać plikowi.
Kiedy używasz SRI, twoja strona internetowa przechowuje skrót, a serwer (CDN lub gdziekolwiek) przechowuje plik. Przeglądarka pobiera plik, a następnie szybko wykonuje obliczenia, aby upewnić się, że jest zgodny z hashem w atrybucie integrity
. Jeśli pasuje, plik jest używany, a jeśli nie, jest blokowany.
Wypróbowanie
Jeśli dziś pójdę na getbootstrap.com
, aby uzyskać łącze CDN do wersji Bootstrap, dostanę tag, który wygląda tak:
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
Widać, że atrybut src
jest taki, do jakiego przywykliśmy, a atrybut integrity
zawiera to, co teraz wiemy, że jest haszem.
Skrót składa się w rzeczywistości z dwóch części. Pierwszym z nich jest prefiks deklarujący, którego algorytmu mieszającego należy użyć. W tym przypadku jest to sha384
. Po nim następuje myślnik, a następnie sam hash, zakodowany za pomocą base64
.
Być może znasz base64
jako sposób kodowania plików wbudowanych, takich jak obrazy, na strony. Nie jest to proces kryptograficzny — to po prostu szybki i wygodny sposób na kodowanie potencjalnie nieuporządkowanych danych w sposób, który można zgrabnie przetłumaczyć na ASCII. Dlatego jest często używany w sieci.

Widząc to, przeglądarka pobierze bootstrap.min.js
. Przed jego wykonaniem zdekoduje on hash base64
, a następnie użyje algorytmu mieszającego sha384
, aby potwierdzić, że hash pasuje do pliku, który właśnie został pobrany. Jeśli pasuje, plik jest wykonywany.
Mogę to przetestować, umieszczając ten tag na stronie, a następnie przechodząc do karty Sieć w narzędziach przeglądarki, aby zobaczyć, czy plik został załadowany.

Widzę, że bootstrap.min.js
(a także plik jQuery, którego potrzebuje) zostały pomyślnie załadowane.
Zobaczmy, co by się stało, gdybym zaktualizował hash tak, aby był czymś, o czym wiem, że jest niepoprawny.
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-SmashingMagazineIsCoolForCats" crossorigin="anonymous"></script>

Jak widać, skrót określony na mojej stronie nie pasuje już do pliku, więc plik zostaje zablokowany.
Korzystanie z SRI we własnych projektach
Posiadanie tej możliwości dla bibliotek w CDN jest świetne, a jeśli widzisz opcję użycia osadzonego pliku z atrybutem integrity
, zdecydowanie powinieneś preferować tę opcję. Ale nie ogranicza się to do dużych projektów w sieciach CDN, możesz używać tego samodzielnie do własnych witryn.
Wyobrażenie sobie scenariusza, w którym hakerowi udaje się uzyskać dostęp do zaledwie kilku plików w Twojej witrynie, wcale nie jest zbyt daleko idące. Myślę, że większość z nas spotkała się z klientem, kolegą lub przyjacielem, który w pewnym momencie miał witrynę WordPress zhakowaną przez mnóstwo paskudnych śmieci, o których nawet nie zdawali sobie sprawy.
SRI może Cię przed tym chronić. Jeśli wygenerujesz skróty integralności dla własnych plików, możesz sprawić, że Twoja witryna odrzuci wszelkie zmiany, tak jak w przypadku pliku hostowanego zdalnie.
Generowanie haszy
Możesz, jak można się spodziewać, uruchomić kilka poleceń na terminalu komputera, aby wygenerować skrót dla pliku. Ten przykład, jak to zrobić, pochodzi ze strony MDN Subresource Integrity:
cat FILENAME.js | openssl dgst -sha384 -binary | openssl base64 -A
Pobiera to zawartość FILENAME.js
i przekazuje ją jako dane wejściowe do openssl
w celu utworzenia skrótu za pomocą sha384
, który jest następnie przekazywany jako dane wejściowe do innego polecenia openssl
w celu zakodowania wyniku w base64
. Jest to nie tylko skomplikowane i niejasne, ale także nie jest to coś, co chcesz robić ręcznie za każdym razem, gdy zmienia się plik JavaScript.
Bardziej przydatne, będziesz chciał jakoś zintegrować to z procesem budowania swojej witryny i jak możesz sobie wyobrazić, jest tam wiele gotowych opcji. Dokładna implementacja będzie się bardzo różnić w zależności od projektu, ale oto kilka elementów konstrukcyjnych.
Jeśli używasz Gulp do tworzenia swoich witryn, istnieje gulp-sri, który wygeneruje plik JSON z listą twoich plików i ich hashami. Możesz to wykorzystać w swojej witrynie. Na przykład w przypadku dynamicznie renderowanej witryny możesz utworzyć wtyczkę szablonu, aby odczytać ten plik i w razie potrzeby dodać skróty do szablonów.
Jeśli nadal korzystasz z Gulpa, ale masz witrynę statyczną (lub witrynę generowaną statycznie), możesz użyć gulp-sri-hash, który będzie faktycznie działał przez twoje strony HTML i modyfikował strony, aby dodać skróty tam, gdzie jest to potrzebne, co jest bardzo przydatne.
Jeśli używasz Webpack, istnieje strona internetowa-subresource-integrity, która w prawdziwym stylu Webpack jest bardziej złożona, niż ktokolwiek mógłby się tego spodziewać, ale wydaje się, że działa.
Dla tych, którzy używają silnika szablonów Handlebars, wydaje się, że dostępne są opcje, a jeśli proces budowania to tylko podstawowy JavaScript, są tam również proste rozwiązania.
Jeśli korzystasz z CMS, takiego jak WordPress, znalazłem wtyczkę, która wydaje się to ułatwiać, chociaż sam jej nie próbowałem. Wyszukiwanie w Google wybranej platformy z SRI lub Sub Resource Integrity prawdopodobnie wskaże Ci właściwy kierunek.
Zasadniczo chcesz podpiąć swój skrót po tym , jak pliki JavaScript zostaną zminimalizowane, a następnie udostępnić ten skrót w dowolnej części systemu, która wyprowadza <script>
. Jednym z cudów platformy internetowej jest to, że jest ona tak różnorodna technicznie, ale niestety nie jestem w stanie podać dobrych instrukcji implementacji!
Inne rzeczy do zapamiętania
W tym artykule dużo mówiłem o plikach JavaScript, ponieważ to właśnie tam najbardziej sensowna jest obrona przed atakami hakerskimi. SRI działa również z CSS, więc możesz go używać w dokładnie ten sam sposób. Ryzyko wystąpienia złośliwego kodu CSS jest znacznie mniejsze, ale nadal istnieje ryzyko uszkodzenia witryny i kto wie, jakie błędy przeglądarki mogą również prowadzić do nieumyślnego narażenia witryny przez CSS na hakera. Więc to działa również przy użyciu SRI.
Inną interesującą rzeczą, jaką możesz zrobić, jest użycie polityki bezpieczeństwa treści, aby określić, że każdy skrypt (lub style) na twojej stronie musi używać SRI i oczywiście, że SRI musi być weryfikowany.
Content-Security-Policy: require-sri-for script;
Jest to sposób na zapewnienie, że SRI jest zawsze używany, co może być przydatne w witrynach, nad którymi pracuje wielu członków zespołu, którzy mogą, ale nie muszą, być w pełni na bieżąco z tym, jak to robić. Ponownie, dobrym miejscem, aby przeczytać więcej na ten temat, są zawsze świetne dokumenty MDN dotyczące integralności zasobów podrzędnych.
Ostatnią rzeczą, o której warto wspomnieć, jest obsługa SRI przez przeglądarkę. Wsparcie w nowoczesnych przeglądarkach jest szerokie, z głównym wyjątkiem jest Internet Explorer. Ze względu na sposób, w jaki specyfikacja została zaimplementowana wstecznie, od razu można z niej bezpiecznie korzystać. Przeglądarki, które rozumieją atrybut integrity
, będą używać skrótu i sprawdzać integralność, a starsze przeglądarki będą działać tak, jak zawsze i nadal działać. Oczywiście nie uzyskasz dodatkowej ochrony w tych starszych przeglądarkach, ale będziesz w przeglądarkach, które oferują wsparcie.
Wniosek
Widzieliśmy nie tylko, co robią te dziwne skróty w atrybutach integrity
, ale także jak możemy je wykorzystać do obrony przed niektórymi rodzajami ataków na naszą witrynę. Oczywiście nie ma jednej srebrnej kuli, która obroni nasze strony przed wszelkiego rodzaju exploitami, ale Subresource Integrity to naprawdę przydatne narzędzie w łańcuchu.
Wykorzystywanie luki w zabezpieczeniach często polega na zebraniu wielu małych elementów w szeregu. Jeśli A jest na miejscu i możesz sprawić, że B się wydarzy, to błąd w C umożliwia D. Funkcje przeglądarki, takie jak SRI, dają nam dobry sposób na nieco większe ograniczenie i potencjalne przerwanie tego łańcucha i uniemożliwienie hakerowi uzyskania tego, czego chce. Co więcej, jeśli możesz zintegrować go z procesem budowania lub CMS, jest to coś, co powinieneś raz skonfigurować, a potem zapomnieć i nie spowoduje to codziennych niedogodności.
W związku z tym naprawdę polecam poważnie przyjrzeć się integralności Subresource Integrity i wdrożyć ją w swoich witrynach, jeśli możesz.