Bezpieczne przechowywanie danych użytkowników w nowoczesnych aplikacjach internetowych

David Dworken
David Dworken

Wiele aplikacji internetowych musi wyświetlać zawartość kontrolowaną przez użytkownika. Może to być tak proste, jak wyświetlanie obrazów przesłanych przez użytkownika (np. zdjęć profilowych), lub tak skomplikowane, jak renderowanie kontrolowanego przez użytkownika kodu HTML (na przykład samouczek tworzenia stron internetowych). Zawsze było to trudne do wykonania w bezpieczny sposób, dlatego pracowaliśmy nad znalezieniem łatwych, ale bezpiecznych rozwiązań, które można zastosować do większości typów aplikacji internetowych.

Klasyczne rozwiązania do izolowania niezaufanych treści

Klasycznym rozwiązaniem do bezpiecznego wyświetlania treści kontrolowanych przez użytkownika jest użycie domen piaskownicy. Podstawowym założeniem jest to, że jeśli domena główna Twojej aplikacji to example.com, możesz wyświetlać wszystkie niezaufane treści w exampleusercontent.com. Te 2 domeny znajdują się w witrynach, więc złośliwe treści w witrynie exampleusercontent.com nie mogą mieć wpływu na witrynę example.com.
Ta metoda pozwala bezpiecznie wyświetlać wszelkiego rodzaju niezaufane treści, w tym obrazy, pliki do pobrania i kod HTML. Chociaż może się wydawać, że korzystanie z tej funkcji w przypadku obrazów lub plików do pobrania nie jest konieczne, pozwala to uniknąć ryzyka związanego z wycieraniem treści, zwłaszcza w starszych przeglądarkach.
Domeny piaskownicy są powszechnie używane w branży i sprawdzają się od dłuższego czasu. Mają jednak dwie poważne wady:

  • Aplikacje często muszą ograniczać dostęp do treści jednemu użytkownikowi, co wymaga implementacji uwierzytelniania i autoryzacji. Ponieważ domeny piaskownicy celowo nie udostępniają plików cookie głównej domenie aplikacji, bardzo trudno jest zrobić to bezpiecznie. Aby obsługiwać uwierzytelnianie, witryny muszą korzystać z odpowiednich adresów URL lub skonfigurować osobne pliki cookie uwierzytelniania dla domeny piaskownicy. Ta druga metoda jest szczególnie problematyczna we współczesnym internecie, gdzie wiele przeglądarek domyślnie ogranicza pliki cookie pochodzące z różnych witryn.
  • Treści użytkownika są oddzielone od głównej witryny, ale nie odizolowane od treści innych użytkowników. Spowoduje to ryzyko zaatakowania przez złośliwe treści użytkowników innych danych w domenie piaskownicy (na przykład przez odczyt danych z tej samej domeny).

Warto również zauważyć, że domeny piaskownicy pomagają ograniczyć ryzyko wyłudzenia informacji, ponieważ zasoby są wyraźnie podzielone na osobne domeny.

Nowoczesne rozwiązania do wyświetlania treści użytkowników

Z biegiem czasu sieć ewoluowała i opracowaliśmy prostsze i bezpieczniejsze sposoby wyświetlania niezaufanych treści. Można tutaj zastosować wiele różnych metod. Przedstawimy więc 2 z nich, które są obecnie powszechnie używane w Google.

Metoda 1. Wyświetlanie nieaktywnych treści użytkowników

Jeśli witryna ma wyświetlać tylko nieaktywne treści dla użytkowników (tj. treści w języku innym niż HTML lub JavaScript, np. obrazy i pliki do pobrania), można to teraz bezpiecznie zrobić bez izolowanej domeny piaskownicy. Należy wykonać 2 kluczowe czynności:

  • Zawsze ustawiaj w nagłówku Content-Type dobrze znany typ MIME, który jest obsługiwany przez wszystkie przeglądarki i gwarantuje, że nie zawiera aktywnej treści (w razie wątpliwości zalecamy użycie application/octet-stream).
  • Ponadto zawsze ustawiaj poniższe nagłówki odpowiedzi, aby zapewnić pełne izolowanie odpowiedzi przez przeglądarkę.
Nagłówek odpowiedzi Purpose

X-Content-Type-Options: nosniff

Zapobiega wychwytaniu treści

Content-Disposition: attachment; filename="download"

Wyzwala pobieranie zamiast renderowania

Content-Security-Policy: sandbox

umieszcza treści w piaskownicy tak, jakby były wyświetlane w osobnej domenie;

Content-Security-Policy: default-src ‘none'

Wyłącza wykonywanie JavaScriptu (i uwzględnianie wszystkich zasobów podrzędnych)

Cross-Origin-Resource-Policy: same-site

Uniemożliwia uwzględnianie strony w innych witrynach

Ta kombinacja nagłówków gwarantuje, że odpowiedź będzie mogła zostać wczytana tylko jako zasób podrzędny przez aplikację lub pobrana przez użytkownika jako plik. Poza tym nagłówki zapewniają wiele warstw ochrony przed błędami w przeglądarce za pomocą nagłówka piaskownicy CSP i ograniczenia default-src. Ogólnie rzecz biorąc, opisana powyżej konfiguracja zapewnia wysoki stopień pewności, że odpowiedzi podawane w ten sposób nie mogą prowadzić do luk w zabezpieczeniach.

Obrona w głąb

Powyższe rozwiązanie zwykle zapewnia wystarczającą ochronę przed atakami XSS, ale istnieje wiele dodatkowych zabezpieczeń, które można zastosować, aby uzyskać dodatkowe warstwy zabezpieczeń:

  • Ustaw nagłówek X-Content-Security-Policy: sandbox, aby zapewnić zgodność z IE11.
  • Ustaw nagłówek Content-Security-Policy: frame-ancestors 'none', aby zablokować umieszczanie punktu końcowego.
  • Treści użytkowników z piaskownicy w odizolowanej subdomenie:
    • wyświetlanie treści użytkowników w odizolowanej subdomenie (np. Google używa domen takich jak product.usercontent.google.com),
    • Skonfiguruj ustawienia Cross-Origin-Opener-Policy: same-origin i Cross-Origin-Embedder-Policy: require-corp, aby włączyć izolację zasobów z innych domen.

Metoda 2. Udostępnianie treści aktywnych użytkowników

Można też bezpiecznie wyświetlać aktywną zawartość (np. obrazy HTML lub SVG), bez wad tego rozwiązania.
Najprostszym sposobem jest skorzystanie z nagłówka Content-Security-Policy: sandbox, aby poinformować przeglądarkę, że ma wyizolować odpowiedź. Chociaż nie wszystkie przeglądarki obecnie wdrażają izolację procesów w przypadku dokumentów w trybie piaskownicy, ciągłe ulepszanie modeli procesów przeglądarki może poprawić oddzielenie treści w trybie piaskownicy od aplikacji umieszczanych. Jeśli ataki SpectreJS i ataki naruszenia zabezpieczeń mechanizmu renderowania wykraczają poza Twój model zagrożeń, raczej użycie piaskownicy CSP będzie wystarczające.
Firma Google opracowała rozwiązanie, które pozwala w pełni izolować niezaufane treści aktywne przez zmodernizowanie koncepcji domen piaskownicy. Podstawową koncepcją jest:

  • Utwórz nową domenę piaskownicy, która zostanie dodana do listy domen publicznych. Na przykład dodając atrybut exampleusercontent.com do PSL, możesz zapewnić, że elementy foo.exampleusercontent.com i bar.exampleusercontent.com będą od siebie całkowicie odizolowane od siebie.
  • Wszystkie adresy URL pasujące do wartości *.exampleusercontent.com/shim są kierowane do statycznego pliku podkładki. Ten plik podkładki zawiera krótki fragment kodu HTML i JavaScript, który nasłuchuje modułu obsługi zdarzeń message i renderuje odbierane treści.
  • Aby z niego skorzystać, usługa tworzy element iframe lub wyskakujące okienko w interfejsie $RANDOM_VALUE.exampleusercontent.com/shim i używa postMessage, aby wysyłać do podkładki do renderowania niezaufane treści.
  • Wyrenderowana treść jest przekształcana w obiekt blob i renderowana wewnątrz elementu iframe w trybie piaskownicy.

W porównaniu z klasyczną wersją piaskownicy zapewnia to pełną izolację wszystkich treści na unikalnej stronie. A ponieważ główna umowa dotycząca aplikacji pobiera dane do renderowania, nie trzeba już korzystać z adresów URL funkcji.

Podsumowanie

Te 2 rozwiązania umożliwiają przejście z klasycznych domen piaskownicy, takich jak googleusercontent.com, na bezpieczniejsze rozwiązania, które są zgodne z blokowaniem plików cookie innych firm. Dokonaliśmy już w Google migracji wielu usług, aby korzystały z tych rozwiązań, a w przyszłym roku zaplanowaliśmy kolejne migracje.