Denne RQ-170 Sentinel dronen ble angivelig tatt av Iran gjennom at man lyktes å få tilgang til dens interne styrings- og navigasjonsprogramvare.

Verifisere og styrke sikkerheten i militære systemer

Sikker kodepraksis – ordentlig testet og verifisert – bidrar til å sikre påliteligheten og trygg bruk av militære systemer. Start fra bunnen av, med en kombinasjon av statisk og dynamisk analyse, enhets- og integrasjonstesting, samt kravsporbarhet.

Publisert Sist oppdatert

Denne artikkelen er 2 år eller eldre

Sikkerhetsbrister i militære systemer kan bli ødeleggende. Ett eksempel der dette fikk alvorlige konsekvenser var da en amerikansk UAV av typen RQ-170 ble fanget inn under en CIA-ledet operasjon i Iran i 2011. Ifølge Iran ble farkosten landet trygt av iranske cyberkrigsenheter som klarte å ta kontroll over den (se bildet over).

Overstyrte dronen
Det ble påstått at UAVen ble tatt ved å jamme dens satellitt- og landbaserte styresignaler, fulgt opp med et GPS ”Spoofing” angrep som fôret UAVen med falske GPS-data, slik at den til slutt landet i Iran – på det stedet dronen trodde var hjemmebasen i Afghanistan. Vi kommer kanskje aldri til å få vite alle detaljene i denne saken, men det virker som dronen ble villedet i en slik grad at den kunne landes trygt på iransk territorium og overlevert i hendene på fienden for mulig konstruksjonsgransking. Ett eller annet i programvaren til denne dronen kunne tillate et sikkerhetsbrudd i minst én del av systemet, hvilket tilsynelatende  åpnet tilgang til dens vitale komponenter.

Innvevde systemer
Innvevde systemer gjennomsyrer nå militæret i alt fra kjøretøystyring, kommunikasjon, våpenstyring og veiledningssystemer, til autonome og halvautonome systemer, inkludert UAV og andre ting. Disse enhetene er nå forbundet med hverandre for styrings- og koordineringsformål. Med tanke på sikkerhet for personellet, evne til å fullføre oppdraget, og ofte med hensyn til nasjonal sikkerhet, må disse enhetene være trygge for brukerne og pålitelige i bruk. I tillegg er det essensielt at det er sikre mot uautorisert tilgang og –angrep. Dersom de ikke er sikre, kan de betraktes verken som trygge eller pålitelige. Derfor er kravene til trygghet, pålitelighet og sikkerhet uatskillelige og gjensidig avhengige.  

Start fra bunnen
Slike krav kan ikke stilles i ettertid, men må bygges opp fra grunnen av. De krever også ofte at programvaren forholder seg til gitte retningslinjer, slik som MISRA eller CERT C, så vel som at de følger industrielle eller myndighetssatte standarder, som DO-178C. Ettersom disse systemene i økende grad blir gjenstand for sertifiseringskrav,  må korrekt koding og funksjonalitet etterprøves og dokumenteres. 

Korrekt koding
Til tross for det faktum at det fins mange metoder for å implementere sikkerhet, vil det fortsatt være nødvendig å sikre at disse også er korrekt kodet – både når det gjelder kodestandarder og korrekt funksjonalitet i hele applikasjonen. 

Kritisk kommunikasjon
Overføringsprotokoller som transport layer security (TSL) – som er en forbedring i forhold til secure sockets layer (SSL), secure file transfer protocol (SFTP) og andre protokoller – er i utstrakt bruk, men ofte kjøpt inn utenfra organisasjonen. Andre strategier omfatter bruk av sikre enhetsdrivere. Dette er metoder for fjernstyrt implementering av sikre og krypterte fastvareoppgraderinger, og personlige verifiseringsmetoder som et passord, retinaskanning og RFID-brikker for å sikre tilgangen. Andre lagvise sikkerhetsmetoder tillater kun utvalgt tilgang til deler av systemet. Men bruk av disse – enten ved å importere dem eller skrive dem fra scratch – kan også introdusere feil som kan utnyttes dersom de ikke blir detektert. Du må være sikker på at din smarte sikkerhetsstrategi faktisk virker som planlagt.

Umulig manuell oppgave
Tidligere kunne mange virksomheter ha muligheten for å sjekke koden med manuelle koderevisjoner og gjennomganger av programvare. Men størrelsen og kompleksiteten på dagens kritiske programmer gjør det umulig å sikre fullstendig analyse med slike metoder og midler. Vi må støtte oss til automatiserte verktøy for å teste for så mange forventede og uventede tilstander som mulig, og fange opp underliggende kodefeil som kan forårsake feilfunksjon eller åpne for usikker tilgang. Dette går langt utover evnene til selv de beste debuggerne eller koderevisjonskomitéene. Det trengs et helt nytt arsenal av test- og analyseverktøy og –metoder for å møte dagens sikkerhetskrav.

Etablere og styrke sikkerhet
Dagens omfattende verktøysett integrerer verktøy for testing, analyse og verifikasjon i ett, enkelt utviklingsmiljø. Bruk av dette verktøymiljøet kan også bidra til å etablere en disiplinert metode innen en organisasjon, som kan hjelpe teamene å koordinere seg, uavhengig av om de arbeider på forskjellige steder. Eksempelvis kan implementeringen av en kodestandard spores og verifiseres med statiske analyseverktøy, for å sikre en enhetlig kodemetodikk gjennom hele virksomheten.

Sporing av krav
For å kunne møte sertifiserings- eller kvalifiseringskrav,  kan verktøy som tillater toveis kravsporbarhet – fra kravspesifikasjon til design, implementering og verifikasjonsaktiviteter og –gjenstander – differensiere en organisasjon fra konkurrentene, og sikre den raskeste veien til godkjenning av enheten. Selv om din prosess og resulterende kode ikke nødvendigvis trenger å møte strenge sertifiseringskrav, vil kravsporbarhet og –håndtering forbedre kodekvaliteten og samlet trygghet, sikkerhet og effektivitet for applikasjonen. Et kravhåndteringsverktøy lar teamene arbeide med individuelle aktiviteter, linkkode og verifikasjonsartifakter, tilbake til høyere mål. 

Sporbart – begge veier

Figur 2: Et kravsporingverktøy er essensielt for dynamisk testing og dekningsanalyse, og kan være til stor hjelp for å identifisere områder med død kode.

Toveis sporbarhet, basert på et kravdokument, er nødvendig for å sikre at et hvert  høynivå krav er dekket av ett eller flere lavnivå krav, og at alle lavnivå krav kan spores tilbake til et høynivå krav. Du må kunne være i stand til å spore fra alle krav, ned til kildekoden som implementerer det kravet, og tilsvarende for å kunne spore fra kildekoden og tilbake til et krav (Figur 2).

Utover det trengs verktøyene også for å utføre omfattende grunntester som er basert på statisk analyse, dynamisk dekningsanalyse og enhets-/integrasjonstesting. Dette bidrar til å sikre både sikkerhet og funksjonell trygghet og samsvar med kodestandarder, så vel som muligheten til å spore krav og se at de faktisk fungerer som forventet, gjennom omfattende testing.

Statisk og dynamisk analyse: Partnere i sikkerhet

Figur 3: Mulighetene for dynamisk analyse i LDRAs verktøysett, produserer rapporter om bruk av variabler og parametere som er basert på den aktuelle testkjøringen. Rapporten vil fremheve filen og plasseringen i filen der variabelen ble brukt, med kundespesifiserte filtre som tillater mer raffinert testing.

For å verifisere sikkerheten, må man først og fremst tenke på data og kontroll. Spørsmål som må tas i betraktning inkluderer: “Hvem har tilgang til hvilke data? Hvem kan lese fra den og hvem kan skrive til den? Hva slags data flyter til og fra hvilke entiteter, og hvordan kan tilgang påvirke kontrollen?” Her kan “hvem” referere til personer som utviklere og operatører — og hackere — men det kan også referere til programvarekomponenter enten i applikasjonen eller som befinner seg ett eller annet sted i en nettverkstilkoplet arkitektur. For å kunne håndtere disse utfordringene, må statisk og dynamisk analyse gå hånd i hand.

Statisk analyse

Når det gjelder statisk analyse arbeider verktøyene med den ukompilerte kildekoden, for å sjekke koden mot de valgte reglene, som kan være en kombinasjon av standarder som støttes, så vel som eventuelle kundespesifiserte regler og krav som utvikleren eller et selskap kan ha spesifisert. Verktøyene kan også se etter programvarekonstruksjoner som kan kompromittere sikkerheten, eller sjekke minnebeskyttelsen for å bestemme hvem som har tilgang til hvilket minne, og for å spore pekere som kan komme til å krysse en minnelokasjon. Resultatene bør ideelt sett presenteres på grafiske skjermer, for enkelt å kunne vurderes for å sikre samsvar med kodestandarder (Figur 3).

Dynamisk analyse

På den annen side brukes dynamisk analyse til å teste den kompilerte koden, som er linket tilbake til kildekoden ved bruk av den symboliske koden som er generert av kompilatoren. Dynamisk analyse, og spesielt analyse av kodedekning, krever omfattende testing. Ofte må utviklerne være i stand til å kunne generere og håndtere manuell kode for sine egne testcaser. Dette er den vanlige måten å generere testcaser – basert på et kravdokument. OG de vil kanskje stimulere og studere deler av applikasjonen med varierende grad av effektivitet. Men sett på bakgrunn av størrelsen og kompleksiteten av dagens kode, vil dette ikke være tilstrekkelig for å oppnå visse påkrevde sertifiseringer (Figur 3).

Funksjonelle sårbarheter

Sikkerheten krever streng og nøyaktig testing for funksjonelle sårbarheter, så vel som for etterfølgelse av kodereglene og direktivene for den aktuelle applikasjonen. Dersom dekningsanalysen inkluderer deklarerings- eller bransje/-beslutningsdekning, eller i mer regulerte miljøer, modifisert tilstands-/beslutningsdekning (MC/DC), kan dette ofte kreve både kilde- og objektkodeanalyse. Det vil sannsynligvis også kreve automatisert testgenerering, så vel som en metode for å måle effektiviteten av testingen.

Testgenerering

Figur 4: Kostnadene ved å fikse feil øker dramatisk jo senere i utviklingssyklusen de blir håndtert.

Automatisk testgenerering er basert på den statiske analysen av koden, og benytter denne informasjonen til å bestemme passende stimuli for programvarekomponentene i applikasjonen under dynamisk analyse. Dette danner en ryggrad for grunnleggende testing av grenseverdier, som enkelt kan utvides med funksjonelle tester, laget manuelt basert på kravdokumentet. Disse bør inkludere alle tester av funksjonell sikkerhet, slik som simulerte forsøk på å få tilgang til kontroll over en enhet,  eller mate den med uriktige data som vil kunne endre dens oppgave. I tillegg bør funksjonell testing basert på manuelt skapte tester inkludere robusthet, slik som testing for resultater av ikke-tillatte inndata og unormale tilstander.

Dypdykk i koden

Det å lete etter sikkerhetsbrister kan omfatte mer subtile problemer. For eksempel er det en viss fare tilknyttet områder med ”død” kode som kan aktiveres av en hacker eller obskure hendelser i systemet, for ondsinnede formål. Selv om den ideelle situasjon er å starte implementering av sikkerhet fra bunnen og opp, inneholder de fleste prosjekter gammel kode som kanskje ikke har vært gjenstand for den samme nitide testingen som det nåværende prosjektet. Disse kan inneholde segmenter som simpelthen ikke er nødvendige for applikasjonen under utvikling. Når de brukes sammen, kan statisk og dynamisk analyse avsløre områder med død kode som kan utgjøre en risiko, eller som bare tar opp plass. Det er nødvendig å identifisere slik kode på en ordentlig måte, og håndtere den – vanligvis ved å eliminere den.

Død – eller sjelden brukt

Evnen til å skille mellom helt død kode og kode som sjelden brukes er en annen årsak til at toveis sporbarhet av krav er viktig – å kunne kontrollere at kravene møtes av koden i applikasjonen, men også å kunne spore kode tilbake til faktiske krav fra den aktuelle koden. Dersom ingen av disse rutene har en forbindelse, hører koden definitivt ikke til der.

Dataflyt

Statisk analyse fungerer derfor til å analysere kildekode for passende programmeringspraksis, og bidrar også til å sette opp dynamisk analyse for dekningstesting, funksjonstesting og analyse av dataflyt. Sistnevnte er essensielt for å kunne fremheve og korrigere potensielle problemområder, og produsere mål for programvarekvalitet. Selskaper som driver med utvikling for å møte strenge sikkerhetskrav i luftbårne- eller kampsystemer kan være pålagt å demonstrere analyser av dataflyt for programvaresertifisering. Når det gjelder DO-178C, kreves det verifikasjon på objektnivå. Dette involverer muligheten for å relatere kodedekning på kildekodenivå med den som oppnås på objektkodenivå. I noen tilfeller kan det også være nødvendig å ivareta mekanismer for å kunne utvide kodedekningen på assemblernivå. Dette kan være spesielt til hjelp for sertifisering på DO-178C Level A, der en programvarefeil kan resultere i tap av flymaskin og/eller tap av liv.

Start med enhetstesting

Det å tenke på og utvikle for sikkerhet fra bunnen av hjelper ikke mye hvis du ikke også kan teste fra bunnen og opp – og det inkluderer testing på et utviklingssystem (vert) før den faktiske maskinvaren er tilgjengelig. På dette stadiet er det ingen som snakker om et prosjekt som nærmer seg fullføring, så det må være mulig å gjøre tidlig enhetstesting og deretter integrasjonstesting etter hvert som de ulike oppgavene samles inn fra forskjellige team eller utviklere.

”Gammel” kode

Dette gjelder også for deler av kode, som kan være skrevet enten fra scratch, hentet inn fra andre prosjekter, kjøpt inn som kommersielle produkter, eller tatt inn som åpen kildekode. Selv egenutviklet kode må sjekkes, ettersom den opprinnelig kanskje ikke er blitt underlagt den samme analysen, eller det kan være noen interne segmenter som må elimineres, modifiseres eller legges til. For eksempel kan det være nødvendig å endre navn på enkelte variabler, for at de skal samsvare med de som brukes i større prosjekter. Alt dette kan være potensielle arenaer for å introdusere feil. Beslutningen om å anvende verktøy for enhetstesting koker ned til en kommersiell beslutning. Jo senere en defekt blir funnet under produktutviklingen, desto mer kostbar er den å rette opp (Figur 4).

Automatisert test

Funksjonell testing på verten kan gjøres uten hensyn til maskinvaretiming, og i noen tilfeller på et vertsbasert virtuelt mål med simulerte tilkoplete periferikretser. De samme testene som eksekveres på verten må også eksekveres på mål-maskinvaren, for å sikre skikkelig funksjonstesting. I stedet for at utviklere skriver kode for testoppsett, vektorer og stubs (og deretter måtte håndtere alle disse både på vertsplattformen, med simulatorer og på målet), kan enhetstesting og måltestingsverktøy spare både tid og hodepine ved å gjøre dette automatisk.

Mindre smertefull prosess

Å implementere et omfattende rammeverk for test og analyse i utviklingsprosessen i en organisasjon vil forbedre grundigheten og nøyaktigheten i sikkerhetstiltakene for å beskytte vitale systemer. Det bidrar også til en mer elegant gjennomføring av det som ofte kan være en smertefull innsats for teamene, med tanke på å jobbe sammen for felles mål og å ha tro på det endelige produktet deres.

 

Powered by Labrador CMS