This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Utvikle

Det er ikke mulig å gi en oppskrift på hvordan man skriver sikker programkode i noen få, enkle og kortfattelige artikler. Det betyr derimot ikke at det er en uoverkommelig oppgave forbeholdt sikkerhetseksperter! Alle som utvikler programvare i Bouvet skal være kjent med OWASP Top 10, som er et godt utgangspunkt for å bli kjent med hvilke utfordinger man står ovenfor som utvikler.

Artikklene du finner under temaet Utvikle på denne siden vil fokusere på det som foregår på en utviklers arbeidsmaskin, som ikke er konkret kode. De vil ikke gå i dybden på konkrete angreps metoder eller hvordan beskytte mot disse. Du vil også finne råd om hvordan et team bør arbeide for å være i stand til å forebygge, identifisere, og fikse sårbar kode.

1 - Utviklingsmiljø, verktøy og byggmiljø

Miljøene og verktøyene vi jobber med er essensielle for prosjektet, og det er viktig at vi har kontroll på hvilke verktøy som brukes og hvordan disse konfigureres.

Utviklingsmiljøet og byggmiljøet er noe av det viktigste vi har i et utviklingsprosjekt, og er en avhengighet det er utrolig viktig at vi har kontroll på.

Det finnes mange ulike måter å forholde seg til disse miljøene; noen utvikler og bygger lokalt på egen laptop, mens andre bruker en kombinasjon av dedikerte utvikling- og byggmiljø - basert på skytjenester som Azure DevBox eller on-prem utviklingsservere.

Uavhengig av hvilken løsning en går for, er det noen viktige momenter som bør dokumenteres og vedlikeholdes - både for å ha et utgangspunkt som kan trusselmodelleres og valideres, men også for at nye teammedlemmer raskt kan onboardes og få et miljø som er “rett”.

Verktøy

Utviklere har ofte ulike preferanser rundt bruk av IDE og utvidelser, og mange har gjerne laget seg en arbeidsflyt som funker for dem. Husk på at alle verktøy må holdes oppdatert, og hvert nytt verktøy som introduseres øker angrepsflaten, spesielt når det kommer til bruk av utvidelser som eksempelvis fra Visual Studio Marketplace og liknende.

Utviklingsmiljø og byggmiljø

Et av de store risikoelementene ved all utvikling er dersom

  • uvedkommende kan nå en maskin der det foregår utvikling eller bygging på
  • maskinen kan nå internett uten særlige begrensninger
  • slike maskiner mangler monitorering

Alle utviklere som skriver kode idag har mange avhengigheter til biblioteker og pakker som hentes fra open-source økosystemer. De færreste av disse har noe forhold til sikkerhet, og som vi har sett gang på gang finnes det ondsinnede aktører som overtar slike komponenter eller lager sine egne kopier under liknende navn. Slike pakker representerer en kjemperisiko, da de kan introdusere bakdører som åpner opp for uvedkommende eller eksfiltrerer data fra maskinen til en ekstern mottaker.

Viktige tiltak for å ta ned risiko vil være å

  • stenge for all innkommende nettverkstrafikk
  • stenge for all utgående nettverkstrafikk
  • kun åpne opp for de tilgangene som absolutt trengs
  • unngå bruk av generelle maskiner som brukes til surfing på nett, kontoraktiviteter og liknende til utvikling

Det er klart at en ikke alltid kan forsvare å sette opp dedikerte maskiner som kun brukes til utvikling ut fra kost/nytte, men dette bør vurderes fra tilfelle til tilfelle for å sikre at en er kjent hvordan dette valget påvirker risikobildet i prosjektet.

Veien videre

2 - Hemmeligheter

Alle utviklingsprosjekter har behov for hemmeligheter som connection strings, identiteter, passord, sertifikater og annet. Disse må oppbevares på en trygg måte, og vi må sikre at vi bruker dem i en sikker kontekst med riktige støtteverktøy og prosesser.

Hemmeligheter er representert i utviklingsprosjekter i form av connection strings, passord, nøkler, sertifikater og alt annet som regnes som sensitiv informasjon vi ikke ønsker at andre skal få kjennskap til.

Det finnes mange ulike tilnærminger til hvordan disse skal håndteres, og dette har også endret seg etter hvert som nye tjenester dukker opp. For skyløsninger har tjenester som Azure Key Vault og liknende nærmest blitt en standard, da disse tjenestene håndterer flere aspekter av hvordan en bruker og forvalter hemmeligheter.

Grunnprinsipper for håndtering av hemmeligheter

  • Hemmeligheter skal aldri hardkodes eller sjekkes inn i versjonskontrollsystemer
  • Verifiser etterlevelse ved å skanne koden - avvis commits med hemmeligheter og roter disse øyeblikkelig!
  • Ha kontroll på hvilke hemmeligheter du har og hvilke tilganger disse har
  • Begrens levetiden på hemmelighetene - ingen hemmeligheter bør leve mer enn et år, passord og nøkler mye kortere
  • Teammedlemmer bør ikke ha tilgang til alle hemmeligheter alltid, elever eller legg på tilgang ved behov

Kryptografi og hashing

Kryptografi og hashalgoritmer er komplekse tema, og det krever store ressurser og mye kompetanse for å bygge gode algoritmer som er sikre. Av denne enkle grunn skal du aldri lage egne, uansett hvor finurlig og sikker den ser ut til å være.

Det du derimot skal gjøre, er å:

  • Sette deg inn i best-practices for ditt programmeringsspråk, rammeverk og plattform
  • Sikre at du ikke bruker sårbare algoritmer som f.eks. SHA1, MD5 eller DES
  • For kryptografi; sett deg inn i hvilke anbefalinger som gjelder for nøkkellengder og anbefalinger ift bruk
Husk

Hemmeligheter skal aldri sjekkes inn i kildekodesystemet!

Veien videre

3 - Datavalidering fra andre systemer

Data er en angrepsvektor, du må aldri stole blindt på at disse er trygge uavhengig av kilde!

Dersom du henter data fra andre systemer bør du aldri stole blindt på disse. OWASP Top 10 har hatt ulike former for sårbarheter relatert til kodeinjeksjon på de øverste punktene sine siden den første lista kom i 2004.

Uavhengig av hvor dataene kommer fra, skal du alltid behandle disse på linje med brukerinput fra et sikkerhetsperspektiv. Sjekk at du får det du forventer, og dersom du henter inn filer må disse skannes for malware før du behandler dem videre. Vurder også behovet for bruk av sandbox-miljø for å prosessere slike filer, slik at skadepotensialet begrenses.

Sett deg inn i trusselbildet for filtypene som er relevante, eksempelvis er det fullt mulig å embedde malware i et bilde; dersom dette ikke mitigeres vil applikasjonen kunne være sårbar mot denne trusselen. Andre filformater medfører andre typer trusler som krever andre tiltak.

Vurder også bruk av Content Security Policies for å unngå at data som hentes fra andre systemer men presenteres til kunden kan resultere i et vellykket XSS-angrep.

4 - Sikkerhetspraksiser

Det er mye å tenke på dersom en skal bygge en sikker løsning, og et viktig utgangspunkt er OWASP Top 10.

Det finnes mange ulike typer sårbarheter og svakheter vi må forholde oss til når vi utvikler nye applikasjoner. Organisasjonen Open Worldwide Application Security Project har siden 2004 gitt ut en liste med de 10 mest vanlige typer sårbarheter, primært rettet mot webapplikasjoner. Selv om denne ikke inneholder alt, brukes den ofte som et utgangspunkt for sårbarheter som må håndteres i utviklingsprosjekter.

Gjeldende punkter på OWASP Top 10:

  1. Broken Access Control
  2. Cryptographic Failures
  3. Injection
  4. Insecure Design
  5. Security Misconfiguration
  6. Vulnerable and Outdated Components
  7. Identification and Authentication Failures
  8. Software and Data Integrity Failures
  9. Security Logging and Monitoring Failures
  10. Server-Side Request Forgery

Dersom teamet ikke har noen prosesser rundt sikker utvikling, vil dette være en god start. For team med større modenhet innenfor applikasjonssikkerhet vil andre sjekklister, som Application Security Verification Standard - også fra OWASP være et videre alternativ. Denne er delt opp i tre ulike nivå, der nivå 1 dekker hovedpunktene, mens level 3 går mye mer i dybden og krever mer kompetanse og støtteverktøy.

OWASP publiserer mye annet i tillegg, både andre Top 10-lister i tillegg til det de kaller "Cheatsheets"; detaljert informasjon om spesifikke sikkerhetsrelaterte tema.

Veien videre

5 - Software supply chain

Alle som lager programvare bruker tredjepartspakker. Alle tredjepartspakker representerer kode skrevet av andre, og utgjør en risiko for leveransen dersom vi ikke har kontroll over hva vi bruker og oversikt over svakheter og risiko assosiert med disse.

Når vi bygger software har vi avhengigheter til en hel haug med ulike tredjepartspakker, fra økosystem som npmjs, nuget, PyPi eller andre. Dette er kode “skrevet av andre”, der vi er avhengige av at disse produserer pakker uten større svakheter og uten onde hensikter. Kilder som blant annet Gartner, Sonatype og Snyk har anslått at så mye som 90% av koden i et typisk utviklingsprosjekt kan bestå av slike tredjepartspakker, så risikoen er betydelig dersom vi ikke har kontroll.

Et viktig hjelpemiddel er å gjennomføre en såkalt Source Composition Analysis - SCA for å få oversikt over pakkene vi bruker, både direkte og indirekte (transiente) avhengigheter, samt risikoen assosiert med disse.

Sikkerhetsrisiko

Det finnes flere sikkerhetsrisikoer knyttet til tredjepartspakker, men dessverre er økosystemene for slike pakker lite proaktive på sikkerhetsfronten. Infiserte pakker som identifiseres blir fjernet, men for alle som bruker automatikk for å holde avhengigheter oppdatert til siste versjon kan dette ofte være for sent.

Sårbarheter

De kan inneholde kjente sårbarheter (CVE) som kan la seg utnytte. Noen av disse kan mitigeres ved å oppgradere pakkene til siste versjon, andre har mer grunnleggende utfordringer som kan mitigeres på annet vis. Det hender også at noen CVE’er lages på svakheter som teknisk sett er en sårbarhet, men der den er ‘by-design’. Et eksempel på dette er Python-pakken Pandas som blant annet har sårbarheten CVE-2020-13091. Denne lar brukeren deserialisere filer uten sjekk av hvor disse kommer fra - dette har da blitt registrert som en sårbarhet da det vil kunne være mulig utnytte dette om andre tiltak ikke er på plass.

Ondsinnet kode

Pakkene vi laster ned og bruker kjøres i samme kontekst som vår kode og kan benytte de samme ressursene og tilgangene den har. Innholdet i pakkene vi konsumerer er helt utenfor vår kontroll, og dersom en av dem inneholder ondsinnet programvare (malware) kan konsekvensene bli store.

De siste årene har det også dukket opp eksempler på pakker som ofte betegnes som “protestware”, da de inneholder logikk som utfører handlinger dersom brukerne kan geolokaliseres til spesifikke land. Pakken “peacenotwar” er et slikt eksempel, som ble lagt til som en avhengighet til node-ipc som er en mye brukt pakke. Dette resulterte i at peacenotwar også ble lastet ned hos mange brukere; de som ble geolokalisert til Russland eller Belarus fikk data slettet og ble utsatt for DOS-angrep via pakken.

Uavhengig av om noe er ment som malware eller protestware er konsekvensene alvorlige, og alle utviklingsprosjekter bør ha på plass tiltak for å begrense risiko og konsekvens dersom en hendelse inntreffer.

Bruk av CDN

Content-delivery-networks for å distribuere Javascript-bibliotek har blitt brukt av mange som en enkel måte å inkludere disse i koden uten å måtte inkludere dette i build eller deploy-prosessen. Tanken er god, men du får da en direkte avhengighet til en kilde du ikke har noen kontroll på som kan misbrukes til å spre malware.

Lisensmodell

Det finnes mange ulike lisensmodeller; noen er helt frie og får ingen konsekvenser for brukerne, mens andre som AGPL og GPL stiller klare krav til alle som konsumerer kode under denne lisensen, også inkludert det øvrige systemet som benytter seg av den. De aller fleste økosystemer tillater også bruk av proprietære lisenser, som kan begrense hva du kan bruke en pakke til. Noen har spesifikke krav i lisensen, andre er gratis for personlig bruk, men krever at du kjøper en lisens dersom den skal brukes kommersielt.

Hvordan sikrer vi oss?

For å beskytte systemet mot disse truslene er det flere effektive tiltak vi kan gjøre. Mange av disse er allerede dekket andre steder, men det er likevel noen som er unike for eksterne pakker.

Trusselmodell og kompleksitet

I mange tilfeller har vi avhengigheter til mange pakker som ikke brukes av oss direkte, såkalte transitive avhengigheter. Hver enkelt pakke vi avhenger av representerer en økning i kompleksitet og angrepsflate, og øker sjansen for at noe skjærer seg på et senere tidspunkt.

dependencies

Et viktig spørsmål alle må stille seg er “trenger vi denne pakken?” Hva er kosten ved å lage funksjonaliteten selv sammenliknet med risikoen og kompleksiteten assosiert med å legge den til?

Overvåkning av avhengigheter

Et viktig hjelpemiddel er analyseverktøy som hjelper oss å ha kontroll på sårbarheter og risiko i avhengighetene våre. Det finnes mange aktører på markedet, alt i fra helt enkle som Githubs Advanced Security med Dependabot, til mer avanserte som Snyk og Sonatype. I mange tilfeller er det datagrunnlaget for løsningen som utgjør den store forskjellen, men det finnes også en del nyttige funksjoner en bør vurdere:

  • Policystyring - Sonatype tagger alle pakker med metadata, slik at du kan definere policyer som sier noe om hva som kan brukes eller ei.
  • Automatisk utbedring - Verktøy som dependabot (Github) oppgraderer automatisk pakker når sårbarheter oppdages og oppdateringer er tilgjengelige.
  • Integrasjoner og varsling - Mange verktøy som eksempelvis Snyk SCA kan integreres i IDE og i CICD.
  • Risikobilde - Mange løsninger gir deg en totaloversikt der du kan se det totale risikobildet for enkeltapplikasjoner eller større deler av porteføljen

Modenhet

Denne kan være vanskelig å si noe konkret om, men hvor aktivt er miljøet rundt en pakke? Vedlikeholdes den av enkeltpersoner, grupper med utviklere eller har den økonomisk eller annen støtte fra et selskap?

Hvor sannsynlig er det at pakken fortsatt kommer til å være vedlikeholdt om eksempelvis 5 år? Hvordan er historikken i forhold til sårbarheter og kvalitet; finnes det et aktivt miljø som rapporterer svakheter som deretter utbedres, eller henger innmeldte saker i limbo over lengre tid? Verktøy som libraries.io og Security Scorecard kan være nyttige for å finne ut mer.

Pinning av versjoner

En av angrepsvektorene er når ondsinnede aktører overtar populære pakker, og publiserer sin egen versjon med ondsinnet innhold. Dersom vi har bygg eller deployprosesser som henter siste versjon av avhengighetene hver gang, vil disse automatisk hente den infiserte pakken. Et tiltak her kan være å låse pakkeversjonene vi bruker, eksempelvis i package-lock.json eller liknende.

Bruk av SBOM

Software Bill Of Materials (SBOM) er en tilnærming der vi genererer en oversikt over alle avhengigheter med versjoner fra løsningene våre. Det finnes flere mer eller mindre standardiserte filformater for dette, disse kan også arkiveres eller legges inn i andre løsninger for å forenkle monitorering fra sentralt hold.

Veien videre

6 - Sikkerhetstesting

På linje med annen elementer assosiert med teamet kvalitet er vi avhengige av å kunne teste for å verifisere at vi har oppnådd målet. Sikkerhetstesting er et viktig ledd i dette, da vi gjennom testingen kan vise at leveransen ikke er sårbar for gitte angrepsmetoder.

Sikkerhetstesting bør alltid være et element av alle leveranser. Mange assosierer sikkerhetstesting med penetrasjonstesting, men det er mye mer enn dette. Noen former for testing kan gjøres automatisk som del av CICD, andre er mer manuelle og skjer typisk mot en deployert løsning.

Før en setter i gang med sikkerhetstesting er det viktig å sette seg inn i hva dette kan gi deg - det finnes ingen enkelttiltak som løser alle sikkerhetsproblemer, og heller ingen enkelt testmetode som avdekker alle svakheter. Sikkerhetstesting er også et av områdene som ofte krever spesifikk kompetanse for at resultatene skal bli gode og/eller tolket korrekt.

Advarsel

Bruk av verktøy som `nmap` og annet som brukes i forbindelse med sikkerhetstesting må **alltid** avklares med eiere av infrastruktur og nettverk, da det er vanskelig å skille vennligsinnet testing fra ondsinnede angrep. Dette gjelder også internt i Bouvet; Intern-IT & Sikkerhet skal alltid være i loopen før du starter en sikkerhetstest! Dersom dette ikke tas hensyn til kan det få konsekvenser, både for kundeforholdet men også for tekniske løsninger mot nettleverandør og Microsoft.

Testmiljø

Når en skal bedrive sikkerhetstesting mot et kjørende miljø er det viktig at en alltid avklarer dette godt i forkant. Mange typer testing kan være destruktiv, så dersom miljøene ikke er godt nok adskilt kan en risikere å påvirke andre miljø enn tiltenkt.

En god løsning, spesielt dersom en bruker infrastruktur-som-kode (IAC) er å ha en pipeline som deployer et eget miljø som kan brukes for sikkerhetstesting. Dersom dette designes inn i leveransen fra starten, vil det ofte være enkelt å sette opp miljø som er identiske med produksjonsmiljøet, der en også kan kopiere databaser og eventuelt kjøre anonymiseringsprosesser mot dataene.

Statisk kodeanalyse (SAST)

Statisk kodeanalyse er et lavterskelteknikk som analyserer koden med avhengigheter for å finne svakheter. SAST kan gjennomføres helt automatisk, og det finnes mange gode verktøy som kan bygge dette inn i CICD slik at du kan skanne som en del av prosessene her.

SAST sjekker kun løsningen som lages, den avdekker ingenting rundt konfigurasjon av kjøremiljø, nettverk eller andre omkringliggende avhengigheter. Verktøy som brukes for å gjennomføre SAST er språkspesifikke, så det er viktig å sette seg inn i hvilke verktøy som gir best resultat for språk og eventuelt rammeverk som benyttes.

Dynamisk applikasjonssikkerhetstesting (DAST)

I motsetning til SAST er DAST en teknikk der en tester en løsning i kjørende tilstand. Dette er en språkagnostisk testmetode, der en eksempelvis tester en webapplikasjon gjennom å teste frontendløsningen for å finne svakheter. DAST kan automatisers, men må ofte kjøres manuelt for at enkelte typer svakheter skal testes.

DAST vil kun dekke funksjonalitet eksponert i den kjørende løsningen, så dersom en har kode som er en del av løsningen men som ikke er tilgjengelig for DAST-verktøyet vil dette heller ikke kunne testes.

Veien videre

7 - Dokumentasjon

Alle utviklingsprosjekter må dokumenteres. Dette er ikke bare viktig for kontinuiteten i prosjektet, men også for å dokumentere sikkerhetsrelaterte tiltak og eventuelle hendelser.

Dokumentasjon er ofte sett på som et nødvendig onde, og vi er ikke alltid gode nok til å dokumentere prosjektene våre. Mange mener at kildekoden er den beste dokumentasjonen, men denne sier kun hvordan en applikasjon fungerer, ikke nødvendigvis hvorfor den fungerer som den gjør, eller hva som er den egentlige intensjonen.

Det er mange årsaker til at vi må dokumentere løsningen vi bygger; den mest åpenbare er for å sikre at nye teammedlemmer kan få en forståelse av hva prosjektet går ut på og også for at informasjonen ikke bare skal leve i hodet til enkeltpersoner. Et annet viktig aspekt av dette er dokumentasjon av hensyn til sikkerheten i prosjektet. Dersom vi ikke dokumenterer hvilke tiltak som gjøres og hvorfor, eller hvilke trusler vi står ovenfor og hvordan vi håndterer dette legger vi et kjempestort ansvar på teammedlemmene som kommer etter: Det som for oss er en logisk og fornuftig løsning gitt en sikkerhetskontekst kan virke bakvendt og tungt for noen uten den samme konteksten og kompetansen, og vi risikerer da at viktige tiltak fjernes for å forenkle løsningen - på beskostning av sikkerheten.

Dokumentasjonsløsning

Prosjektet må finne en løsning for hvor dokumentasjon oppbevares som gir mening i prosjektet. Husk at god dokumentasjon er like sensitivt som kildekoden, og må behandles deretter. I mange tilfeller kan det være lurt med verktøy som støtter versjonskontroll - i mange tilfeller kan det være lurt å legge dokumentasjon sammen med kildekoden, eller evt i egne repos som kan brukes f.eks. med Azure DevOps wiki.

Hva skal dokumenteres

Hva vi bør dokumentere vil variere fra prosjekt til prosjekt. Vi bør alltid ha et design som gir et innblikk i eksempelvis infrastruktur, IAM og dataflyt slik at det er mulig å ettergå dette på senere tidspunkt.

Trusselmodell må alltid dokumenteres og vedlikeholdes, og eventuelle mitigerende tiltak må også dokumenteres.

OWASP Top 10 har flere punkter som kan relateres til utviklingsmiljøet og oppsettet av dette, så dersom det er spesielle konfigurasjoner som må på plass bør dette også dokumenteres, slik at en unngår svakheter eller sårbarheter som oppstår dersom noen glemmer viktige steg som ikke er skrevet ned.

En må også ta inn over seg kritikaliteten til løsningen; dersom det er et system som har 24/7-oppetidskrav og er kritisk for kunden må dokumentasjonen stå i stil med dette, slik at selv den minst erfarne personen i teamet kan feilsøke problemer uten å kjenne løsningen i detalj.

Veien videre

8 - Interne komponenter

Dersom teamet avhenger av interne komponenter som servere, applikasjoner eller annet som driftes av teamet selv, må en ha en rutine for å holde disse oppdatert.

Mange utviklingsteam gjør mer enn å skrive kode. Du har gjerne virtuelle maskiner i sky eller on-premise, med applikasjoner eller tjenester som brukes i leveransen hos kunden. Du drifter kanskje integrasjonsløsninger for kunden, containere, applikasjonsservere og mye annet.

Har dere en rutine for å holde disse oppdatert, og inngår de som en del av det øvrige sikkerhetsarbeidet?

Viktige huskeregler

Oppdateringer

Dersom dere drifter servere, tjenester eller andre assets innad i teamet må de holdes oppdatert. Dere må sette dere inn i rutinene for release av nye versjoner fra leverandørens side, slik at dere kan holde alt oppdatert. Det er ikke alltid en ønsker å gå for siste versjon hele tiden, så det er viktig å sette seg inn i release notes eller annen dokumentasjon rundt releasen for å forstå hvorfor den kom, og hva den løser.

Husk på at software vi bruker bør være supportert slik at vi unngår feil og problemer som følge av at en komponent ikke støtter siste versjon av en annen komponent.

Sikkerhetspraksiser

Alle komponenter vi bruker må inngå i det totale designet, og vi må ha kontroll på nettverksåpninger, IAM og hvordan disse er eksponert både internt og eksternt. Uten kjennskap til dette er det vanskelig å si noe om hvilke trusler en kan stå overnfor og dermed også mitigerende tiltak.

Husk på at sikkerheten i en løsning aldri skal avhenge av ett enkelt tiltak; forsøk derfor å isolere komponenter så mye som mulig. Som standard bør ingenting være lov - enten det gjelder tilgang på ressurser eller nettverk inn/ut, men åpne heller eksplisitt for det som skal tillates.

Logging, monitorering og hendelseshåndtering

Husk på at interne komponenter også må monitoreres. Selv om det er hyllevare må samme tiltak gjennomføres her også for å sikre at vi vet hva som skjer og at loggene er til å stole på og ikke kan manipuleres på linje med alt annet vi overvåker.

Veien videre