Fagartikkel: Hvordan gjøre et tilkoplet system trygt og sikkert?

Det å vite forskjellen mellom trygghet og sikkerhet er første steg mot et effektivt, innvevd systemdesign i en tilkoplet verden.

Publisert Sist oppdatert

Denne artikkelen er 2 år eller eldre

Vi har ofte brukt ”sikkerhet” i betydning av både ”trygghet” og ”sikkerhet”. I forbindelse med utvikling av kritiske applikasjoner bør vi kanskje skille mellom de to.

God, innvevd programvare har alltid vært designet med tanke på både trygghet og sikkerhet. Men utvidet tilkopling til nettverk har introdusert et uholdbart sårbarhetsnivå når det gjelder sikkerhet i trygghetskritiske applikasjoner, som medisin, autonome kjøretøy og enheter i Tingenes Internett (IoT).

Den nære sammenhengen mellom trygghet og sikkerhet, kombinert med økende trusselnivå, krever at utviklerne fullt ut forstår forskjellen, og anvender industriens beste praksis for å sikre at begge deler er designet inn i produktet – helt fra starten (Figur 1).

Figur 1: Godt programvare- og maskinvaredesign forutsetter at en rekke lag med kvalitetssikring og beskyttelse må implementeres gjennom hele designprosessen. 

Figur 1: Godt programvare- og maskinvaredesign forutsetter at en rekke lag med kvalitetssikring og beskyttelse må implementeres gjennom hele designprosessen.

Følgene av dårlig design
Med IoT blir systemene nå sårbare for “action at a distance”, altså fjerntliggende trusler. En fersk sak omhandler nettverksmonterte sikkerhetskameraer fra Sony, som man fant hadde  bakdørskontoer1. Disse portene kunne utnyttes av hackere til å infisere systemet med skadelig botnet-programvare, og utføre flere angrep. Sony har senere utviklet et firmwaretillegg som brukerne kan laste ned for å stenge bakdøren, men mange tilfeller av kode- eller designfeil er uopprettelige og kan få katastrofale følger.

For å bevise dette, hacket to sikkerhetsforskere en bil mens den var i bevegelse, og tok over dashboardfunksjonene, styring, kraftoverføring og bremser.2 Datainnbruddet var ikke skadelig, men ble gjort med tillatelse fra sjåføren, for at forskerne skulle kunne demonstrere hvor lett det er å hacke nettverksforbindelsen. Ikke desto mindre ledet dette datainnbruddet til at 1,4 millioner kjøretøy ble tilbakekalt.

Selvfølgelig trenger ikke systemene være tilkoplet internett for å bli sårbare og ansett som utrygge: dårlig skrevet innvevd kode og dårlige designbeslutninger har allerede krevd sine ofre. Ta for eksempel tilfellet med Therac-25, en stråleterapimaskin lansert i 1983 for å behandle kreft.3 Den er nå blitt en anerkjent casestudie som handler om hva man IKKE skal gjøre når det gjelder systemdesign. En kombinasjon av programvarebugs, mangel på sperremekanismer i maskinvare, og generelt dårlige designvalg førte til dødelige stråledoser.

Man fant at de største synderne i tilfellet Therac-25 var:

  • Umoden og utilstrekkelig programvareutviklingsprosess (“ikke-testbar programvare”)
  • Ufullstendig pålitelighetsmodellering & feilmodusanalyse
  • Ingen (uavhengig) revisjon av kritisk programvare
  • Feilaktig gjenbruk av programvare fra eldre modeller

En av de viktigste feilmodusene involverte en 1-byte teller i en testrutine som jevnlig fløt over (overflow). Dersom en operatør ga manuell input til maskinen i det øyeblikket telleren fløt over,  ville den programvarebaserte, interne sperren som systemet brukte feile.

I juni 1996 forlot Ariane 5, Flight 501, sin planlagte kurs og selvdestruerte, fordi man hadde droppet overflow-sjekker for effektivitetens skyld. Da en variabel som inneholdt horisontal fart fløt over, fantes det ingen måte å detektere dette og reagere på riktig måte.

Likevel blir kritisk kode og sikkerhetssårbarheter fortsatt ikke sjekket. Tvert imot fant Barr Groups 2016 Embedded Systems Safety and Security Survey ut følgende om ingeniører som arbeider med prosjekter som er tilkoplet internett og kan drepe dersom de blir hacket:

  • 50% av dem bruker ikke kodestandarder
  • 17% gjennomfører aldri koderevisjoner
  • Kun 24% vurderer å gjøre koderevisjoner
  • Og mer en en tredel gjør ikke statisk analyse

Det å forstå den sanne betydningen av trygghet og sikkerhet er en god start på veien mot å bedre denne situasjonen.

Definisjon av trygghet og sikkerhet
De to uttrykkene trygghet og sikkerhet blir ofte forvekslet, og noen utviklere er av den misoppfatning at dersom de bare skriver god kode,  så vil den være både trygg og sikker. Men det er definitivt ikke tilfellet.

Et “trygt” system er et, som under normal drift i seg selv ikke forårsaker noen skade på brukeren eller andre. Et “trygghetskritisk” system er et system som kan forårsake skade eller død når det feiler. Designerens mål i dette tilfellet er å forsikre seg om – så langt mulig – at et system ikke stopper eller feiler.

På den andre siden dreier sikkerhet seg først og fremst om et produkt kan gjøre sine ressurser tilgjengelig for en autorisert bruker, samtidig som det beskytter mot uautorisert tilgang, som hackere. Disse ressursene omfatter interne eller dynamiske data, kode, intellektuell eiendom (IP), prosessorer og systemkontrollsentre, kommunikasjonsporter, minne og lagre med statiske data.

På dette tidspunkt burde det være klart at et system kan være sikkert, uten at det dermed er trygt: et farlig designet system kan være like sikkert som et trygt designet system. Imidlertid vil et usikkert system alltid være utrygt, ettersom det,  til tross for at det er funksjonelt trygt på utsiden, er sårbart for uautorisert tilgang og dermed kan gjøres utrygt når som helst. 

Design for trygghet og sikkerhet
Når det gjelder design for trygghet her det mange faktorer som må tas i betraktning,  som eksemplet med Therac-25 demonstrerte. Imidlertid kan designerne kun kontrollere sitt eget aspakt av designet, og fokus i denne artikkelen er på fastvare (firmware).

Et godt eksempel på en oppgavekritisk applikasjon er bilen, som kan ha opp mot 100 millioner linjer med kode. Samtidig er den i hendene på i – mange tilfeller – dårlig trente eller distraherte brukere (sjåfører). For å kompensere for disse brukerne, legges det gjerne til enda flere trygghetsegenskaper og –kode, i form av kameraer, sensorer, kjøretøy-til-infrastruktur- (V2I) og kjøretøy-til-kjøretøy- (V2V) kommunikasjon. Kodemengden fortsetter å øke. Eksponensielt.

Samtidig som selve mengden av kode gjør koding og debugging av et system stadig vanskeligere, kan mye av debuggingstiden elimineres dersom man holder rede på noen kjernebegreper, som:

  • Maskinvare-/programvare-partisjonering som faktorer i sanntids ytelse, kostnad, oppgraderbarhet, sikkerhet, pålitelighet og trygghet
  • Implementering av feilbegrensende regioner
  • Unngå enkeltpunkter som kan feile (Figur 2)4
  • Håndtere unntak forårsaket av kodebugs, selve programmet, minnehåndtering eller tilfeldige avbrudd
  • Implementering av overflow sjekk (Therac-25 og Ariane-raketten)
  • Opprydding i korrupte data fra verden utenfor (bruk områdesjekk & CRC)
  • Testing på alle nivå (enhetstest, integrasjonstest, systemtest, fuzzing, verifikasjon og validering, blant andre

Figur 2. Trygghetskritiske systemer unngår enkeltpunkter som kan feile. (Kilde: Professor Phil Koopman4)

Når det gjelder sikkerhet, må en designer eller utvikler gjøre seg kjent med vanskelighetene knyttet til bruker- og enhetsautentisering, public key infrastructure (PKI), og datakryptering. I tillegg til å gjøre ressurser tilgjengelig til autoriserte brukere og beskytte dem fra uautorisert tilgang, betyr sikkerhet også at et system ikke gjør uventede eller utrygge ting i tilfelle et angrep eller feilfunksjon.

Selvsagt kommer angrep i forskjellige former, inkludert grunnleggende tjenestenekt (DoS) og distribuert DoS (DDoS). Selv om utviklerne ikke kan styre hva som angriper systemet, kan de styre hvordan systemet reagerer på angrepet, og at oppmerksomhet rundt hvordan det skal reageres må gjennomsyre hele systemet: et systemet er bare så sikkert som det svakeste ledd, og det er lurt å anta at en angriper vil finne det leddet.

Et eksempel på et utsatt svakt ledd er fastvareoppdatering, der enhetens Remote Firmware Update (RFU) funksjoner er aktivisert. Denne kan enkelt angripes, så det kan være greit å ha en strategi på plass, slik som: Gi brukeren valget mellom å enten deaktivere RFU, eller laste ned en oppdatering som krever påfølgende digital signering av bilder.

Det kan virke ulogisk, men kryptografi er sjelden det svakeste ledd. Angripere kan i stedet lete andre steder for angrepsflater som er gjort sårbare på grunn av selve implementeringen, protokollsikkerhet, API, bruk, og angrep via sidekanaler.

Hvor mye innsats, tid og ressurser som går inn i disse områdene avhenger av hva slags sikkerhetstrussel som er på tale, ettersom det er ulike forsvarsmekanismer for hver. Her er noen generelle tiltak en utvikler kan gjøre for å redusere produktsårbarheten:

  • Bruke en mikrokontroller uten eksterne minner
  • Deaktivere JTAG-grensesnittet
  • Implementere sikker oppstart
  • Bruke en masternøkkel til å generere hver enhets enhetsspesifikke nøkkel
  • Bruke objektkode-forvrengning, såkalt obfuscation
  • Implementere power-on, selvtest (POST) og innebygd selvtest (BIST)

Når vi snakker om “obfuscation,” så finnes det en idéretning som promoterer “sikkerhet gjennom obskuritet.” Denne tankegangen kan bokstavelig talt bli fatal dersom man utelukkende baserer seg på denne,  ettersom enhver hemmelighet skaper et potensielt feilpunkt.5 Før eller senere blir hemmeligheter avslørt, enten gjennom sosial utvikling, misfornøyde ansatte, eller gjennom teknologier som dumping og konstruksjonsgransking. Imidlertid har obskuriteten selvsagt en rolle, som å holde kryptografiske nøkler hemmelig. 

Å sikre trygghet og sikkerhet
Samtidig som det fins mange teknikker og teknologier som kan hjelpe utviklere og designere med å oppnå et høyt nivå av både trygghet og sikkerhet, er det noen grunnleggende steg som kan sikre at et system er optimalisert så langt det er mulig, innenfor rimelighetens grenser.

Det første er å designe i henhold til etablerte kode-, funksjonell sikkerhets- samt industri- og applikasjonsspesifikke standarder. Disse omfatter MISRA og MISRA-C, ISO 26262, Automotive Open System Architecture (Autosar), IEC 60335, og IEC 60730.

Det å ta i bruk en kodestandard som MISRA hjelper ikke bare å holde bugsene borte, men gjør også koden mer lesbar, konsistent, og portabel (Figur 3).

Figur 3: Fordelene ved å ta i bruk kodestandarder som MISRA går langt utover å holde programvarebugs fra livet: det gjør også koden mer lesbar, konsistent og portabel.

For det andre, bruk statisk analyse (Figur 4). Dette er analyse av programvare, uten å eksekvere programmet. Det er kun en symbolsk eksekvering, dvs. i prinsippet en simulering. I motsetning til dynamisk analyse, som avdekker defekter under kjøring av den aktuelle koden på en målenhet.

Figur 4: Verktøy for statisk analyse kjører en ”simulering” av kildefilen, analyserer for syntaks og logikk, og produserer advarsler i stedet for objektfiler.

Selv om statisk analyse ikke er noe mirakelmedisin, tilfører den imidlertid et ekstra sikkerhetslag  ettersom teknikken er meget god på å detektere potensielle bugs, som bruk av uinitialiserte variabler, mulige integer overflow/underflow, og blanding av signerte og usignerte datatyper. I tillegg blir verktøy for statisk analyse stadig bedre.

Vanligvis impliserer statisk analyse bruk av et dedikert verktøy, slik som PC-Lint eller Coverity, men utviklere bør også vurdere re-analyse av sin egen kode.

Figur 2. Trygghetskritiske systemer unngår enkeltpunkter som kan feile. (Kilde: Professor Phil Koopman4)

For det tredje, gjennomfør koderevisjoner. Dette vil forbedre riktigheten av kode, samtidig som det bidrar til vedlikeholdbarhet og utvidbarhet. Koderevisjoner kan også være til hjelp i tilfeller av tilbakekallelser/garantireparasjoner og produktansvarskrav.

Det fjerde steget er å gjøre trusselmodellering. Start med et ”angrepstre”. Dette krever at utvikleren tenker som en angriper, og begynner å:

  • Identifisere angrepsmål
    • Hvert angrep har et separat tre
    • For hvert tre (mål):
      • Bestem de ulike angrepene
      • Identifisere stegene og mulighetene for hvert angrep

Merk at denne type analyse drar stor nytte av å ha flere perspektiv.

Men hvem har tid til å gjøre det riktig?
Selv om det virker likefrem å gjøre disse grunnleggende, fire stegene for å minimalisere feil og forbedre trygghet og sikkerhet, så tar de tid. Så en utvikler må planlegge tilsvarende. Ettersom prosjektstørrelsene varierer, er det viktig å være så realistisk som mulig.

For eksempel bør du legge til mellom 15 og 50 prosent  til designtiden for koderevisjon. Noen systemer krever fullstendige kodegjennomganger, andre ikke. Statisk analyse-verktøy kan ta 10 til hundrevis av timer for det initielle oppsettet, men så snart det er en del av utviklingsprosessen, blir det ikke lagt ekstra tid til produktutviklingen, og det ender opp med å betale seg selv gjennom bedre systemer.

Tilkopling til nettverk har medført en ny bekymring for designere av innvevde systemer, som krever ekstra fokus på sikkerhet og trygghet. En god forståelse av disse to konseptene, kombinert med den riktige anvendelsen av beste praksis tidlig i designsyklusen, vil forbedre den totale tryggheten og sikkerheten i et produkt dramatisk. Disse ”beste praksis” omfatter: bruk av kodestandarder, bruk av statiske analyseverktøy, koderevisjoner, og trusselmodellering.

Referanser:
1: Backdoor accounts found in 80 Sony IP security camera models
http://www.pcworld.com/article/3147311/security/backdoor-accounts-found-in-80-sony-ip-security-camera-models.html

2: After Jeep Hack, Chrysler Recalls 1.4M Vehicles For Bug Fix
https://www.wired.com/2015/07/jeep-hack-chrysler-recalls-1-4m-vehicles-bug-fix/

3: Killed By A Machine: The Therac-25
http://hackaday.com/2015/10/26/killed-by-a-machine-the-therac-25/

4: A Case Study of Toyota Unintended Acceleration and Software Safety
https://users.ece.cmu.edu/~koopman/pubs/koopman14_toyota_ua_slides.pdf

5: Quote by Charles Mann, paraphrasing Bruce Schneier (Atlantic Monthly, Sept. 2002.)

Figur 3: Fordelene ved å ta i bruk kodestandarder som MISRA går langt utover å holde programvarebugs fra livet: det gjør også koden mer lesbar, konsistent og portabel.
Figur 4: Verktøy for statisk analyse kjører en ”simulering” av kildefilen, analyserer for syntaks og logikk, og produserer advarsler i stedet for objektfiler.
Powered by Labrador CMS