You are here: TUTWiki>Tietoturva/Tutkielmat>TyoLuettelo?>2005-17
Markus Osa:

Avoimen koodin ohjelman haavoittuvuus

Johdanto

Tässä työssä tutustutaan erääseen BIND-nimipalvelinohjelmistossa ilmenneeseen puskurin ylivuotohaavoittuvuuteen. Puskurin ylivuodot ovat vielä tänäkin päivänä erittäin yleinen ongelma. Kun katsotaan esimerkiksi Ubuntussa, eräässä suositussa Linux-distribuutiossa, ilmenneitä haavoittuvuuksia, luokitellaan 45 % haavoittuvuuksista puskurin ylivuodoiksi. [1]

Käyn tässä työssä läpi kooditasolla, mikä haavoittuvuuden aiheutti ja miten se olisi voitu ehkäistä ja korjata. Käyn myös läpi, mitä olisi vaadittu onnistuneen hyökkäyksen suorittamiseen tätä haavoittuvuutta hyväksi käyttäen.

Puskurin ylivuoto

Kun tarkastellaan ohjelmistoissa esiintyneitä haavoittuvuuksia, ehkä yleisimmin tavattu virhe on se, että käyttäjän ohjelmistolle antaman syötteen oikeellisuutta ei tarkasteta tarpeeksi hyvin. Näin annetaan hyökkääjälle mahdollisuus muuttaa ohjelmiston suorituksen kulkua. Puskurin ylivuodot ovat erikoistapauksia näistä haavoittuvuuksista, ja niitäkin tavataan usein.

Puskurin ylivuodot johtuvat siitä, että ohjelmiston käyttämään puskuriin, esimerkiksi taulukkoon, kirjoitetaan enemmän tietoa kuin sinne itse asiassa mahtuu. Osaltaan puskurin ylivuotojen yleisyyteen on ehkä vaikuttanut se, että käytetyissä ohjelmointikielissä on ollut käytettävissä funktioita, joissa ei ole tarvinnut määrittää kopioitavan datan kokoa tai pituutta. Esimerkiksi C-ohjelmointikielessä on funktio strcpy(), joka kopioi annetusta osoitteesta lähtien merkkejä kohdeosoitteeseen, kunnes syötteessä tulee vastaan NULL-merkki. Näin on mahdollista kopioida kohdeosoitteeseen enemmän tietoa kuin sinne itse asiassa on varattu vapaata tilaa.

Miksi puskurin ylivuodoilla voidaan sitten ajaa hyökkääjän määrittämää koodia? Tämä johtuu käytetystä tietokoneen pinoarkkitehtuurista. Kun ohjelmassa kutsutaan funktiota, talletetaan pinoon funktion parametrit, funktion paikalliset muuttujat ja tieto siitä mistä kohtaa koodia suoritusta pitää jatkaa, kun funktio on suoritettu. Kirjoittamalla funktiossa liikaa dataa paikalliseen muuttujaan on mahdollista ylikirjoittaa tieto siitä, mistä suoritusta pitää jatkaa. Näin annetaan hyökkääjälle mahdollisuus ajaa haluamaansa koodia, kun hän pääsee tallentamaan haluamansa koodinpätkän ohjelman muistiavaruuteen ja muuttamaan funktion paluuosoitteen tämän koodinpätkän alkuun. [5]

Berkeley Internet Name Domain (BIND)

Esittely

BIND on Internet Systems Consortium (ISC) -yhtiön ylläpitämä toteutus DNS-protokollista. Ohjelmistopaketti sisältää toteutuksen mm. DNS-palvelimesta ja -asiakasohjelmistosta. Tässä tutustutaan nimenomaan DNS-palvelintoteutukseen.

Alunperin BIND luotiin Berkleyn yliopistossa Yhdysvalloissa. Sitä ylläpidettiin siellä aina versioon 4.8.3 asti. ISC on ylläpitänyt BIND:ia versiosta 4.9.3 lähtien. Tällä hetkellä BIND:in 4- ja 8-versiota ei enää tueta, vaan tarjolla on 9-versio. [2]

Haavoittuvuudet tässä ohjelmistossa

Käyttäen lähteenä CERT:in haavoittuvuustiedotteita [3] ja US-CERT:in haavoittuvuustietokantaa [4] voidaan suurin osa BIND:in haavoittuvuuksista lajitella puskurin ylivuotohaavoittuvuuksiin ja pelkkiin palvelunestohaavoittuvuuksiin (ks. listaus: Haavoittuvuudet BIND:issa). Puskurin ylivuotohaavoittuvuuksia käyttäen on teoriassa mahdollista suorittaa mitä tahansa hyökkääjän valitsemaa koodia, ja myös palvelunesto on mahdollista toteuttaa ylivuototapauksissa. Jälkimmäisillä haavoittuvuuksilla ("pelkkä" palvelunesto) viitataan palvelunestoon muilla keinoilla kuin ylivuotohaavoittuvuuksia käyttäen.

Tässä työssä tutkittu haavoittuvuus on tyypiltään ylivuotohaavoittuvuus, ja tätä haavoittuvuutta voidaan siten pitää eräänlaisena tyyppiesimerkkinä puskurin ylivuotohaavoittuvuudesta niin tässä ohjelmassa kuin yleisestikin.

Puskurin ylivuoto BIND versio 4:ssä

Sijainti

Tutkittavana oleva haavoittuvuus sijaitsee nslookupComplain() -funktiossa, joka sijaitsee named -hakemistossa ns_forw.c -tiedostossa. Tätä funktiota kutsutaan nslookup() -funktiosta useaan otteeseen. Alla ongelmallisen funktion esittely.

static void
nslookupComplain(sysloginfo, queryname, complaint, dname, a_rr, nsdp)
const char *sysloginfo, *queryname, *complaint, *dname;
const struct databuf *a_rr, *nsdp;

Funktion tarkoitus on luoda Syslog-daemonille virheviesti jostain nslookup() -funktion suorituksen aikana huomatusta ongelmasta. Ongelmalliset parametrit tässä ovat queryname ja dname -osoittimet, jotka ovat hyökkääjän määriteltävissä. Näitä parametreja käytetään kyseisessä funktiossa, kun luodaan viestiä Syslogille. Viestiä luodaan buf -nimiseen taulukkoon, jonka esittely alla.

char buf[999];

Kuten yllä olevan taulukon esittelystä huomataan, on taulukon koko ´vain` 999 merkkiä. Taulukkoon lisätään tietoa sprintf() -funktiolla.

sprintf() -funktio ottaa vaihtelevan määrän parametreja ja tulostaa annettuja parametreja halutulla tavalla formatoituna annettuun kohdeosoitteeseen. Ongelmalliset parametrit dname ja queryname pyydetään koodissa formatoimaan merkkijonoksi käyttäen s-valitsinta (s, kuten ´string`). s-valitsimesta kerrotaan ohjeissa seuraavaa:

´The const char * argument is expected to be a pointer to an array of character type (pointer to a string). Characters from the array are written up to (but not including) a terminating NUL character` [6]

Annettujen parametrien oletetaan siis olevan merkkijonotaulukoita, joista kopioidaan merkkejä kunnes vastaan tulee NUL-merkki. Jos NUL-merkkiä ei missään vaiheessa tulekaan vastaan, jatkaa sprintf() -funktio tyytyväisenä kohdetaulukon buf täyttämistä.

Haavoittuvuuden hyödyntäminen

DNS-protokolla toimii UDP:n päällä, ja DNS-palvelin kuuntelee portissa 53. Kuuntelu porteissa 1-1024 vaatii erityisoikeuksia, jonka takia DNS-palvelinta ajetaan monesti pääkäyttäjän tunnuksilla. Kun hyökkääjä tätä haavoittuvuutta käyttäen saa suoritettua näillä oikeuksilla valitsemaansa koodia, voivat seuraukset olla kohtalokkaita järjestelmän turvallisuuden kannalta. Olettaen, että pääkäyttäjän oikeuksia ei ole muuten rajoitettu, on hyökkääjän näin mahdollista periaatteessa tehdä palvelinkoneella mitä hän haluaa.

Korjausmahdollisuudet

Ylläkuvatun haavoittuvuuden mahdollistama hyökkäys voitaisiin estää usealla eri tavalla. Alla on kuvattuna joitakin tapoja.

Normaalit puskurin ylivuototarkistukset

Ensimmäinen ja ehkä selvin tapa on välttää kyseisten haavoittuvuuksien muodostumista. Puskurien ylivuodot johtuvat aina siitä, että puskurien kokoja ja rajoja ei oteta huomioon ja käytetään kopiointiin ohjelmointikielen funktioita, jotka eivät myöskään näitä tarkista. Inhimillisiä virheitä tietenkin sattuu, mutta on silti hyödyllistä pitää mielessään, mitä turvallisen ohjelmoinnin ohjeissa sanotaan. [7].

Eräs hyödylliseksi havaittu tapa vähentää yllä mainittuja inhimillisiä virheitä lopullisessa ohjelmistotuotteessa on ottaa ohjelmiston tuottamiseen mukaan säännölliset koodin katselmukset. Siinä käydään läpi tuotettua koodia ja etsitään mahdollisia virheitä tai vääriä toteutustapoja. Tätä prosessia on käytetty menestyksellä mm. OpenBSD-käyttöjärjestelmää kehitettäessä. [8] OpenBSD:n oletusasennuksessa ei ole ollut yli kahdeksaan vuoteen haavoittuvuutta, jota olisi voinut käyttää hyväksi ulkopuolelta. [9] Katselmukset ovat olleet apuna tässä.

Ohjelmien oikeuksien rajaamiset

Eräs tapa minimoida ohjelmassa esiintyvien haavoittuvuuksien teho on rajata ohjelman ajonaikaisia oikeuksia vain kullakin hetkellä tarvittaviin. Tämä on mahdollista esimerkiksi UNIX:eissa seteuid() - ja setegid() -kutsuilla. [10]

Käyttöympäristön laajennusosat

Järjestelmän ylläpitäjän kannalta yllä mainituista korjaustavoista ei ole kuitenkinkaan paljoakaan iloa, jos hänellä ei ole aikaa tai mahdollisuuksia alkaa tarkistaa käyttämänsä uuden ohjelman koodia. Ylläpitäjän onneksi käytettävissä on myös tapoja vähentää tai kokonaan poistaa puskurin ylivuodoista aiheutuvien hyökkäysten teho.

Eräs ylläpitäjän mahdollisuus on, käyttöjärjestelmästä riippuen, asentaa käyttöjärjestelmän ytimeen laajennusosia, jotka parantavat järjestelmän turvallisuusominaisuuksia. Eräs tällainen Linux-alustalle kehitetty järjestelmä on RSBAC [11], joka tuo lisäominaisuuksia ohjelman ajonaikaisten oikeuksien rajaamiseen. Ohjelmalle voidaan antaa vain sen tarvitsemat oikeudet sen tarvitsemiin resursseihin, eikä kaikkea mitä esimerkiksi järjestelmän ylläpitäjän tunnus toisi mukanaan.

Eräs myös käyttöjärjestelmän ytimeen muutoksia vaativa tapa on asettaa järjestelmän pino ei-ajettavaan tilaan, siten että sieltä ei voida suorittaa koodia. Tämä tapa voi tosin rikkoa joidenkin ohjelmien toiminnan, jotka käyttävät hyväkseen pinon ajettavuutta, mutta on muuten hyvin tehokas tapa pienentää puskurin ylivuotohyökkäysten vaikutusta [12]

Muut

Perinteinen, ja edelleen suositeltava tapa välttää ongelmia ohjelmistohaavoittuvuuksien kanssa on ajoittaisten ohjelmistopäivitysten suorittaminen.

Haavoittuvuuden korjaus BIND-ohjelmistossa

Haavoittuvuus korjattiin ISC:n toimesta BIND:n versiossa 4.9.8.

Tämän version funktiossa ongelma on korjattu lisäämällä seuraavat rivit aivan nslookupComplain() -funktion alkuun:

  1. strncpy(queryname, net_queryname, sizeof queryname);
  2. queryname[(sizeof queryname) - 1] = 0;
  3. strncpy(dname, net_dname, sizeof dname);
  4. dname[(sizeof dname) - 1] = 0;

Tässä net_queryname ja net_dname ovat uuden version funktiolle annettuja parametreja.

Ensimmäisellä rivillä kopioidaan annettu parametri queryname -muuttujaan käyttäen strncpy() -funktiota. Tämä funktio, toisin kuin sen sisarfunktio strcpy(), vaatii kolmanneksi parametrikseen kopioitavan datan määrän, joten dataa kopioidaan net_queryname -parametrista vain niin paljon kuin queryname -muuttujassa on tilaa. Samoin tehdään kolmannella rivillä net_dname ja dname -muuttujille.

Toisella ja neljännellä rivillä varmistetaan että queryname ja dname -muuttujien viimeisenä merkkinä on NUL-merkki, jotta sprintf() funktio osaisi lopettaa merkkien kopioinnin oikeassa kohtaa.

Kunnia tämän haavoittuvuuden löytämisestä ja analysoinnista annetaan alunperin PGP Securityn alaisuudessa toimineelle COVERT Labs -yksikölle. [13] Kyseisen yksikön julkaisemia tiedotteita tai muuta tietoa yksiköstä ei tosin enää löydy PGP Securityn sivustolta, joten tarkempaa tietoa haavoittuvuuden löytöhistoriasta ei ole saatavilla.

Tuoreita haavoittuvuuksia

BIND:ia ylläpitävä ISC pitää yllä myös listaa tunnetuista BIND-haavoittuvuuksista [14]. Haavoittuvuuksia on lukuisia myös uusimmalle versiolle 9, ja osa niistä on tyypiltään puskurin ylivuotoja. Sivulta pitäisi löytyä haavoittuvuusmatriisi, jonka avulla kutakin versiota koskevat haavoittuvuudet voisi helposti tarkistaa.

Lähteet

  1. Ubuntu Linux. Ubuntu Linux Security Notice Analysis verkkosivusto. Haettu 16.1.2006. https://wiki.ubuntu.com//USNAnalysis Lähdevinkistä kiitos Ville Reijoselle.
  2. Internet Systems Consortium. History of BIND software development. Haettu 17.11.2009. https://www.isc.org/software/bind/history
  3. CERT. CERT Advisories. Haettu marraskuussa 2005. http://www.cert.org/advisories/
  4. US-CERT. Vulnerability Notes. Haettu marraskuussa 2005. http://www.kb.cert.org/vuls
  5. Aleph One. Smashing The Stack For Fun And Profit. Haettu viimeksi 16.1.2006. http://www-cse.ucsd.edu/classes/sp05/cse127/Smash.htm
  6. Linux Programmer´s Manual. PRINTF-funktioperhe.
  7. Tietoturvallisuuden jatkokurssi. Tietoturvallinen ohjelma, yksi peukalosääntö - Kohta #15. Haettu viimeksi 16.1.2006. http://sec.cs.tut.fi/maso/materiaali.php?id=360
  8. OpenBSD. OpenBSD Security: Audit Process. Haettu viimeksi 16.1.2006. http://www.openbsd.org/security.html
  9. OpenBSD. Pääsivu. Haettu viimeksi 16.1.2006. http://www.openbsd.org/
  10. Thamer Al-Herbish. 1999. Secure UNIX Programming FAQ. Privileges and Credentials. Haettu viimeksi 17.11.2009. http://www.packetstormsecurity.org/programming-tutorials/secure-faq.html. (Alkuperäinen: http://www.whitefang.com/sup/secure-faq.html, toimimaton linkki 6.10.2009).
  11. Rule Set Based Access Control (RSBAC) verkkosivu. Haettu viimeksi 16.1.2006. http://www.rsbac.org
  12. Wikipedia. Buffer overflow: Executable space protection. Haettu viimeksi 16.1.2006. http://en.wikipedia.org/wiki/Buffer_overflow Lähdevinkistä kiitos Ville Reijoselle.
  13. US-CERT. Vulnerability #572183 - Credits. Haettu viimeksi 16.1.2006. http://www.kb.cert.org/vuls/id/572183
  14. Internet Systems Consortium. BIND Vulnerabilities. Haettu viimeksi 17.11.2009. http://oldwww.isc.org/index.pl?/sw/bind/bind-security.php Huom: haavoittuvuusmatriisia ei löydy.

-- HannuSimonen? - 23 Sep 2009
Print version |  PDF  | History: r11 < r10 < r9 < r8 | 
Topic revision: r11 - 17 Nov 2009 - 08:16:29 - HannuSimonen?
 

TUTWiki

Copyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TUTWiki? Send feedback