2005-11-22

Turvallista HTML-syndikaatiota

Re: No, ask what Bloglines can do to you.

Juttu lyhyesti: Phil Ringnalda löysi XSS-haavoittuvuuksia kolmesta web-pohjaisesta uutisvirtalukijasta. Uutisvirran mahdollisesti sisältämä vahingollinen koodi pääsee luikertelemaan läpi lukijaohjelman suodattimista ja osaksi lukijaohjelman käyttöliittymänä toimivaa web-sivua. Kahdessa tapauksessa kolmesta Ringnaldan havaitsemat viat on jo korjattu, kolmas jostain syystä hidastelee.

Taustalla on se ikävä tosiasia, että useimpien HTML-koodia lähteestä tai toisesta vastaanottavien web-sovellusten suodattimissa on virheitä. Nämä virheet taas johtuvat siitä, että kyseiset suodattimet ovat useimmiten ad hoc -periaatteella kasattuja regex-listoja. Puolustukseksi sanottakoon, että tehtävä ei ole helppo: jo pelkästään standardien mukainen HTML 4.01 tarjoaa lukuisia paikkoja JavaScript-koodin piilottamiseen ja mukaan täytyy laskea erilaiset yksipuoliset selainlaajennokset*, on kasassa aikamoinen soppa.

Mikä siis neuvoksi, jos projekti vaatii ulkopuolisesta lähteestä tulevan HTML:än lisäämistä osaksi sivua, eikä turvallisuudesta myöskään saa tinkiä? Yksi vaihtoehto on kylmästi poistaa kaikki tagilta näyttävä ja laittaa loput saman koodausrutiinin läpi kuin kaikki muukin ulkopuolisesta lähteestä tuleva teksti. Toinen vaihtoehto on olla todella tiukka ja sallia vain taatusti harmittomia elementtejä ilman attribuutteja.

Muitakin vaihtoehtoja on ja se mitä suosittelen on jäsentelijän (tuttavallisemmin parseri) ja kirjoittajan yhdistelmä. Käytännössä siis otetaan sopiva jäsentelijä, annetaan sen muodostaa HTML-koodista puu ja käydään tuo puu lävitse, lisäten HTML-kirjoittajan puuhun ainoastaan sallitut elementit ja sallien attribuuteista ainoastaan hyväksytyksi määritellyt arvot. Kun tähän liitetään CSS-jäsentelijä, voidaan sallia myös joidenkin inline-tyylien lisääminen sisältöön. Kokonaisuuden viimeistelee sopiva kuvankäsittelykirjasto, jonka kautta palvelin välittää kaikki viitatut kuvat.

Ainoastaan todella paha tietoturvavirhe selaimessa tai kuvankäsittelykirjastossa voisi enää tehdä tästä hyökkäysvektorista toimivan. Mikäli niin halutaan, voidaan tuloksena olevan koodin taata myös olevan asianmukaisesti muotoiltua tai peräti validia XHTML:ää.

Koska ratkaisu on olemassa, miksi sitä ei sitten käytetä ja miksi Ringnalda löysi samankaltaisia haavoittuvuuksia kolmesta ohjelmasta sen kummemmin aivojaan rasittamatta? Ehkä tärkeimpänä, HTML:n jäsentely ei ole millään lailla hauskaa puuhaa, varsinkin mikäli ohjelman oletetaan pystyvän käsittelemään uskomattomin tavoin rikkinäistä koodia. Joitain avoimen ohjelmiston alaisia kirjastoja on olemassa, mutta näille kirjastoille harvemmin löytyy liittymää web-sovelluksissa suosituista skriptikielistä. Skriptikielellä kirjoitettu jäsentelijä olisi puolestaan uskomattoman hidas. Tämän tyyppinen ratkaisu olisi myös melko pakko toteuttaa kokonaisuutena, toisin kuin mainitut regexit, joiden määrä voi olla aluksi viisi, sitten kymmenen ja piakkoin viisikymmentä, mutta asian kimpussa tarvitse missään vaiheessa kuluttaa aikaa kyllästymiseen asti.

Jos tästä jutusta haluaa etsiä jonkin pointin, voisi se olla että tämä ongelma voidaan ratkaista hyvin pitävällä tavalla. Ikävä kyllä ratkaisu tulee vaatimaan merkittävän määrän C-koodausta, mikäli sillä haluaa olevan laajempaa vaikutusta. En kuitenkaan ihmettelisi lainkaan, jos jokin Mozilla Firefoxin selainlaajennuksina tarjotuista lukijaohjelmista toimisi jo tähän tapaan, kun kaikki tarvittavat kirjastot ovat jo saatavilla.

Jokaisen ohjelmoijan kannattaa puolestaan muistaa, että regexit ovat hyvä renki mutta huono isäntä. Jos joku ohjelman osa alkaa sisältää rivi rivin jälkeen regexejä, kannattaa harkita osan laittamista uusiksi.

* Erityisti voisi mainita Microsoftin dynamic properties-tekniikan, jota kavereiden kesken kutsutaan nimellä CSS expressions.