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 
htmlspecialcharsstrip_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$varENT_QUOTES'UTF-8' ); 
   
$encje = array(
                     
'@&lt;strong&gt;(.*?)&lt;/strong&gt;@si',
                     
'@&lt;h1&gt;(.*?)&lt;/h1&gt;@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

  1. Brak komentarzy.

Skomentuj

Dozwolone tagi: a, strong, em, code, blockquote

Nick (wymagany)

E-mail (na potrzeby graviatar'a):

Jesteś botem?

Komentarz: