Wskazówki dotyczące ograniczania zagrożeń dla renderowania statycznego po stronie serwera ASP.NET Core Blazor

W tym artykule wyjaśniono zagadnienia dotyczące zabezpieczeń, które deweloperzy powinni wziąć pod uwagę podczas tworzenia Blazor usługi Web Apps ze statycznym renderowaniem po stronie serwera.

Blazor łączy trzy różne modele w jednym do pisania interaktywnych aplikacji internetowych. Tradycyjne renderowanie po stronie serwera, które jest modelem żądania/odpowiedzi na podstawie protokołu HTTP. Interaktywne renderowanie po stronie serwera, które jest modelem renderowania opartym na .SignalR Na koniec renderowanie po stronie klienta, czyli model renderowania oparty na zestawie WebAssembly.

Wszystkie ogólne zagadnienia dotyczące zabezpieczeń zdefiniowane dla trybów renderowania interakcyjnego mają zastosowanie do Blazor usługi Web Apps, gdy istnieją składniki interaktywne renderowania w jednym z obsługiwanych trybów renderowania. W poniższych sekcjach opisano zagadnienia dotyczące zabezpieczeń specyficzne dla nieinterakcyjnego renderowania po stronie serwera w Blazor usłudze Web Apps oraz konkretne aspekty, które mają zastosowanie w przypadku interakcji między trybami renderowania.

Ogólne zagadnienia dotyczące renderowania po stronie serwera

Model renderowania po stronie serwera (SSR) jest oparty na tradycyjnym modelu żądań/odpowiedzi protokołu HTTP. W związku z tym istnieją typowe obszary problemów między usługą SSR a żądaniem/odpowiedzią HTTP. Ogólne zagadnienia dotyczące zabezpieczeń i konkretne zagrożenia muszą zostać pomyślnie rozwiązane. Platforma udostępnia wbudowane mechanizmy zarządzania niektórymi z tych zagrożeń, ale inne zagrożenia są specyficzne dla kodu aplikacji i muszą być obsługiwane przez aplikację. Te zagrożenia można podzielić na kategorie w następujący sposób:

  • Uwierzytelnianie i autoryzacja: aplikacja musi mieć pewność, że użytkownik jest uwierzytelniony i autoryzowany do uzyskiwania dostępu do aplikacji oraz udostępnianych przez nią zasobów. Platforma udostępnia wbudowane mechanizmy uwierzytelniania i autoryzacji, ale aplikacja musi upewnić się, że mechanizmy są prawidłowo skonfigurowane i używane. Wbudowane mechanizmy uwierzytelniania i autoryzacji są omówione w Blazor węźle zabezpieczeń serwera dokumentacji oraz w dokumentacji zabezpieczeń iIdentitywęzła dokumentacji ASP.NET Core, więc nie zostaną omówione w tym miejscu.

  • Walidacja i oczyszczanie danych wejściowych: wszystkie dane wejściowe pochodzące z klienta muszą zostać zweryfikowane i oczyszczone przed użyciem. W przeciwnym razie aplikacja może być narażona na ataki, takie jak wstrzyknięcie kodu SQL, skrypty między witrynami, fałszerzowanie żądań między witrynami, otwarcie przekierowania i inne formy ataków. Dane wejściowe mogą pochodzić z dowolnego miejsca w żądaniu.

  • Zarządzanie sesjami: Prawidłowe zarządzanie sesjami użytkowników ma kluczowe znaczenie dla zapewnienia, że aplikacja nie jest narażona na ataki, takie jak naprawa sesji, przejęcie sesji i inne ataki. Informacje przechowywane w sesji muszą być prawidłowo chronione i szyfrowane, a kod aplikacji musi uniemożliwić złośliwemu użytkownikowi odgadnięcie sesji lub manipulowanie nimi.

  • Obsługa błędów i rejestrowanie: aplikacja musi upewnić się, że błędy są prawidłowo obsługiwane i rejestrowane. W przeciwnym razie aplikacja może być narażona na ataki, takie jak ujawnienie informacji. Może się tak zdarzyć, gdy aplikacja zwraca poufne informacje w odpowiedzi lub gdy aplikacja zwraca szczegółowe komunikaty o błędach z danymi, których można użyć do ataku na aplikację.

  • Ochrona danych: Dane poufne muszą być prawidłowo chronione, co obejmuje logikę aplikacji podczas uruchamiania w zestawie WebAssembly, ponieważ można je łatwo odtworzyć.

  • Odmowa usługi: aplikacja musi mieć pewność, że nie jest narażona na ataki, takie jak odmowa usługi. Dzieje się tak na przykład wtedy, gdy aplikacja nie jest prawidłowo chroniona przed atakami siłowymi lub gdy akcja może spowodować użycie zbyt wielu zasobów przez aplikację.

Walidacja i oczyszczanie danych wejściowych

Wszystkie dane wejściowe pochodzące z klienta muszą być uznawane za niezaufane, chyba że jego informacje zostały wygenerowane i chronione na serwerze, takie jak token CSRF, uwierzytelnianie cookie, identyfikator sesji lub dowolny inny ładunek chroniony za pomocą uwierzytelnionego szyfrowania.

Dane wejściowe są zwykle dostępne dla aplikacji za pośrednictwem procesu powiązania, na przykład za pośrednictwem atrybutu lub atrybutu[SupplyParameterFromQuery].[SupplyParameterFromForm] Przed przetworzeniem tych danych wejściowych aplikacja musi upewnić się, że dane są prawidłowe. Na przykład aplikacja musi potwierdzić, że podczas mapowania danych formularza na właściwość składnika nie wystąpiły żadne błędy powiązania. W przeciwnym razie aplikacja może przetwarzać nieprawidłowe dane.

Jeśli dane wejściowe są używane do wykonania przekierowania, aplikacja musi upewnić się, że dane wejściowe są prawidłowe i że nie wskazuje domeny uznanej za nieprawidłową lub nieprawidłowej ścieżki podrzędnej w ścieżce podstawowej aplikacji. W przeciwnym razie aplikacja może zostać uwidoczniona w celu otwarcia ataków przekierowania, w których osoba atakująca może utworzyć link, który przekierowuje użytkownika do złośliwej witryny.

Jeśli dane wejściowe są używane do wykonywania zapytania bazy danych, aplikacja musi potwierdzić, że dane wejściowe są prawidłowe i że nie uwidaczniają aplikacji w atakach polegających na wstrzyknięciu kodu SQL. W przeciwnym razie osoba atakująca może utworzyć złośliwe zapytanie, które może służyć do wyodrębniania informacji z bazy danych lub modyfikowania bazy danych.

Dane, które mogły pochodzić z danych wejściowych użytkownika, również muszą być oczyszczone, zanim zostaną uwzględnione w odpowiedzi. Na przykład dane wejściowe mogą zawierać kod HTML lub JavaScript, który może służyć do wykonywania ataków skryptowych między witrynami, które mogą służyć do wyodrębniania informacji od użytkownika lub wykonywania akcji w imieniu użytkownika.

Platforma udostępnia następujące mechanizmy ułatwiające walidację danych wejściowych i oczyszczanie:

  • Wszystkie powiązane dane formularza są weryfikowane pod kątem podstawowej poprawności. Jeśli nie można przeanalizować danych wejściowych, proces powiązania zgłasza błąd, który aplikacja może odnaleźć przed podjęciem dowolnej akcji z danymi. Wbudowany EditForm składnik uwzględnia to przed wywołaniem wywołania zwrotnego OnValidSubmit formularza. Blazor unika wykonywania wywołania zwrotnego w przypadku wystąpienia co najmniej jednego błędu powiązania.
  • Platforma używa tokenu chroniącego przed fałszerzami w celu ochrony przed atakami fałszerzowania żądań między witrynami. Aby uzyskać więcej informacji, zobacz omówienie uwierzytelniania i autoryzacji ASP.NET Core Blazor oraz formularzy ASP.NET CoreBlazor.

Wszystkie dane wejściowe i uprawnienia muszą być weryfikowane na serwerze w czasie wykonywania danej akcji, aby upewnić się, że dane są prawidłowe i dokładne w tym czasie oraz czy użytkownik może wykonać akcję. Takie podejście jest zgodne ze wskazówkami dotyczącymi zabezpieczeń udostępnianymi na potrzeby interaktywnego renderowania po stronie serwera.

Zarządzanie sesją

Zarządzanie sesjami jest obsługiwane przez platformę. Platforma używa sesji cookie do identyfikowania sesji użytkownika. Sesja cookie jest chroniona przy użyciu interfejsów API ASP.NET Core Data Protection. Sesja cookie nie jest dostępna dla kodu JavaScript uruchomionego w przeglądarce i nie można jej łatwo odgadnąć ani manipulować nim przez użytkownika.

W odniesieniu do innych danych sesji, takich jak dane przechowywane w usługach, dane sesji powinny być przechowywane w ramach usług o określonym zakresie, ponieważ usługi o określonym zakresie są unikatowe dla danej sesji użytkownika, w przeciwieństwie do usług jednotonowych, które są współużytkowane przez wszystkie sesje użytkownika w danym wystąpieniu procesu.

Jeśli chodzi o usługę SSR, w większości przypadków nie ma wiele różnic między usługami o określonym zakresie i przejściowymi, ponieważ okres istnienia usługi jest ograniczony do pojedynczego żądania. Istnieje różnica w dwóch scenariuszach:

  • Jeśli usługa jest wstrzykiwana w więcej niż jednej lokalizacji lub w innym czasie podczas żądania.
  • Jeśli usługa może być używana w kontekście serwera interaktywnego, gdzie przetrwa wiele renderów i jego podstawy, że usługa jest ograniczona do sesji użytkownika.

Obsługa błędów i rejestrowanie

Platforma zapewnia wbudowane rejestrowanie aplikacji na poziomie platformy. Platforma rejestruje ważne zdarzenia, takie jak w przypadku niepowodzenia weryfikacji tokenu ochrony przed fałszerzją formularza, gdy składnik główny rozpoczyna renderowanie, a po wysłaniu akcji. Aplikacja jest odpowiedzialna za rejestrowanie wszelkich innych zdarzeń, które mogą być ważne do zarejestrowania.

Platforma zapewnia wbudowaną obsługę błędów dla aplikacji na poziomie platformy. Platforma obsługuje błędy występujące podczas renderowania składnika i używa mechanizmu granic błędów do wyświetlania przyjaznego komunikatu o błędzie lub umożliwia bąbelek błędu do oprogramowania pośredniczącego obsługującego wyjątki skonfigurowanego do renderowania strony błędu.

Błędy występujące podczas renderowania strumieniowego po rozpoczęciu wysyłania odpowiedzi do klienta są wyświetlane w końcowej odpowiedzi jako ogólny komunikat o błędzie. Szczegółowe informacje o przyczynie błędu są uwzględniane tylko podczas programowania.

Ochrona danych

Platforma oferuje mechanizmy ochrony poufnych informacji dla danej sesji użytkownika i zapewnia, że wbudowane składniki korzystają z tych mechanizmów w celu ochrony poufnych informacji, takich jak ochrona tożsamości użytkowników podczas korzystania z cookie uwierzytelniania. Poza scenariuszami obsługiwanymi przez platformę kod dewelopera jest odpowiedzialny za ochronę innych informacji specyficznych dla aplikacji. Najczęstszym sposobem wykonania tej czynności jest użycie interfejsów API ASP.NET Core Data Protection lub dowolnego innego rodzaju szyfrowania. Ogólnie rzecz biorąc, aplikacja jest odpowiedzialna za:

  • Upewnij się, że użytkownik nie może sprawdzić ani zmodyfikować prywatnych informacji innego użytkownika.
  • Upewnij się, że użytkownik nie może modyfikować danych użytkownika innego użytkownika, na przykład identyfikatora wewnętrznego.

W odniesieniu do ochrony danych musisz jasno zrozumieć, gdzie kod jest wykonywany. W przypadku renderowania statycznego po stronie serwera (statycznego SSR) i interaktywnego renderowania po stronie serwera (interakcyjnego odzyskiwania po stronie serwera) kod jest przechowywany na serwerze i nigdy nie dociera do klienta. W trybie renderowania Interactive WebAssembly kod aplikacji zawsze dociera do klienta, co oznacza, że wszystkie poufne informacje przechowywane w kodzie aplikacji są dostępne dla każdej osoby mającej dostęp do aplikacji. Zaciemnianie i inna podobna technika do "ochrony" kodu nie jest skuteczna. Po dotarciu kodu do klienta można go odtworzyć w celu wyodrębnienia poufnych informacji.

Denial of service (odmowa usługi)

Na poziomie serwera platforma zapewnia limity parametrów żądania/odpowiedzi, takie jak maksymalny rozmiar żądania i rozmiar nagłówka. W odniesieniu do kodu Blazoraplikacji system mapowania formularzy definiuje limity podobne do tych zdefiniowanych przez system powiązań modelu MVC:

  • Ogranicz maksymalną liczbę błędów.
  • Limit maksymalnej głębokości rekursji dla bindera.
  • Ogranicz maksymalną liczbę elementów powiązanych w kolekcji.

Ponadto istnieją limity zdefiniowane dla formularza, takie jak maksymalny rozmiar klucza formularza i rozmiar wartości oraz maksymalna liczba wpisów.

Ogólnie rzecz biorąc, aplikacja musi ocenić, czy istnieje prawdopodobieństwo, że żądanie wyzwoli asymetryczną ilość pracy przez serwer. Przykłady tego obejmują, gdy użytkownik wysyła żądanie sparametryzowane przez N, a serwer wykonuje operację w odpowiedzi, która jest N razy kosztowna, gdzie N jest parametrem, który użytkownik kontroluje i może rosnąć w nieskończoność. Zwykle aplikacja musi narzucić limit maksymalnej N, którą chce przetworzyć, lub upewnić się, że każda operacja jest mniejsza, równa lub droższa niż żądanie przez stały czynnik.

Ten aspekt ma więcej wspólnego z różnicą wzrostu między pracą wykonywaną przez klienta a pracą wykonywaną przez serwer niż w przypadku porównania 1→N. Na przykład klient może przesłać element roboczy (wstawianie elementów do listy), który zajmuje N jednostek czasu do wykonania, ale serwer potrzebuje N^2^ do przetworzenia (ponieważ może to robić coś bardzo naiwnego). Jest to różnica między N i N^2^2^, która ma znaczenie.

W związku z tym istnieje limit ilości pracy, którą serwer musi wykonać, co jest specyficzne dla aplikacji. Ten aspekt dotyczy obciążeń po stronie serwera, ponieważ zasoby znajdują się na serwerze, ale nie musi dotyczyć obciążeń zestawu WebAssembly na kliencie w większości przypadków.

Innym ważnym aspektem jest to, że nie jest to tylko zarezerwowane do czasu procesora CPU. Dotyczy również wszelkich zasobów, takich jak pamięć, sieć i miejsce na dysku.

W przypadku obciążeń zestawu WebAssembly zwykle występuje niewielkie obawy dotyczące ilości pracy wykonywanej przez klienta, ponieważ klient jest zwykle ograniczony zasobami dostępnymi na kliencie. Istnieją jednak pewne scenariusze, w których może to mieć wpływ na klienta, jeśli na przykład aplikacja wyświetla dane od innych użytkowników, a jeden użytkownik może dodawać dane do systemu, co wymusza na klientach wyświetlających dane w celu wykonania ilości pracy, która nie jest proporcjonalna do ilości danych dodanych przez użytkownika.

  • Upewnij się, że użytkownik jest uwierzytelniony i autoryzowany do uzyskiwania dostępu do aplikacji oraz udostępnianych zasobów.
  • Przed jego użyciem zweryfikuj i odczyści wszystkie dane wejściowe pochodzące z klienta.
  • Prawidłowo zarządzaj sesjami użytkowników, aby upewnić się, że stan nie jest błędnie współużytkowany przez użytkowników.
  • Poprawnie obsłuż błędy i rejestruj je, aby uniknąć uwidaczniania poufnych informacji.
  • Rejestruj ważne zdarzenia w aplikacji, aby zidentyfikować potencjalne problemy i akcje inspekcji wykonywane przez użytkowników.
  • Ochrona poufnych informacji przy użyciu interfejsów API ASP.NET Core Data Protection lub jednego z dostępnych składników (Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage, PersistentComponentState).
  • Upewnij się, że aplikacja rozumie zasoby, które mogą być używane przez określone żądanie i ma limity, aby uniknąć ataków typu "odmowa usługi".