Content Security Policy to lista tego, co wolno wczytać stronie: skryptów, stylów, czcionek, ramek, obrazów. Nagłówek jest jedną z najskuteczniejszych barier przeciwko wstrzykniętemu kodowi — i jednocześnie jedną z najrzadziej wdrażanych, bo napisanie go ręcznie oznacza przejście po wszystkich podstronach z konsolą przeglądarki i wypisanie z niej każdego adresu.
Problem nie polega na tym, że to żmudne. Polega na tym, że jest to niesprawdzalne. Lista zasobów strony nie leży w kodzie motywu — leży w przeglądarce, po wykonaniu wszystkich wtyczek, osadzonych filmów, analityki, czcionek i ramek płatności. Jedno przeoczenie i polityka blokuje coś, czego nikt nie testował. Zwykle wychodzi to w miejscu, w które nikt nie zagląda: w koszyku albo w kroku płatności.
Polityka napisana ręcznie opisuje stronę, którą autor pamięta. Polityka zbudowana z raportów opisuje stronę, która działa.
Trzy fazy zamiast jednego skoku
Podejście, które stosujemy, odwraca kolejność. Zamiast pisać politykę i sprawdzać, co się zepsuło, najpierw zbieramy materiał.
- Nauka. Wychodzi nagłówek w trybie report-only, na tyle restrykcyjny, że przeglądarki raportują każdy wczytany zasób. Nic nie jest blokowane — tak stanowi specyfikacja tego nagłówka, więc faza uczenia nie może zepsuć strony.
-
Generowanie. Z zebranego rejestru powstaje polityka. Każda
dyrektywa zachowuje
'self', adresy zewnętrzne są wypisane wprost, a całość jest do odczytania i poprawienia przed włączeniem. - Egzekwowanie. Polityka idzie na produkcję. Raportowanie może zostać włączone, więc to, co zepsuje przyszła zmiana, nadal się pokaże.
Raporty są agregowane po dyrektywie i adresie źródłowym. To detal, ale przesądzający o tym, czy narzędzie da się włączyć na żywym ruchu: bez agregacji tabela raportów rośnie liniowo z liczbą odsłon i po dobie na średnim serwisie robi się z niej największa tabela w bazie.
Uczenie musi dać się zablokować
Faza nauki jest kosztowna. Na ruchliwym serwisie to tysiące raportów na godzinę, a każdy z nich to zapis do bazy. Włączona przez pomyłkę i zostawiona na tydzień potrafi zrobić więcej szkody niż brak polityki.
Dlatego uczenia nie wyłącza się checkboxem w panelu, tylko stałą w konfiguracji. Wpisana raz sprawia, że trybu nie da się włączyć w żaden sposób — ani kliknięciem, ani przypadkowym poleceniem zmieniającym opcję, ani bazą przywiezioną ze środowiska testowego, gdzie uczenie było potrzebne i zostało włączone.
To ta sama zasada, którą stosujemy przy każdym przełączniku o wysokim koszcie: jeżeli zła wartość jest droga, przełącznik ma mieszkać poza bazą danych.
Czego raporty nie zbierają
Raport naruszenia niesie adres podstrony, na której doszło do zdarzenia. Adresy koszyka, płatności i konta klienta zawierają klucze zamówień i tokeny resetu hasła — a do listy dozwolonych źródeł nie wnoszą nic, czego nie ma na pozostałych podstronach.
Dlatego zapytania z adresów są obcinane przed zapisem, a raporty z koszyka, płatności i konta odrzucane w całości. To nie jest ustawienie prywatności do włączenia, tylko domyślne zachowanie — dane, których nie zbieramy, nie wyciekną z kopii zapasowej.
Czego to świadomie nie robi
Panel administracyjny nie jest domyślnie objęty polityką. Kokpit WordPressa jest pełen kodu osadzonego bezpośrednio w stronie, więc polityka na tyle ostra, żeby cokolwiek tam dawała, rozłożyłaby edytor. Przełącznik istnieje, ale świadoma decyzja brzmi: chronimy warstwę publiczną, bo to ona przyjmuje ruch z zewnątrz.
Jeżeli w wygenerowanej polityce pojawia się 'unsafe-inline', to znaczy,
że serwis ma kod osadzony w stronie — polityka opisuje stan faktyczny. Zaznaczamy to
wprost w panelu, bo ta jedna wartość znacząco osłabia ochronę. Naprawą jest
przeniesienie kodu do plików, a nie poprawienie polityki tak, żeby przestała o tym
mówić.
