- COMP.SEC.100
- 18. Turvallinen ohjelmistokehitys (SDL)
- 18.1 Turvallinen ohjelmistokehitys
Turvallinen ohjelmistokehitys¶
Aiemmassa luvussa on käsitelty ohjelmistojen haavoittuvuuksia ja keinoja niiden välttämiseksi. Ohjelmistojen turvaaminen ei välttämättä ole halpaa ja varsinkin Internetin alkuaikoina organisaatioissa saatettiin ohjata resursseja verkkoyhteyksien suojaamiseen ja yritettiin säästää turvaamalla ohjelmistoja vain reaktiivisesti eli korjaamalla haavoittuvuuksia vasta sitten, kun ne havaitaan. ”Penetrate and patch” -lähestymistavassa on haittapuolensa:
- Se voi tulla kalliiksi. IBM:n tilaaman kartoituksen perusteella vuonna 2025 yhden tietomurron kustannus oli koko maailmassa keskimäärin 4,4 miljoonaa dollaria, ja Yhdysvalloissa 10,2 miljoonaa (tutkittuja organisaatioita oli 600). Lisäksi murrosta aiheutuu vaikeasti mitattavaa mainehaittaa.
- Hyökkääjät voivat jatkaa pitkään huomaamattomasti. Mainitun tutkimuksen mukaan haavoittuvuuden hyväksikäytön havaitseminen kesti keskimäärin 181 ja korjaus 60 päivää.
- Korjaukset voivat saada aikaan uusia haavoittuvuuksia.
- Päivityksiä ei usein asenneta. Esimerkiksi Heartbleed-haavoittuvuus havaittiin vuonna 2014, mutta vuonna 2017 oli edelleen 200 000 haavoittuvaa laitetta verkossa.
CyBOK esittää historikatsauksessa muutoksen alkaneen niinkin myöhään kuin vuonna 1998 Gary McGraw’n lyhyestä artikkelista: Testing for security during development: why we should scrap penetrate-and-patch. Muutama vuosi kului vielä:
Turvallisen ohjelmistokehityksen malli¶
Aikoinaan Microsoftia kritisoitiin lukuisista virheistä ja sen www-palvelinohjelmistoa jopa suositeltiin välttämään. Vuonna 2002 Microsoft teki ”Trustworthy computing” -julistuksen, jonka tavoitteena oli parantaa ohjelmistoturvallisuutta. Julistus pantiin käytäntöön parantamalla ohjelmistokehitysprosessia ja näin muodostui vähitellen Microsoftin turvallinen ohelmistokehitysmalli SDL (Secure Software Development Lifecycle), jonka periaatteet Microsoft julkaisi. Turvallisesta ohjelmistokehitysmallista käytetään myös lyhenteitä SSDL ja SDLC. Microsoftin SDL on kehitetty suuren yrityksen näkökulmasta, mutta sen periaatteita voi soveltaa myös pienimuotoisempaan ohjelmistokehitykseen. Microsoft on julkaissut mallin myös PK-yrityksille, mutta malleja on muillakin, mm. OWASPilla sekä erilaisille järjestelmille (ks. seuraava alaluku).
Tyypillistä SDL:lle on, että siinä huomioidaan turvallisuus alusta alkaen osana ohjelmistokehitystä: mm. määritetään kehitettävän ohjelmiston tietoturvatavoitteita, otetaan turvallisuutta parantavia työkaluja pakollisena käyttöön sekä asetetaan ohjelmistokehitykseen osallistuville henkilöille rooleja, jotka edistävät turvallisuutta. Esimerkiksi roolina voi olla huolehtia, että asetetut turvallisuustavoitteet täyttyvät.
Microsoftin SDL sisältää mm. seuraavia osia:
- Koulutus on tärkeä tapa edistää osaamista, jotta ohjelmistokehittäjät tietävät oikeat toimintatavat ja oppivat tekniset yksityiskohdat, joilla parannetaan ohjelmistojen turvallisuutta.
- Tietoturvamääritykset ovat tärkeitä, koska niiden avulla ohjataan turvallista ohjelmistokehitystä ja voidaan määrittää ohjelman turvallisuus. Yhtenä esimerkkinä tietoturvamäärityksestä voi olla, että ohjelmassa ei saa olla yhtään SQL-haavoittuvuutta. Tämä voidaan sitten todentaa mm. testaamalla, koodikatselmoinnilla, ja staattisella analyysilla. Toisena esimerkkinä tietoturvamäärityksestä on, että käytetään määrättyjä staattisia analysaattoreita tietyissä vaiheissa ohjelmistokehitystä eikä staattinen analyysi saa ilmaista yhtään haavoittuvuutta. Tietoturvamäärityksiä pitää huomata päivittää, koska uhat myös muuttuvat. Tietoturvamääritysten luomiseen on kehitetty valmiita prosesseja, kuten SQUARE (Security Quality Requirements Engineering).
- Metriikat. Tietoturvallisuuden tason määrittäminen ja päätösten tekeminen edellyttää käytännössä metriikoita. Metriikoiden avulla määritetään alin mahdollinen hyväksyttävä tietoturvallisuuden taso. Yksi metriikka on KPI (Key Performance Indicator), jota käytetään johdon päätöksenteossa. KPI:t kuvaavat ja mittaavat organisaation liiketoimintaa, mutta ne voidaan sovittaa myös ohjelmistokehityksen tietoturvatavoitteisiin kuvaamaan ohjelmiston turvallisuustasoa. Tätä voidaan käyttää esimerkiksi viestinnässä organisaation johdolle. Esimerkkejä tällaisista KPI-mittareista on ratkaisemattomien haavoittuvuuksien lukumäärä, haavoittuvuuden korjaukseen kuluva keskimääräinen aika ja haavoittuvuuksien muodostumisen odotettu lukumäärä ohjelmoitaessa tietty määrä koodia. Lisäksi haavoittuvuuksille voidaan tehdä riskiarvio, mikä auttaa mm. organisaation johtoa hahmottamaan kokonaistilannetta.
- Lainsäädännön noudattaminen on tärkeää ohjelmistotuotteissakin. Erityisesti GDPR, CRA (Cyber Resilience Act) ja PCI DSS (Payment Card Industry Data Security Standard) ovat kansainvälisesti merkittäviä. EU:n tietosuoja-asetuksen noudattamisesta on tarkemmin kohdassa EU:n tietosuoja-asetuksen vaatimukset ohjelmistoille, ja aiemmassa luvussa on laajemmin EU-sääntelystä (mm. CRA ja siinä etenkin ohjelmistojen materiaaliluettelo SBOM, Software Bill of Materials, josta on lisää eri luvussa).
- Uhkamallinnus ohjelmistokehityksessä ottaa huomioon ohjelmiston ja sen käyttämän tiedon näkökulmat. Yksi malli on STRIDE (Spoofing, Tampering, Repudiation, Information Disclosure, Denial of Service, Elevation of Privilege). Lyhennelmän termit kuvaavat myös uhkamallinnuksen sisältöä: Tekeytyminen toiseksi, peukalointi, kiistäminen, tiedon vuotaminen, palvelunesto ja oikeuksien luvaton nosto. Uhkamallinnuksesta on tarkemmin riskienhallinnan yhteydessä.
- Suunnitteluperiaatteiden muodostaminen. Jotta ohjelmistokehitys olisi kustannustehokasta, kannattaa panostaa turvallisuuteen jo suunnitteluvaiheessa. Aiempi luku käsittelee monipuolisesti suunnitteluperiaatteita ja sieltä on hyvä kerrata myös varhaiset ja edelleen pätevät Saltzerin ja Schroederin periaatteet. Niiden painotukset ovat yli 50 vuoden kuluessa hieman muuttuneet. Esimerkiksi on entistä tärkeämpää suunnitella käyttöliittymä sellaiseksi, että käyttäjän on luontevaa tehdä turvalliset valinnat, (ks. myös luku inhimilliset tekijät). Vaikka ohjelmistojen mutkikkuus on aikojen kuluessa lisääntynyt, aivan alkuperäisellä tavalla pätee monimutkaisuuden minimoinnin periaate (yleisemmin “K.I.S.S.”). Sen avulla myös virheet minimoituvat ja käyttöliittymäkin pysyy ymmärrettävänä. Täydennyksenä varhaisiin periaatteisiin on varautuminen päivityksiin. Ohjelmisto pitää rakentaa niin, että päivittämisen on mahdollisimman turvallista ja vaivatonta.
- Käytä kryptografiaa oikein. Perehtymättömyys voi johtaa vakaviin virheisiin kryptografian valinnassa ja toteutuksessa. Esimerkiksi valitaan turvaton salausalgoritmi, turvallisen algoritmin turvaton käyttömoodi, tai pahimmillaan jätetään suojausta vaativa tieto kokonaan salaamatta. On perehdyttävä kryptografian standardeihin ja toteutettava krypto niiden mukaisesti. Tähän sopii tärkeä turvallisen ohjelmoinnin periaate: ”Pyörää ei kannata keksiä uudestaan.” Kryptossa tämä tarkoittaa parhaiden toimintatapojen selvittämistä ja ottamista käyttöön sekä niiden oikeaa toteuttamista ohjelmistoon. On muistettava myös varautua tulevaisuuteen: Kryptoalgoritmien vaihtamisen pitäisi olla mahdollista ja helposti toteutettavissa.
- Valitse muutkin tietoturvaratkaisut oikein. Autentikointi sinänsä on osa kryptografiaa, mutta identiteetin- ja pääsynhallinta (IAM) tai kerrospuolustusperiaatteen noudattaminen eivät välttämättä näy algoritmien tasolla. Lisäksi uhkamalli voi edellyttää lokitietojen keruuta tai muuta redundanssia.
- Hallitse riskit kolmansien osapuolten ohjelmistokomponenteissa. Ohjelmasta on riskialtista viitata ulkoisten osapuolten ohjelmistokomponentteihin. Näin joudutaan kuitenkin käytännössä tekemään, sillä kaikkea ei kannata toteuttaa itse. Tyypillistä on esimerkiksi ulkoisten ohjelmarajapintojen kutsuminen sekä ohjelmakirjastojen käyttö. Riskejä voidaan hallita seuraamalla säännöllisesti ulkopuolisten komponenttien haavoittuvuuksia (esim. CVE-tietokannasta). Haavoittuvuuksien korjaamiseksi pitää olla valmis suunnitelma ja ohjelma pitää pystyä tarvittaessa päivittämään. Riskiä voidaan pienentää myös varautumalla ennalta ulkoisen ohjelmistokomponentin antamaan arvaamattomaan syötteeseen. Ulkopuolisen kirjaston tai ohjelmiston valinnassa kannattaa huomioida, onko se laajasti käytössä ja päivitetäänkö sitä edelleen. Esimerkiksi GitHubista löytyy sinänsä hyödyllisiä kirjastoja, mutta ne on merkitty arkistoiduksi, jolloin niitä ei enää päivitetä.
- Käytä hyväksyttyjä työkaluja. Organisaation tulee määrittää hyväksytyt työkalut ja niiden asetukset sekä käyttö osana ohjelmistokehitystä. Esimerkiksi määritetään, mitä kääntäjiä on sallittu käyttää sekä määritetään asetukset, joilla kääntäjiä ajetaan.
- Tee staattista analyysia. Staattisen analyysin työkalut ja koodikatselmoinnit ovat tärkeä osa ohjelmistokehitystä. Organisaatiossa nimetään hyväksytyt staattiset analysaattorit sekä niiden asetukset ja määritetään vaatimukset, jotka ohjelman on täytettävä, jotta se voidaan hyväksyä ohjelmistokehityksen eri vaiheissa. Näitä päivitetään tarvittaessa.
- Tee dynaamista analyysia. DASTia (Dynamic Analysis Security Testing) tehdään ohjelman ajon aikana testaamaan ohjelman toimintaa ja etsimään virheitä ja haavoittuvuuksia. DAST sisältää usein ennalta rakennettuja työkaluja ja hyökkäyksiä. Myös fuzz-testaus sisällytetään usein osaksi DASTia. Kuten staattinen analyysi, DAST voidaan ottaa osaksi ohjelmistokehitysputkea. DAST voidaankin nähdä automatisoituna penetraatiotestauksena.
- Tee penetraatiotestausta. Penetraatiotestausta tekee yleensä joko organisaation sisäinen ryhmä tai ulkoinen konsultti. Penetraatiotestauksen tavoitteena on löytää haavoittuvuuksia ja virheitä ohjelmistosta, jotta ne voidaan korjata. Laajasti käytettynä viitekehyksenä penetraatiotestaukselle on OWASPin TOP 10 -lista.
- Toteuta prosessi tietoturvapoikkeamille. Kaikista varotoimista huolimatta on oletettavaa, että ohjelmiston haavoittuvuuksiin tai muihin tietoturvatapahtumiin joudutaan jossain vaiheessa reagoimaan. Siksi on tärkeää olla varautunut ennalta. Tämän vuoksi laaditaan valmiussuunnitelma (IRP, Incident Response Plan). IRP:n tulee sisältää, keneen tai mihin ollaan yhteydessä tietoturvapoikkeamissa ja hätätilanteissa, menettelyt haavoittuvuuksien ratkaisemiseksi ja vaikutusten vähentämiseksi sekä menettelyt asiakkaiden, käyttäjien ja viranomaisten kanssa viestimiseen. IRP:n tulee huomioida myös kolmannen osapuolen ohjelmistot ja komponentit, joihin on riippuvuuksia. IRP tulee myös testata ja sitä tulee kehittää havaintojen perusteella.