Cross-site scripting

**Cross-site scripting** (**XSS**) on tietoturva-aukko, joka esiintyy usein WWW-sovelluksissa. Cross-site scripting mahdollistaa koodin syöttämisen, ja sen avulla mahdollisesti tunkeutumisen verkkosivulle.

XSS-aukkoa hyödyntämällä voidaan kiertää pääsynhallinta, kuten saman alkuperän käytäntö. Haavoittuvuutta voidaan hyödyntää esimerkiksi HTML-koodilla tai asiakaspäässä suoritettavilla skripteillä.

Cross-site scriptingistä käytettiin aluksi lyhennettä *CSS*, mutta tästä lyhenteestä on luovuttu, koska se sekoittuu helposti kaskadisiin tyyliohjeisiin (*Cascading Style Sheets*).

Erityisen vaarallisia aukot ovat sivustoilla, joilla käsitellään henkilötietoja, rahaa tai joiden surffaajien henkilöllisyyden tulisi pysyä salassa (esimerkiksi ihmisoikeusaiheiset sivustot monissa maissa).

## Taustaa

Kun Netscape-selaimeen lisättiin JavaScript-tuki, havaittiin, että siihen liittyy turvallisuusriski, kun WWW-palvelin lähettää suoritettavaa koodia käyttäjän koneelle. Yksi ongelmista syntyy, kun käyttäjä avaa useita selainikkunoita. Joissain tapauksissa skripti tarvitsee oikeuksia toisen sivuun tai objektin käsittelemiseen. Toisaalta taas tämä tulisi estää, koska ominaisuutta hyväksikäyttävä vihamielinen koodi voi varastaa salattavia tietoja. Ongelman ratkaisemiseksi selaimissa otettiin käyttöön yhtenäinen turvallisuuskäytäntö. Käytäntö sallii objektien ja sivujen vuorovaikutuksen vain samalla protokollalla ja saman verkkotunnuksen sisällä. Näin hyökkääjän verkkosivustolla ei ole pääsyä selaimen toisessa ikkunassa oleviin, salattaviin tietoihin. Samankaltaisia saantikäytäntöjä on sittemmin omaksuttu muihinkin skriptikieliin.

Cross-site scripting -turvallisuusaukot ovat verkkosivuilla olevia haavoittuvuuksia, joita hyväksikäyttäen hyökkääjä voi ohittaa nämä suojamekanismit. Verkkosivulle syötetyn vihamielisen koodin avulla hyökkääjä pääsee käsiksi salattaviin tietoihin, evästeisiin ja muihin kohteisiin.

## Tyypit
XSS-haavoittuvuudet luokitellaan DOM-pohjaisiin, pysyviin ja ei-pysyviin.

### DOM-pohjaiset
DOM-pohjaiset haavoittuvuudet, eli paikalliset cross-site scripting -haavoittuvuudet ovat sivujen skripteissä itsessään. Tällainen haavoittuvuus voi sisältyä esimerkiksi JavaScript-koodiin, joka käyttää sivun osoitteessa annettuja parametreja kirjoittaessaan sivulle sisältöä. Sivu on haavoittuva, jos parametrina välitettävää tietoa ei ennen sivulle lisäämistä käsitellä siihen mahdollisesti sisällytettyjen HTML-koodien varalta. Tällöin parametrina annettu HTML lisätään sivulle sellaisenaan, minkä seurauksena se saatetaan tulkita ja suorittaa sivun katselijan selaimessa. Käytännössä nämä aukot ovat hyvin samankaltaisia kuin ei-pysyvät haavoittuvuudet.

Koska Internet Explorer -selaimen vanhat versiot käsittelevät asiakaspuolen skriptejä paikallisesti (esimerkiksi sivua selaavan käyttäjän koneen kiintolevyllä), tällainen XSS-turvallisuusaukko voi aiheuttaa etäkäyttöhaavoittuvuuden. Jos paikallinen sivu (jollaisia asennetaan tyypillisesti selaimen asennuksen yhteydessä) on haavoittuva, hyökkääjän verkkosivustolla olevan linkin kautta tälle sivulle tultaessa sen sisältö suoritetaan käyttäjän koneella, käyttäjän selaimen oikeuksilla hänen järjestelmässään. Näin on mahdollista ohittaa pelkästään XSS-hyökkäysten estoon tarkoitettujen verkkotunnusrajoitusten lisäksi kaikki muutkin selaimen skripteille normaalisti asettamat rajoitukset. Internet Explorerin osalta tämä turvallisuusaukko on korjattu Internet Explorer 6 Service Pack 2:ssa.

### Ei-pysyvät
Ei-pysyvissä tai väliaikaisissa XSS-aukoissa haitallisesti muotoiltu koodi ei tallennu sivustoa ylläpitävälle palvelimelle mutta toimii käyttäjän selaimessa siten kuin sen alkuperä olisi sivusto itse. Haittakoodi ujutetaan sivustolle osoitteen avulla. Käyttäjä täytyy huijata napsauttamaan vahingollisesti muotoiltua linkkiä esimerkiksi sähköposti-, pika- tai tekstiviestissä, hakukoneen tuloslistauksessa, keskustelupalstalla tai internetsivuilla.

#### Esimerkki
# Liisa käyttää usein verkkokauppaa, jonne voi kirjautua tunnuksilla ja tallentaa henkilö- ja luottokorttitietoja.
# Kalle huomaa verkkokaupan sivustolla XSS-haavoittuvuuden.
# Kalle lähettää Liisalle sähköpostitse, pikaviestimellä tai muulla keinolla vihamielisesti muotoillun linkin, joka saa verkkokauppasivuston käyttäytymään Kallen haluamalla tavalla.
# Liisa ei huomaa linkin viallisuutta, koska se alkaa aivan normaalisti verkkokaupan osoitteella ja sivu itsessään näyttää oikealta. Liisa surffaa sivuilla kirjautuneena.
# Kallen skripti voi nyt varastaa Liisan henkilö- ja luottokorttitiedot ja tehdä käytännössä mitä tahansa sivustolla Liisan puolesta.

### Pysyvät
Pysyvissä XSS-aukoissa haittakoodi on tallennettu sivustoa ylläpitävälle palvelimelle esimerkiksi sivuston osoitteeseen lisättyjen parametrien avulla, lomakkeella tai vihamielisesti muotoilluilla tiedoilla, joita selain ilmoittaa itsestään HTTP-kutsun yhteydessä. Sivulla vierailevat altistuvat haittakoodille. Sivuston osoite ei näytä huomiota herättävän pitkältä koodilta, ja sivulle voidaan eksyä normaalisti sivustolla navigoimalla.

#### Esimerkki
# Liisa käyttää usein verkkokauppaa, jonne voi kirjautua tunnuksilla ja tallentaa henkilö- ja luottokorttitietoja (esimerkiksi `www.vaatteisto.fi`).
# Kalle huomaa verkkokaupan sivustolla XSS-haavoittuvuuden.
# Kalle muotoilee verkkokaupan osoitetta siten, että haittakoodi tallentuu sivustolle (esimerkiksi `www.vaatteisto.fi/&lt;script src="/haittakoodi.js">&lt;/script>`).
# Kalle odottaa, että ihmiset vierailevat sivuilla.
# Kallen skripti kerää Liisan ja muiden käyttäjien henkilö- ja luottokorttitiedot talteen.

## Todellisia esimerkkejä
Julkisesti esillä olleista cross-site scipting -haavoittuvuuksista on satoja esimerkkejä. Seuraavat esimerkit havainnollistavat erilaisia tietoturva-aukkoja.

* Bugzillan virhesivulta löytyi DOM-pohjainen haavoittuvuus, jossa sivulle kirjoitettiin sen osoite JavaScriptillä ilman suotimia tai merkistökoodausta. Selaimesta riippuen hyökkääjä saattoi sopivasti muotoillulla osoitteella lisätä sivulle oman skriptinsä. Haavoittuvuus korjattiin koodaamalla erikoismerkit merkistökoodauksella ennen niiden sivulle kirjoittamista.
* Kuuluisa esimerkki ei-pysyvästä haavoittuvuudesta ovat Yair Amitin joulukuussa 2005 löytämät kaksi haavoittuvuutta Google.com-sivustolla. Haavoittuvuuksia hyödyntävä hyökkääjä saattoi esiintyä Googlen edustajana tietojenkalastelussa.
* Elokuussa 2006 DOM-pohjaista haavoittuvuutta hyödynnettiin tekaistuissa uutisissa, joiden mukaan presidentti Bush oli palkannut 9-vuotiaan pojan Information Security -osaston päälliköksi. Cbsnews.com- ja www.bbc.co.uk-uutispalveluissa olleita haavoittuvuuksia hyväksikäyttäen hyökkääjät pystyivät lisäämään niihin oman, keksityn uutisen.
* Marc Slemko löysi Hotmail-palvelusta pysyvän haavoittuvuuden lokakuussa 2001. Hyökkääjä saattoi varastaa käyttäjän Microsoft .NET Passport -evästeen. Haavoittuvuuden hyödyntäminen edellytti vihamielistä HTML-koodia sisältävän sähköpostin lähettämistä Hotmail-käyttäjälle. Hotmailin sähköpostien suodatus ei havainnut vihamielistä koodia, ja Internet Explorerin jäsennin käsitteli ja suoritti vihamielisen koodin. Ongelma korjattiin nopeasti, mutta useita samankaltaisia ongelmia havaittiin Hotmail-palvelussa ja muissa Passportia käyttävillä sivustoilla myöhemmin.
* Netcraft-yhtiö ilmoitti kesäkuussa 2006, että PayPalin verkkosivustolla on turvallisuusongelma ja että sitä on hyödynnetty aktiivisesti luottokorttien numerosarjojen ja henkilötietojen kalastelussa. Pian sen jälkeen Paypal ilmoitti, että muutos sivuston koodissa sulki haavoittuvuuden.
* Lokakuussa 2005 Samy hyödynsi turvallisuusaukkoa MySpace-palvelussa, mikä aiheutti yli miljoona ystäväkutsua tunnuksen luojan profiiliin.
* Susam Pal paljasti huhtikuussa 2006 haavoittuvuuden Community Architect -sivuston vieraskirjaohjelmassa. Monet ohjelmaa käyttäneet WWW-hotellit olivat haavoittuvia.
* Marraskuussa 2006 Rajesh Sethumadhavan löysi pysyvän haavoittuvuuden Orkut-sivustolta. Haavoittuvuutta hyödyntävä Orkutin jäsen saattoi lisätä HTML- ja JavaScript-koodia profiileihinsa. Rodrigo Lacerda käytti tätä haavoittuvuutta luodessaan evästeitä varastavan skriptin, Orkut Cookie Exploitin. Joulukuussa Orkut korjasi haavoittuvuuden.
* Lokakuussa 2007 Australian liberaalipuolueen sivustolta löytyi haavoittuvuus. Pääministeri Howardin kuvaan liitettiin haavoittuvuutta hyväksikäyttäen rivoa tekstiä.
* Suomessa Matti Nikin lista lapsipornona estetyistä sivustoista näkyi hetken aikaa poliisin sivustolla.
* Sampo-pankin sivut olivat avoinna kalastelijoille. Vuonna Aukon löytämisen jälkeisinä päivinä hakkerit löysivät kymmeniltä suurilta suomalaisilta sivustoilta vastaavanlaisia haavoittuvuuksia.
* Lokakuussa Twitterin etusivulle tehtiin muutoksia XSS:llä.

## XSS-haavoittuvuuksien välttäminen

Cross-site scripting -haavoittuvuuksien välttäminen edellyttää HTML-koodien siistimistä (*quoting* tai *escaping*) ennen kuin WWW-sovellus tai skripti käyttää niitä tulostuksessa. Monissa ohjelmointikielissä tähän on sisäänrakennetut funktiot tai kirjastot.

Ongelmana XSS-haavoittuvuuksien välttämisessä on, että keinot riippuvat usein tilanteesta, eli sivuston tarpeista ja ongelmista. Turvallisin menetelmä WWW-sovelluksille on jäsentää HTML, riisua tunnisteet ja attribuutit, joita ei ole erikseen sallittu ja tulostaa vasta sen jälkeen.

Yksinkertaiset suodatustavat, kuten tunnettujen vaarallisten tunnisteiden riisuminen, eivät välttämättä riitä. Esimerkiksi Hotmailiin lokakuussa 2001 kohdistuneessa hyökkäyksessä hyödynnettiin standardoimattomia parametreja.

## Muita haavoittuvuuksia
* Cross-zone scripting -haavoittuvuuksia hyödynnetään sovellusten vyöhykeympäristössä. Yleensä tällöin suoritetaan koodia suuremmilla oikeuksilla kuin mitä koodille normaalisti sallitaan.
* HTTP header injection -haavoittuvuudet, joita käytetään XSS-haavoittuvuuksien luomiseen, mahdollistavat esimerkiksi HTTP-vastauksen jakamisen.
* Sivustojenvälinen pyynnön väärennys (cross-site request forgery, CSRF tai XSRF) on kuin vastakohta XSS:lle. Siinä missä XSS:ssä hyödynnetään käyttäjän luottamusta verkkosivuun, CSRF:ssä hyökkääjä hyödyntää sivuston luottamusta sivua selaavan käyttäjän selainohjelmaan. Selain lähettää palvelimelle pyynnön, jonka palvelin luulee tulleen omilta autentikoiduilta (oikeaksi todistetuilta) käyttäjiltään.
* SQL-injektiossa hyödynnetään haavoittuvuutta sovelluksen tietokantakerroksessa. Kun käyttäjän syöte on suodatettu väärin, sovellus voi suorittaa minkä tahansa SQL-lauseen.

## Lähteet

## Aiheesta muualla
* Usein kysytyt kysymykset cross-site scripting -haavoittuvuuksista CGISecurity 
* Tietoa cross-site scripting -haavoittuvuuksista Apache Software Foundation 
* Saman alkuperän käytäntö MDN/Mozilla 
* Lista suomalaisilta sivustoilta löytyneistä XSS-aukoista (päivitetty 10.7.2010)