wiki:htmlKoodausJulkinen
Last modified 8 years ago Last modified on 2009-10-13 10:48:15

ParentLinkage?

Käyttäjän syötteiden esittäminen HTML-sivulla

Ongelman kuvaus

Cross-site scripting eli XSS-haavoittuvuuksien välttämiseksi kaikki dynaamisesti tuotettu html-koodi on tulostettava siten, että selaimelle lähetettävään sivuun ei ole mahdollista sisällyttää vaarallisia elementtejä. Vaarallisesta vähemmän vaaralliseen varottavia asioita ovat mm. seuraavat:

  • Skriptit, jotka suoritetaan heti sivua ladattaessa. Näitä ovat mm. kaikki script-elementin avulla esitettävät skriptit, mutta myös muita elementtejä (esim. iframe) voi hyödyntää tähän tarkoitukseen.
  • Skriptit, jotka suoritetaan jonkin käyttäjän toimenpiteen seurauksena. Näitä voi liittää käytännössä mihin tahansa elementtiin:
    <p onmouseover="alert('XSS')">Kappale tekstiä.</p>
    
    Vaikka skriptiä ei suoriteta täysin automaattisesti, on tämä haavoittuvuuden muoto käytännössä yhtä vaarallinen kuin skriptin suora suoritus.
  • Linkit, joiden href-attribuutti sisältää skriptin. Esim.
    <a href="javascript:alert('XSS')">Linkki</a>
    
  • Selaimen puolella suoritettavassa JavaScript-koodissa voi olla logiikkavirheitä sivun DOM-puuta muokattaessa. Jos esimerkiksi skripti hakee palvelimelta tekstimuotoista tietoa Ajax-pyynnön avulla ja liittää sen DOM-puuhun väärällä tavalla, saattaa hyökkääjä, joka pystyy vaikuttamaan palvelimen palauttaman tiedon sisältöön, pystyä kaappaamaan käyttäjän selaimen. Myös silloin, kun selain suorittaa palvelimella dynaamisesti generoitua JavaScriptiä on vaarana, että virhe skriptin generoinnissa mahdollistaa selaimen kaappaamisen.
  • Eräät "turvalliset" elementit (p, div jne.), joille on annettu CSS-tyylimäärityksiä. Näiden avulla on mahdollista peittää sivulla olevia rakenteita siten, että käyttäjän silmissä sivu näyttää aivan normaalilta, mutta tietosisältö ei pidäkään paikkaansa. Tällöin käyttäjä voidaan huijata suorittamaan toimintoja, joita hän muutoin ei olisi tehnyt. Joskus edes CSS-määrityksiä ei tarvita. Esimerkiksi jos tekstin oletetaan menevän yhdelle riville, mutta se sisältääkin br-elementin, voi jollekin listalle saada aikaiseksi "haamurivejä".
  • Muut linkit, joiden kohde on käyttäjän määrittämä. Näitä ei luonnollisestikaan voida täysin välttää, mutta jos linkin kohdetta on mahdollista jollakin tavoin rajata, se kannattaa tehdä. http- ja https-linkit eivät itsessään aiheuta XSS-ongelmia, mutta niitä voidaan käyttää apuna cross-site request forgery -hyökkäyksissä. Jos esimerkiksi ulkopuolisella sivulla on img-elementtejä, joiden src-attribuutti osoittaa Korppiin, suorittaa selain (tavallisesti mitään kysymättä) get-kutsut näihin Korpin sivuihin. Kutsut sisältävät myös Korpin sessioon liittyvät evästeet.

Apumetodeja JavaScriptiä kirjoitettaessa

  • jQueryn text()-metodilla voi DOM-puun elementin sisälle tulevan tekstin asettaa turvallisesti ilman, että tekstissä mahdollisesti olevia HTML-erikoismerkkejä tulkitaan HTML-koodina. Esimerkiksi
    $("#tekstikappale").text(str);
    
    asettaa elementin, jonka id="tekstikappale" tekstisisällöksi str. Jos str="<b>kissa</b>", ei tekstiä "kissa" lihavoida, vaan tagit tulostetaan selaimessa sellaisenaan.

Vaarallisiksi havaittuja paikkoja

  • Kannasta haettujen merkkijonojen lisäksi on koodattava myös sellaiset merkkijonot, jotka on saatu URL-parametreina. Myös hidden-kenttien kautta välitettävät merkkijonot ovat käyttäjän muutettavissa, vaikka sivulla ne eivät näykään tekstikenttinä! Jos yksikin parametri välitetään URL:stä html-sivulle koodaamatta, on mahdollista rakentaa sellainen hyökkäys, jossa uhrille lähetetään sähköpostiviesti ("Antaisitko mielipiteesi asiasta X...") ja skripti on piilotettu linkissä olevaan URL-parametriin. Tällöin skripti voi esimerkiksi Ajax-pyynnön avulla tehdä viestin vastaanottajan nimissä toimenpiteitä, ilman että viestin vastaanottanut edes huomaa mitään. Tästä menetelmästä tekee erityisen ikävän se, että palvelimen HTTP-lokeista ei usein paljastu kunnollisia johtolankoja hyökkääjän identiteetistä.
  • Epäselvyydet siitä, mitkä merkkijonot on jo koodattu ja mitkä ei, johtavat usein virheeseen. Pitäisi olla aina selvää, palauttaako jokin metodi suoraan sivulle tulostettavaksi tarkoitettua html-koodia (jota ei pidä koodata uudestaan) vai mielivaltaisia merkkijonoja (esimerkiksi suoraan kannasta). Tarvittaessa kannattaa asiasta mainita metodin kommentissa. Jos sivulla yhdistellään merkkijonoja, pitäisi yhdistettävien merkkijonojen olla "samaa tyyppiä" (molemmat html-koodia tai molemmat koodaamatonta dataa).
  • Merkkijonon html-koodaaminen kahteen kertaan rikkoo sivun toiminnan, vaikkei yleensä aiheutakaan tietoturvaongelmia. Koodataan siis kerran ja vain kerran.
  • Turhia tietotyyppien muutoksia kannattaa välttää, ja käyttää mahdollisuuksien mukaan mahdollisimman spesifiä tyyppiä kussakin tilanteessa. Esimerkiksi päivämäärät Javassa Calendar-olioina, ei String-olioina.

Lisälukemista