Tämä blogikirjoitus on tiivistelmä OWASP Helsingin alajaoksen 17.11. järjestetyssä tilaisuudessa pitämästäni esityksestä Manuaalinen ja automaattinen koodianalyysi (Manual vs. Automated Code Analysis). Englanninkielinen esitys on ladattavissa myös jaoksen verkkosivuilla.
Sovellustietoturvan tarkistus voidaan jakaa neljään osa-alueeseen, sen mukaan onko tarkastus dynaamista vai staattista ja tehdäänkö tarkastus automaattisesti vai käsin. Tässä tarkastellaan vain staattisen eli koodiin perustuvan tarkastuksen eroja, ulkopuolelle jäävät siis pentestit yms.
Automaattinen koodin skannaus voi perustua monenlaiseen lähestymistapaan, yksinkertaisimmillaan pelkkään tekstimatchaukseen ja monimutkaisimmillaan koko koodin jäsentämiseen ja analysointiin tai jopa tilastollisiin menetelmiin. Ääripäiden väliin jää token matching, syntaksipuuhun perustuva haku (jolloin analysaattori ymmärtää erottaa esim. funktiokutsut ja muuttujat toisistaan), ja data flow analyysi.
Käsin koodin läpikäynti voi tapahtua hyvin monella tavalla, mutta tyypillisiä lähestymistapoja ovat mm. tiettyjen merkkijonojen etsiminen (työkalulla), hyökkäyspinnan selvittäminen ja tarkastelu, input/output-polkujen ja komponenttikirjastojen konfiguraation tarkastelu, autorisointilogiikan ja esimerkiksi hyväksymissääntöjen validointi ja ennen kaikkea arkkitehtuurin analysointi mm. sisäisten rajapintojen osalta. Luonnollisesti käytössä ovat myös erilaiset tarkistuslistat.
Automaattisen analysoinnin etu on kiistatta se, että se on huomattavasti nopeampaa, laaja-alaisempaa (ainakin katetun koodin mielessä) ja toistettavaa. Automaattisesta analysoinnista saatavat tulokset on kuitenkin jonkun aina tulkittava ja arvioitava löydöksistä:
- mitkä ovat todellisia löydöksiä eli oikeita haavoittuvuuksia?
- mitkä ovat vääriä hälytyksiä?
- miten paljon haavoittuvuuksia jäi löytymättä?
Lisäksi todellisten löydösten korjaukset täytyy suunnitella, mihin työkalu joko antaa tai ei anna hyvää suositusta.
Application Security Verification Standard (ASVS)
OWASP:n Application Security Verification Standard eli ASVS määrittää vaatimukset eritasoisille sovellustietoturvan tarkistuksille. Se koostuu neljästä tasosta, joista ensimmäinen kattaa pintapuolisen tarkistuksen ja neljäs taso edellyttää jo hyvinkin perusteellista tarkastusta.
Karkeasti ottaen ASVS:n ensimmäinen taso voidaan toteuttaa automaattisilla (staattisilla ja dynaamisilla) työkaluilla, joskin niiden antamat tulokset täytyy käydä käsin läpi. Toiselle tasolle päästäkseen sovellus tulee käydä manuaalisesti läpi, dynaamisesti (käsin testaamalla) ja/tai staattisesti (käsin katselmoimalla). Kolmas ja neljäs taso syventävät käsin tehdyn katselmoinnin vaatimuksia. Työkalujen käyttö on sallittu muillakin kuin ensimmäisellä tasolla, mutta silloin ne toimivat vain käsin tehtävän tarkastuksen apuna.
ASVS:ssä on 14 vaatimusosa-aluetta, mm. autentikaatioon, syötteen validointiin, tiedon suojaamiseen ja lokitukseen liittyen. Näille vaatimuksille on tarkemmat sisältömääritykset, joista kunkin kohdalta on mainittu, miltä osin tarkastusvaatimus sisältyy millekin ASVS:n tasolle, ts. käytännössä onko sen katsottu voitavan tehdä automaattisesti vai käsin ja dynaamisesti vai staattisesti.
Semitieteellisesti tarkasteltuna, kun verrataan ASVS:n tasoille 1B (eli automaattinen koodin skannaus) ja 2B (eli käsin tehtävä koodin läpikäynti) asetettuja vaatimuksia, havaitaan että taso 2B sisältää huomattavasti enemmän tarkastuskohteita. Nämä ovat käytännössä sellaisia, joihin ei automaattinen työkalu edes pure, esimerkkinä:
-
V2.5 Verify that all authentication controls (including libraries that call external authentication services) have a centralized implementation.
-
V2.13 Verify that account passwords are salted using a salt that is unique to that account (e.g., internal user ID, account creation) and hashed before storing.
-
V14.2 Verify that security control interfaces are simple enough to use that developers are likely to use them correctly.
Toisaalta taas, automaattinen työkalu kelpuutetaan tarkastamaan seuraavat asiat lähdekoodista:
-
V5.2 Verify that a positive validation pattern is defined and applied to all input.
-
V6.1 Verify that all untrusted data that are output to HTML (including HTML elements, HTML attributes, JavaScript data values, CSS blocks, and URI attributes) are properly escaped for the applicable context. (Saattaa onnistua ns. tekstimatchingiin perustuvilta työkaluilta.)
-
V11.2 Verify that the application accepts only a defined set of HTTP request methods, such as GET and POST. (Vaatii työkalulta ymmärrystä konfiguraatiosta, esim. Struts tai Spring MVC.)
Automaattisen koodin skannauksen ongelmakohtia
Yleisesti ottaen automaattiselle koodiskannerille ongelmia tuottavat mm. big picturen katsominen ja arkkitehtuurin selkeyden ja turvallisuuden arviointi, ei-toiminnalliset vaatimukset (esim. kuinka hyvin järjestelmä sietää kuormitusta ja DoS-hyökkäyksiä), loogiset virheet esimerkiksi autorisoinnissa, tai puuttuvat tietoturvavaatimukset tai niiden toteutus.
Skannausta hankaloittaa tietysti myös koodi, joka on osa järjestelmää jollain epätavallisella tavalla, esim. plugin, sekä järjestelmän konfiguraation tulkinta, erityisesti kun käytössä on jokin framework kuten Hibernate, Spring, Wicket yms.
Johtopäätökset
Loppupäätelmänä ei voi tietysti sanoa, että jompi kumpi koodin analysointitapa olisi ainoa oikea, mutta ne tukevat toisiaan ja sopivat eri tilanteisiin. Tapojen painotuksessa on syytä pohjata päätös järjestelmän luonteeseen ja riskianalyysiin. Esimerkiksi web-portaalin ohjelmakoodi voidaan saada melko hyvinkin skannattua automaattisesti, mutta monimutkaisen extranet-sovelluksen logiikan monimutkaisuus ja riskit saattavat olla liian suuria automaattiselle työkalulle jätettäväksi.
On siis hyvä tiedostaa, että automaattinen analyysi ei useinkaan anna kovin täydellistä raporttia tietyntyyppisistä ongelmia, ja lisäksi ihmistyötä tarvitaan aina tulosten analysointiin. Toisaalta taas käsin tehtävä läpikäynti voi hyötyä suuresti automaattisten työkalujen kaivamista alustavista tuloksista.