w tej sekcji opiszemy kilka ogólnych zasad zapobiegania lukom w zabezpieczeniach w skryptach między witrynami oraz sposoby korzystania z różnych popularnych technologii do ochrony przed atakami XSS.

zapobieganie skryptom krzyżowym można ogólnie osiągnąć za pomocą dwóch warstw obrony:

  • Kodowanie danych na wyjściu
  • Walidacja danych wejściowych po przybyciu

możesz użyć skanera Burp do skanowania witryn internetowych pod kątem licznych luk w zabezpieczeniach, w tym XSS. Najnowocześniejsza logika skanowania firmy Burp replikuje działania wykwalifikowanego napastnika i jest w stanie osiągnąć odpowiednio wysokie pokrycie luk w zabezpieczeniach XSS. Możesz użyć skanera Burp, aby uzyskać pewność, że Twoja obrona przed atakami XSS działa skutecznie.

Kodowanie danych wyjściowych

kodowanie powinno być zastosowane bezpośrednio przed zapisaniem danych sterowanych przez użytkownika na stronie, ponieważ kontekst, w którym piszesz, określa, jakiego rodzaju kodowania potrzebujesz użyć. Na przykład wartości wewnątrz ciągu znaków JavaScript wymagają innego rodzaju ucieczki niż te w kontekście HTML.

w kontekście HTML należy przekonwertować wartości spoza białej listy na encje HTML:

  • < konwertuje na: &lt;
  • > konwertuje na: &gt;

w kontekście łańcuchów JavaScript wartości nie alfanumeryczne powinny być unikodowane:

  • < konwertuje na: \u003c
  • > konwertuje na: \u003e

czasami trzeba zastosować wiele warstw kodowania, w odpowiedniej kolejności. Na przykład, aby bezpiecznie osadzić dane wejściowe użytkownika wewnątrz procedury obsługi zdarzenia, musisz poradzić sobie zarówno z kontekstem JavaScript, jak i kontekstem HTML. Musisz więc najpierw Unicode-escape the input, a następnie HTML-encode it:

<a href="#" onclick="x='This string needs two layers of escaping'">test</a>

zweryfikuj wejście po przybyciu

kodowanie jest prawdopodobnie najważniejszą linią obrony XSS, ale nie jest wystarczające, aby zapobiec lukom XSS w każdym kontekście. Powinieneś również zweryfikować dane wejściowe tak ściśle, jak to możliwe w momencie, gdy są one po raz pierwszy odbierane od użytkownika.

przykłady walidacji danych wejściowych obejmują:

  • jeśli użytkownik poda adres URL, który zostanie zwrócony w odpowiedziach, potwierdza, że zaczyna się od bezpiecznego protokołu, takiego jak HTTP i HTTPS. W przeciwnym razie ktoś może wykorzystać Twoją witrynę za pomocą szkodliwego protokołu, takiego jak javascript lub data.
  • jeśli użytkownik podaje wartość, której oczekuje, że będzie numeryczna, sprawdza, czy wartość rzeczywiście zawiera liczbę całkowitą.
  • sprawdzanie, czy wejście zawiera tylko oczekiwany zestaw znaków.

walidacja danych wejściowych powinna najlepiej działać, blokując nieprawidłowe dane wejściowe. Alternatywne podejście, polegające na próbie wyczyszczenia nieprawidłowych danych wejściowych, aby były poprawne, jest bardziej podatne na błędy i należy ich unikać tam, gdzie to możliwe.

Whitelisting vs blacklisting

walidacja danych wejściowych powinna zazwyczaj wykorzystywać białe listy, a nie czarne listy. Na przykład, zamiast próbować zrobić listę wszystkich szkodliwych protokołów (javascript, data, itd.), po prostu zrób listę bezpiecznych protokołów (HTTP, HTTPS) i nie zezwalaj na nic, czego nie ma na liście. Zapewni to, że Twoja obrona nie pęknie, gdy pojawią się nowe szkodliwe protokoły i sprawi, że będzie mniej podatna na ataki mające na celu zaciemnienie nieprawidłowych wartości, aby uniknąć czarnej listy.

zezwalanie na „Bezpieczny” HTML

Zezwalanie użytkownikom na zamieszczanie znaczników HTML powinno być unikane wszędzie tam, gdzie to możliwe, ale czasami jest to wymóg biznesowy. Na przykład witryna blogowa może zezwalać na publikowanie komentarzy zawierających ograniczone znaczniki HTML.

klasycznym podejściem jest próba odfiltrowania potencjalnie szkodliwych tagów i JavaScript. Możesz spróbować zaimplementować to używając białej listy bezpiecznych tagów i atrybutów, ale ze względu na rozbieżności w silnikach parsowania przeglądarki i dziwactwach, takich jak mutation XSS, takie podejście jest niezwykle trudne do bezpiecznego wdrożenia.

najmniej złą opcją jest użycie biblioteki JavaScript, która wykonuje filtrowanie i kodowanie w przeglądarce użytkownika, takiej jak DOMPurify. Inne biblioteki pozwalają użytkownikom na dostarczanie treści w formacie markdown i konwertowanie markdown do HTML. Niestety, wszystkie te biblioteki od czasu do czasu mają luki w zabezpieczeniach XSS, więc nie jest to idealne rozwiązanie. Jeśli używasz jednego z nich, powinieneś uważnie monitorować aktualizacje zabezpieczeń.

Uwaga

oprócz JavaScript, inne treści, takie jak CSS, a nawet zwykły HTML, mogą być szkodliwe w niektórych sytuacjach.

ataki za pomocą złośliwego CSS

jak zapobiec XSS za pomocą silnika szablonów

wiele nowoczesnych stron internetowych używa silników szablonów po stronie serwera, takich jak Twig i Freemarker do osadzania dynamicznej zawartości w HTML. Te typowo definiują swój własny system ucieczki. Na przykład w Twig możesz użyć filtru e() z argumentem definiującym kontekst:

{{ user.firstname | e('html') }}

niektóre inne silniki szablonów, takie jak Jinja i React, domyślnie uciekają przed dynamiczną zawartością, co skutecznie zapobiega większości wystąpień XSS.

zalecamy uważne zapoznanie się z funkcjami objaśniającymi, gdy oceniasz, czy użyć danego silnika szablonów, czy struktury.

Uwaga

jeśli bezpośrednio połączysz dane wejściowe użytkownika w ciągi szablonów, będziesz podatny na wstrzyknięcie szablonu po stronie serwera, co jest często poważniejsze niż XSS.

jak zapobiec XSS w PHP

w PHP jest wbudowana funkcja kodowania encji o nazwie htmlentities. Należy wywołać tę funkcję, aby uniknąć wejścia w kontekście HTML. Funkcja powinna być wywołana z trzema argumentami:

  • Twój łańcuch wejściowy.
  • ENT_QUOTES, który jest flagą, która określa wszystkie cudzysłowy powinny być zakodowane.
  • zestaw znaków, który w większości przypadków powinien być UTF-8.

na przykład:

<?php echo htmlentities($input, ENT_QUOTES, 'UTF-8');?>

gdy w JavaScript string context, musisz Unicode-escape input jak już opisano. Niestety, PHP nie udostępnia API dla Unicode-escape a string. Oto trochę kodu do zrobienia tego w PHP:

<?php

function jsEscape($str) {
$output = '';
$str = str_split($str);
for($i=0;$i<count($str);$i++) {
$chrNum = ord($str);
$chr = $str;
if($chrNum === 226) {
if(isset($str) && ord($str) === 128) {
if(isset($str) && ord($str) === 168) {
$output .= '\u2028';
$i += 2;
continue;
}
if(isset($str) && ord($str) === 169) {
$output .= '\u2029';
$i += 2;
continue;
}
}
}
switch($chr) {
case "'":
case '"':
case "\n";
case "\r";
case "&";
case "\";
case "<":
case ">":
$output .= sprintf("\u%04x", $chrNum);
break;
default:
$output .= $str;
break;
}
}
return $output;
}
?>

oto jak używać funkcji jsEscape w PHP:

<script>x = '<?php echo jsEscape($_GET)?>';</script>

Alternatywnie możesz użyć silnika szablonów.

jak zapobiec XSS po stronie klienta w JavaScript

aby uniknąć wprowadzania danych przez użytkownika w kontekście HTML w JavaScript, potrzebujesz własnego kodera HTML, ponieważ JavaScript nie zapewnia API do kodowania HTML. Oto przykładowy kod JavaScript, który konwertuje ciąg znaków na encje HTML:

function htmlEncode(str){
return String(str).replace(//gi, function(c){
return '&#'+c.charCodeAt(0)+';';
});
}

następnie można użyć tej funkcji w następujący sposób:

<script>document.body.innerHTML = htmlEncode(untrustedValue)</script>

jeśli twoje wejście znajduje się wewnątrz ciągu JavaScript, potrzebujesz kodera, który wykonuje Escape Unicode. Oto przykładowy koder Unicode:

function jsEscape(str){
return String(str).replace(//gi, function(c){
return '\u'+('0000'+c.charCodeAt(0).toString(16)).slice(-4);
});

}

następnie można użyć tej funkcji w następujący sposób:

<script>document.write('<script>x="'+jsEscape(untrustedValue)+'";<\/script>')</script>

jak zapobiec XSS w jQuery

najczęstszą formą XSS w jQuery jest przekazanie danych wejściowych użytkownika do selektora jQuery. Programiści często używali location.hash i przekazywali ją do selektora, co powodowało, że XSS, jak jQuery renderował HTML. jQuery rozpoznał ten problem i poprawił logikę selektora, aby sprawdzić, czy wejście zaczyna się od skrótu. Teraz jQuery będzie renderować HTML tylko wtedy, gdy pierwszym znakiem jest <. Jeśli przekazujesz niezaufane dane do selektora jQuery, upewnij się, że poprawnie opuściłeś wartość za pomocą funkcji jsEscape powyżej.

Łagodzenie XSS przy użyciu zasad bezpieczeństwa treści (CSP)

zasad bezpieczeństwa treści (CSP) jest ostatnią linią obrony przed skryptami między witrynami. Jeśli zapobieganie XSS nie powiedzie się, możesz użyć CSP, aby złagodzić XSS, ograniczając możliwości atakującego.

CSP pozwala kontrolować różne rzeczy, takie jak to, czy zewnętrzne skrypty mogą być ładowane i czy skrypty wbudowane będą wykonywane. Aby wdrożyć CSP, musisz dołączyć nagłówek odpowiedzi HTTP o nazwie Content-Security-Policy z wartością zawierającą twoje zasady.

przykładowy CSP wygląda następująco:

default-src 'self'; script-src 'self'; object-src 'none'; frame-src 'none'; base-uri 'none';

ta zasada określa, że zasoby, takie jak obrazy i skrypty, mogą być ładowane tylko z tego samego źródła co Strona główna. Tak więc nawet jeśli atakujący może pomyślnie wstrzyknąć ładunek XSS, może załadować zasoby tylko z bieżącego źródła. To znacznie zmniejsza ryzyko, że atakujący może wykorzystać lukę XSS.

jeśli potrzebujesz ładowania zasobów zewnętrznych, upewnij się, że zezwalasz tylko na skrypty, które nie pomagają atakującemu w wykorzystywaniu witryny. Na przykład, jeśli dodasz określone domeny do białej listy, atakujący może załadować dowolny skrypt z tych domen. Tam, gdzie to możliwe, spróbuj hostować zasoby na własnej domenie.

jeśli nie jest to możliwe, możesz użyć zasady opartej na hash lub nonce, aby zezwolić na Skrypty w różnych domenach. Nonce to losowy ciąg znaków, który jest dodawany jako atrybut skryptu lub zasobu, który zostanie wykonany tylko wtedy, gdy losowy ciąg pasuje do generowanego przez serwer. Atakujący nie jest w stanie odgadnąć losowego ciągu znaków i dlatego nie może wywołać skryptu lub zasobu z poprawnym nonce, a więc zasób nie zostanie wykonany.

Łagodzenie ataków XSS przy użyciu CSP

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.