utvikling

Slik unngår du sikkerhetshull i programkoden

Kompleksitet i koden er fienden din, forteller norsk ekspert. Modellering av problemfeltet kan gjøre alvorlige feil til enkle feil.

Kompleksitet i koden er en fiende, ifølge sikkerhetsforsker Erlend Oftedal. – Vi legger hele tiden til nye ting, vi utvider funksjonaliteten, og vi er ikke flinke til å fjerne ting.
Kompleksitet i koden er en fiende, ifølge sikkerhetsforsker Erlend Oftedal. – Vi legger hele tiden til nye ting, vi utvider funksjonaliteten, og vi er ikke flinke til å fjerne ting.

Sikkerhetshull trenger ikke stamme fra programkode. De kan stamme fra svindel og juks eller feil i en konfigurasjon. Men det er neppe tvil om at kodefeil igjen og igjen utløser store sikkerhetsproblemer med programvare.

På konferansen Øredev, som nylig ble avholdt i Malmö, snakket sikkerhetsforsker Erlend Oftedal i Crosspoint Labs om nettopp dette.

Han innledet med å påpeke at det er kompleksitet i koden som er fienden. Det er her feilene oppstår.

– Vi legger hele tiden til nye ting, vi utvider funksjonaliteten og vi er ikke flinke til å fjerne ting, sa Oftedal og påpekte at sårbarheter kun er programfeil.

Noen oversikter viser at halvparten av sårbarhetene ligger i forretningslogikk, forteller han. Det er viktig fordi automatiske kodeskannere bare finner de vanligste feilene, ikke de som oppstår på grunn av problemfeltet (domenet). Denne typen feil må utviklerne selv finne og fjerne.

Flytt feilene opp i kjeden

Oftedal rangerer feilene fra dem han foretrekker til dem han virkelig ikke synes noe om.

De beste feilene er de som oppdages på kompileringstidspunktet. De er enkle å fange opp. Neste kategori er de som fanges av automatiserte tester. Deretter feil som man finner ved manuell gjennomgang eller på automatisk vis. Så er det ren manuell feilfinning, som noen ifølge Oftedal kaller «erfaringsbasert feilfinning».

Men så blir det verre. Den neste kategorien er feil under kjøringen, som først oppdages når programvaren tas i bruk. Det neste er kjørefeil som også er sårbarheter. Og så er det sårbarheter som blir utnyttet. Og det aller verste er sårbarheter som bare opptrer periodisk.

Oftedals strategi er å flytte feilene opp i kjeden, slik at alvorlige feil kan bli til enkle feil.

Han tar til orde for tilnærmingen domenedrevet design (DDD), som det er mye snakk om på utviklerkonferanser for tiden. Det er imidlertid en gammel kjenning: Målet er å modellere koden ut fra problemfeltet. Den tilnærmingen brukes ofte i objektorientert programmering, og sånn har det vært lenge. Domain Driven Design er også tittelen på en bok fra 2003 som kommer med en rekke tips.

Oftedal kaller det domenedrevet sikkerhet når ideene i DDD brukes på sikkerhetsområdet. Som eksempel nevner han en vanlig forretningsapplikasjon, der data hentes fra en database, puttes inn i en mal og vises som HTML for sluttbrukere. Poenget hans er:

– Samme data har mange ulike representasjoner.

Data kan eksistere som en rad i en database eller som et resultat fra et søk. Eller som et objekt på serversiden som en JSON-streng, samt mange ulike representasjoner i HTML. Et brukerobjekt kan være en side der man kan redigere profilen sin, eller en avatar i hjørnet av siden – mange ulike ting, men i prinsippet de samme dataene.

Pass på når data skifter representasjon

Ett sted der man ofte støter på sårbarheter, er når data skifter representasjon. Det kan skje når man for eksempel skifter fra JSON til et objekt på serversiden. Det kan være i forbindelse med deserialisering, der en strøm av bytes omskapes til et objekt – et område der sårbarheter ofte opptrer. Det var for eksempel årsaken til en lekkasje der personopplysningene til 143 millioner amerikanske forbrukere ble stjålet.

Med klassiske dyder, som modellering av inndata i problemfeltet, vil Erlend Oftedal gjøre det enklere å finne og rette sikkerhetsfeil. Han presenterte et innlegg om emnet på konferansen Øredev, som fant sted i Malmö tidligere i måneden. Foto: Tania Andersen
Med klassiske dyder, som modellering av inndata i problemfeltet, vil Erlend Oftedal gjøre det enklere å finne og rette sikkerhetsfeil. Han presenterte et innlegg om emnet på konferansen Øredev, som fant sted i Malmö tidligere i måneden.

Når man går fra serverside-objekter til SQL, er det fare for SQL-injeksjoner. Derfor er det viktig å være oppmerksom på slike datatransformasjoner. Første skritt er å sjekke gyldigheten av inndata fra brukere. Oftedal mener at målet må være at inndata er gyldige for problemfeltet. Det må også sjekkes at inndataene gir mening, også i forhold til de dataene man har fra før. Et ID-nummer må for eksempel matche det man har i databasen.

Da nytter det ikke å bare se på syntaks, for fire sifre gir ikke nødvendigvis et fornuftig årstall. Situasjonen kan lett bli mer innviklet. Hvis brukerne skal kunne skrive fritekst i et kommentarfelt, blir det mer komplisert. Og på et nettsted som Stack Overflow må brukere kunne skrive kode i innlegg – noe som kan være farlig. Man må holde øye med syntaks og sørge for at koden ikke kan kjøres.

Rådet fra Oftedal er at man ikke forsøker å rense inndataene. Hvis inndata er feil, bør man forkaste alt sammen. Sjekk av gyldighet krever at data normaliseres og at lengden sjekkes. Deretter sjekkes dataformat eller syntaks. Så kommer den semantiske sjekken av at inndata gir mening, og her må man bruke de normaliserte og gyldige verdiene – ikke de rå.

Objektorienteringens klassiske bud

Dette var bare inndata. Men domenedrevet sikkerhet handler om mye mer. Vi bruker strenger til alt i programmering. Det kan gå galt, noe det gjorde i MacOS, der passord og passordtips ble byttet om – slik at innloggingsdialogen skrev passordet i brukerflaten. Det kan gå galt hvis både e-postadresse, passord og telefonnummer representeres som strenger i koden.

For en streng kan være tom eller være på to gigabyte, og de tre nevnte konseptene er helt ulike ting, med ulik syntaks. I stedet bør man følge objektorienteringens klassiske bud om å kapsle inn de ulike konseptene i hver sin klasse – som kalles «domeneprimitiver». Da blir det vanskeligere å bytte på passord og passord-tips, for eksempel som parametre i et funksjonskall. Inne i klassen kan man sjekke gyldigheten av e-post, telefonnummer og så videre når objektet opprettes. Da vet man at verdien er gyldig.

Oftedal advarer mot redskaper som Ruby-on-Rails-aktige verktøy og objekt-relasjonsdatabase-broer (ORM), der utviklerne uforvarende kan skape grensesnitt til hemmelige felt i databasen, som med dagens enkle verktøy kan ende som en lekkasje et sted i HTML-suppen som blir sendt til klienten.

Kontrakt-objekter redder dagen

Løsningen er data transfer-objekter (DTO), også kalt kontraktobjekter, som med kode spesifiserer hvilke data som skal eksponeres fra datalaget til forretningslogikken. Det samme gjelder fra brukersiden, hvis en angriper for eksempel legger til et ekstra felt i HTML-kallet. Feltet finnes ikke i kontraktobjektet, og derfor blir verdien kastet ut med det samme.

Når det gjelder moderne, grafbaserte datagrensesnitt som Graphql, der utviklerne har adgang til alle slags data, kommenterer Oftedal:

– Når man lager grensesnittet til Graphql, må man sørge for at man ikke får en direkte representasjon av innholdet i databasen. I stedet må man tenke på hva man vil eksponere, og så sørge for at det bare er dette som sendes til Graphql. Men det krever at man tenker seg nøye om. For hvis man bare tar Graphql og dundrer i vei, får man et stort sikkerhetshull. Man kan tråle gjennom grafer og komme fram til objekter og data man ikke bør ha adgang til, i motsetning til å ha et API som sier at du kan få adgang til akkurat disse feltene.

Men det er ikke nok å holde øye med inndata. Ved alle former for injeksjonsangrep, som SQL-injeksjon eller cross site scripting (XSS), er poenget at data ikke fortsetter å være data. Plutselig er de en del av HTML-en eller et SQL-uttrykk. Løsningen er for eksempel å bruke «prepared statements» i datalaget, og på tilsvarende måte inneholder Javascript-biblioteket React tiltak mot XSS i klient-laget.

Denne artikkelen ble først publisert på Version 2 for deres abonnenter. Den er tilgjengelig på norsk for abonnenter av Ekstra gjennom vår samarbeidsavtale.

Powered by Labrador CMS