Obsługa HTML
Jakiś czas temu w notce Niebezpieczeństwo HTML'a nakreśliłem problem wstrzyknięć kodu HTML. W komentarzach kilkukrotnie pojawiło się pytanie o sposób obrony przed tego typu zagrożeniem.
Najprostszą obroną jest usuwanie wszelkich tagów HTML z przesłanych danych. Możemy tego dokonać korzystając z funkcji strip_tags oraz htmlspecialchars. W przypadku drugiej funkcji warto zainteresować się jej opcjonalnymi parametrami tzn. sposobem postępowania z apostrofami i cudzysłowami oraz kodowaniem. Przykładowy kod chroniący przed HTML Injection dla strony kodowanej UTF-8 może wyglądać tak:
<?php
$var = htmlspecialchars( strip_tags( $var ), ENT_QUOTES, 'UTF-8' );
?>
Metajęzyki
Często spotykanym sposobem obejścia problemów z przesyłanym kodem HTML jest skorzystanie z metajęzyków. Najpopularniejsze z nich to BBCode, Textile oraz Wikitekst. Ich zadaniem jest umożliwienie korzystania z dobrodziejstw HTML bez jego jawnego użycia, poprzez udostępnienie użytkownikom odpowiednich znaczników. Przykładowo w celu uzyskania efekty pogrubienia należy skorzystać z tagu [b] zamiast <b> czy <strong>. Po przesłaniu odpowiednio sformatowanego tekstu skrypt na serwerze odpowiednio parsuje go tworząc jego odpowiednik w HTML.
Czarna lista
Blacklist jest popularnym sposobem wykrywania ataków typu XSS. Opiera się on na zdefiniowaniu słów, które są charakterystyczne dla tego typu ataków. W przypadku XSS takim słowem może być script. W przypadku wykrycia jednego ze słów znajdującego się na czarnej liście w przesyłanym tekście podejmowana jest akcja mająca zaradzić niebezpieczeństwu np. przerwanie działania skryptu.
<?php
if( strpos( $var, 'script' ) !== false )
die( 'Wykryto XSS!' );
?>
Minusem takiego rozwiązania jest duża trudność w zdefiniowaniu wszelkich możliwych słów kluczowych charakteryzujących ataki XSS. Istnieje wiele sposobów przemycenia kodu JavaScript przez co metoda ta nie jest bardzo bezpieczna. Przekonali się o tym twórcy strony house.pl, którzy zdecydowani się na stworzenie własnego systemu filtracji.
Biała lista
Odwrotnością blacklist jest whitelist. Polega ona na zdefiniowaniu znaczników HTML, które mogą być użyte. Po raz kolejny przyda nam się nam funkcja strip_tags. Tym razem będziemy musieli skorzystać z jej opcjonalnego parametru określającego dozwolone tagi.
<?php
$txt = strip_tags( $txt, '<h1><strong>' );
?>
Powyższy kod ma jedną wadę ? nie kontroluje w żadne sposób atrybutów dozwolonych znaczników. Tak więc jeśli zmienna $txt przyjmie wartość
<h1 onmousemove="alert('XSS')">XSS</h1>
nie zablokuje ona wykonania XSS.
W przypadku gdy ilość udostępnianych znaczników nie jest duża możemy posłużyć się wyrażeniami regularnymi w celu przefiltrowania danych. W pierwszej kolejności zamieniamy wszystkie tagi na encje, a następnie odwracamy ten proces dla dozwolonych znaczników.
<?php
$var = htmlspecialchars( $var, ENT_QUOTES, 'UTF-8' );
$encje = array(
'@<strong>(.*?)</strong>@si',
'@<h1>(.*?)</h1>@si'
);
$tagi = array(
'<strong>$1</strong>',
'<h1>$1</h1>'
);
echo preg_replace( $encje, $tagi, $var );
?>
HTML Purifier
HTML Purifier jest skryptem PHP mającym za zadanie usunięcie z kodu HTML wszelkich niebezpiecznych elementów. Dodatkowym atutem tego narzędzia jest poprawa kodu, tak aby był on zgodny ze specyfikacjami W3C.
W najprostszej formie użycie powyższego narzędzia sprowadza się do kilku linii kodu.
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . 'htmlPurifier' );
require 'HTMLPurifier.php';
$purifier = new HTMLPurifier( );
$var = '<h1 onmousemove="alert(1)">dasdas</h1>
<strong><em>test</strong></em>';
echo $purifier -> purify( $var );
?>
wynik:
<h1>dasdas</h1><strong><em>test</em></strong>
Jak widać powyższy kod został oczyszczony z kodu JavaScript oraz zostało poprawione zagnieżdżenie tagów.
Warto zobaczyć:
Komentarze
- Brak komentarzy.