En sikker løsning begynner med et godt design! Mye av grunnlaget for å vurdere om en løsning er sikker, kommer fra designfasen hvor det må gjøres viktige avveininger mellom kost, nytte og risiko.
Artikklene du finner under temaet Designe på denne siden vil fokusere på designprosessen. Selv om denne kan inkludere mye mer enn vi har listet opp, dekker vi det viktigste i form av god dokumentasjon på det som skal bygges, viktige avklaringer og behovet for kontekst.
1 - Sikkerhetskrav
Hvordan kan en bygge sikkerhet i en løsning dersom en ikke har veldefinerte sikkerhetskrav?
Noen krav er implisitte, som eksempelvis bruk av HTTPS/TLS, mens andre vil være eksplisitte og definert av lovverk, kunde eller tredjepart. Dersom kunden ikke har noen spesifikke krav er det likevel viktig at leveranseteamet lager en kravliste slik at rammene for prosjektet er dokumentert.
De fleste prosjekter må forholde seg til ulike krav fra Bouvet, kunden og eksterne parter. Alle utviklingsteam må ha kontroll på hvilke krav som stilles til leveransen:
Fra Bouvet (der dette er aktuelt)
Fra kunden
Lovpålagte krav
Av lovpålagte krav kan en ha generelle krav eksempelvis knyttet til personvern, men mange bransjer opererer med mer spesifikke forskrifter som stiller andre krav som vil gjelde i tillegg.
I mange tilfeller er det klart både for Bouvet og kunde hva som gjelder, men det er viktig at teamet verifiserer dette før en begynner å utvikle løsningen, slik at kostbare og tidkrevende overraskelser kan unngås. Uavhengig av hva som er definert hvor, bør teamet uansett dokumentere hvilke krav en forholder seg til slik at dette er bevart for ettertiden.
Introduksjon til ansvarsfordeling i leveranser - hva må vi ha klarhet i?
Nettverk er en grunnleggende komponent i alt vi lager, og det er viktig med en grunnleggende forståelse for hvordan dette fungerer og hvordan det kan utnyttes av andre.
Riktig konfigurasjon av nettverk er viktig for både rene skyløsninger, hybride nettverk og rene on-prem-løsninger. Nettverk er et stort fagfelt, med store variasjoner i bruksområde, sikkerhet og kompleksitet. Under dekker vi grunnleggende konsepter for kommunikasjon til og fra servere og nettjenester.
Zero trust arkitektur
Zero trust er et viktig konsept innen nettverksdrift. Kort fortalt så skal man aldri stole på noe som kommer fra andre systemer, og du skal anta at all kommunikasjon vil bli kompromittert. Zero trust kan ikke løses bare ved å sikre nettverket, men må være et mål i seg selv når en designer løsninger og infrastrukturen rundt disse. Ved å implementere zero-trust vil du fjerne mange potensielle angrepsvektorer og dermed beskytte tjenestene som benytter nettverket.
Få oversikt over nettverket
Viktig
Ha kontroll på hvilke IP-adresser og porter du eksponerer, og hvilke tjenester som lytter på portene. Undersøk brannmurregler, se i logger og skann
egne systemer med nmap.
Ha oversikt over hvilke IP-adresser, porter og protokoller som et IT-system eksponerer mot utsiden. Dette gjelder uavhengig av om du skal sette opp et nytt, endre på eksisterende eller bare undersøke hva du allerede har. En målrettet angriper vil kartlegge åpne endepunkter for å finne angrepsmål, og det har vært flere eksempler på at datainnbrudd begynner med en bortglemt, usikker tjeneste.
Som utviklere og systemansvarlige er det kritisk at vi vet akkurat hvilke tjenester som er åpne for hvem og hvorfor de er det.
Når man setter opp nye systemer har man gode muligheter til å få kontroll over hva som eksponeres. Hovedregelen etter Zero trust-arkitekturen bør være å begynne med at alt er stengt, og så åpne kun de porter og protokoller som trengs. Nye komponenter bør isoleres fra eksisterende systemer.
I eksisterende systemer kan det være vanskelig å få oversikt over hva som er eksponert, spesielt i hybride eller on-prem oppsett. Å bare stenge ned alt som ikke er dokumentert kan også være risikabelt, da dette kan ramme legitime systemer. Dersom en jobber i kundens infrastruktur, ta gjerne kontakt med en eventuell nettverksavdeling for hjelp til kartlegging.
Skanning av nettverk
For å finne åpne porter og tjenester bør man skanne både public og private IP-masker fra ulike steder. Husk at interne nettverk kan følge andre nettverksruter enn ekstern trafikk, og dermed se forskjellige åpninger. Det samme gjelder i sitasjoner der en har kontornett, VPN, DMZ/gjestenett eller andre åpne nett.
Det finnes verktøy og tjenester som gjør kartleggingen enklere. nmap er industristandarden og FOSS, og den egner seg utmerket til å skanne IP-masker og detektere åpne UDP-, TCP- og SCTP-porter. Hvis du mangler oversikt, er nmap et godt sted å starte.
Advarsel
Bruk av scannerverktøy som `nmap` skal alltid avklares med eiere av infrastruktur og nettverk. Dersom du sitter på
et Bouvet-kontor og scanner Azure-miljøet til en kunde, kan du lett trigge alarmer hos både Bouvet og kunden, samt ISP.
Isolasjon av tjenester
Viktig
Bruk brannmur til å begrense trafikk innad i systemer og mellom systemer og Internett. Bruk allowlist hvis mulig. Filtrer trafikk i applikasjonslaget hvis
nødvendig.
Brannmur er en fellesbetgegnelse på barrierer i nettverk som stopper uønsket trafikk. I de fleste sammenhenger er definisjonen litt snevrere, hvor det er
snakk om barrierer i TCP/IP-laget, men en brannmur kan også operere i applikasjonslaget.
For å håndheve en zero-trust arkitektur må alle komponenter isoleres og kun gjøres tilgjengelig for de tjenestene som de selv skal konsumere eller levere data til. Det gjør det nødvendig med brannmur mellom komponenter i samme applikasjon, mellom applikasjoner og mellom applikasjon og Internett. Har du en applikasjon med en database, et backend-API og et web-API, er det gunstig om du kan sette brannmurregler mellom komponentene som kun tillater den trafikken som er nødvendig. Se diagrammet under for eksempel.
Brannmurer bør alltid droppe all inngående og utgående trafikk som standard, og heller åpnes eksplisitt for legitime forbindelser. Begrens alltid portåpninger til spesifikke porter og protokoller der det er mulig. Unngå bruk av “Any” som protokoll!
Bruk også brannmurer mellom alle tjenester internt i nettverket for å sikre at en har flere lag med beskyttelse om ett skulle feile. Segmentering av nettverket slik at hver funksjon har sitt subnett vil også hjelpe.
Unngå å sende trafikk over internett selv til egne skytjenester, bruk private endepunkter og VPN-tunneller der dette er mulig. Tjenester som må eksponeres mot andre systemer (både interne, eksterne og på internett) bør legges bak sikkerhetsfunksjoner som web application firewalls og/eller api gateways, og en må sikre at disse også beskytter mot eksempelvis DDOS-angrep.
Send all utgående trafikk gjennom en egen proxytjeneste som blokkerer alt som standard, whitelist heller etter behov. Eksponer aldri tjenestene direkte dersom du kan unngå det. Å eksponere tjenester på andre porter enn standardportene er ikke en god ide, et scan av nettverket vil fort avsløre dette.
Konfigurasjon
Konfigurasjon av nettverk bør automatiseres i så stor grad som mulig, helst ved bruk av et CI/CD-system.
Begrens hvem som kan konfigurere både nettverket og nettverksregler direkte
Sett opp Just-in-time (JIT)-tilgang der det er mulig
Begrens hvor nettverket kan redigeres fra (f.eks. kun på innsiden av en on-prem brannmur)
Script alle regler som kan scriptes
Bruk kildekodekontroll
Ha ekstra sikkerhet på repos som inneholder kilden til nettverket, beskytt både mot lesing og skriving
Bruk verktøy som Snyk for å kjøre analyse av script
Scriptene bør kjøres regelmessig og automatisk (minst hvert døgn)
Dersom ukjente regler oppdages skal det opprettes varsler
Alle ukjente regler slettes eller deaktiveres
Alternativt kan man bruke andre metoder som oppdager endring fra ønsket konfigurasjon
Ta backup av eller dokumenter alle regler som settes opp uten scripting
Dokumenter alle regler som settes opp / håndteres av personer utenfor ditt team
Det er viktig med et godt underlag når vi skal bygge gode løsninger, og skisser og diagrammer som viser oppbygningen av infrastruktur, dataflyt, nettverk og tilgangsstyring er viktige elementer. Uten denne informasjonen er det vanskelig å validere om sluttresultatet matcher intensjonen.
Når vi designer en løsning, er det viktig med gode og oversiktlige skisser og diagrammer som viser designet slik at det planlagt. Dette gjøres allerede av mange utviklerteam uten at det nødvendigvis stilles krav til det, men det er likevel greit å nevne her.
Systemskissene bør gi nok informasjon til at en i etterkant kan
Validere at implementasjonen er som designet
Bruke dem ifm trusselmodellering, pentesting eller liknende
Brukes av den/de som forvalter løsningen for å få en god oversikt over komponenter og dataflyt
Brukes av leveranseteamet for onboarding av nye kollegaer eller handover til andre team.
Selv om det er mye som kan dokumenteres her, fokuserer vi bare på det viktigste her:
Overordnet systemskisse med de viktigste logiske komponentene
Detaljert nettverksskisse med ressurser, tjenester og nettverk
Dataflytdiagram - viser hvordan data flyter mellom komponenter i løsningen
IAM-diagram - Viser identiteter, tilganger og roller samt hvor de hentes fra
Viktige avhengigheter – oversikt over andre systemer, tjenester, ressurser, onprem/cloud
Eksempler
Under finner du eksempler på punktene listet ovenfor. Diagrammene du produserer trenger ikke å være like, det viktigste er at de inneholder nok informasjon til at de kan brukes for det tiltenkte formålet og at de er forståelige for teamet.
For enkelt å komme igang med design av diagrammer og skisser kan verktøy som Miro eller Draw.io brukes. Sistnevnte er gratis og tilbyr lagring av tegniner i nettleser, lokalt på maskinen som XML og mye annet.
Husk
Diagrammene trenger ikke å være perfekte, eller inneholde alle tenkelige detaljer. Vurder behovet og jobb med gradvise forbedringer over tid.
Overordnet systemskisse
Netverksdiagram
Husk:
Nettverksdiagram bør lages for alle miljø, slik at en får nødvendig informasjon på alle ressurser i alle miljø, samt forbindelser mellom disse.
Utviklingsprosjekter benytter flere ulike miljø til ulike formål som for å teste deployments i et eget dev-miljø, en eksponerer testmiljø mot produkteier og andre nøkkelpersoner samt produksjonsmiljø mot sluttbrukere. For å unngå at hendelser i ett miljø ikke påvirker et annet må vi segregere disse på et nivå som gir mening for teamet og konteksten man jobber i.
Når vi bygger løsninger setter vi ofte opp flere miljø, ofte for dev, test og prod slik at vi kan utvikle samtidig som at produkteier tester ny funksjonalitet og sluttbrukere bruker systemet i prod. Det er viktig at vi skiller mellom disse miljøene, slik at vi unngår å komme i situasjoner der endringer i ett miljø påvirker bruken av et annet.
Når vi designer en ny løsning må vi derfor tenke på hvordan vi skiller mellom miljøene. For skytjenester er en vanlig tilnærming ofte å benytte seg av ulike subscriptions per miljø der dette er mulig. En subscription kan ikke påvirke en annen med mindre dette er eksplisitt satt opp, men det finnes andre muligheter også.
Kortfattet oversikt over de vanligste løsningene (Azure):
Separate subscriptions per miljø:
Naturlig skille med mindre en eksplisitt definerer tilganger
Mer overhead med administrering av flere subscriptions
Bruk av separate ressursgrupper
Forenklet administrasjon
Ressursgrupper deler enkelte begrensninger og tilganger på subscription-nivå
Separate virtuelle nettverk
Segregering på nettverksnivå
Krever ofte mer admin for å sikre at en har et faktisk skille
Det finnes andre tilnærminger på dette også, men uansett hvilken løsning teamet går for er det viktig å se det totale bildet med kost/nytte opp mot kravene en må forholde seg til.
Autentisering og autorisering sjekker henholdsvis hvem du er og hva du har lov til. Dette er viktige konsepter som må implementeres korrekt for at sikkerheten i en løsning skal ivaretas.
Autentisering og autorisering er viktig i alle utviklingsprosjekter. Kort fortalt går autentisering ut på at en skal validere at en bruker representerer den identiteten den hevder å representere, typisk gjennom å sjekke brukernavn og tilhørende passord. Autorisering går ut på å sjekke at brukeren har lov til å gjøre det den prøver på. Disse er ofte forkortet til authn for autentisering og authz for autorisering.
Autentisering
Når en skal validere en bruker, er det viktigste at en ikke lager en egen autentiseringsløsning! Å sikre at slike løsninger faktisk er sikre er en kjempejobb, og man bør istedet benytte seg av etablerte løsninger for dette!
Vanlige tilnærminger for å håndtere autentisering kan være bruk av tredjepartstjenester, eller protokoller som håndterer autentisering mot kundens AD/Entra. I mange tilfeller ønsker vi å benytte Single-Sign-On(SSO) for å unngå at brukeren må taste inn brukernavn og passord, spesielt for interne forretningsapplikasjoner.
Vanlige løsninger for å håndtere pålogging er å benytte seg av biblioteker som tar seg av hele flyten, som eksempelvis Microsoft.Identity.Web. Andre alternativer kan være bruk av
SAML
Oauth 2.0
OpenID Connect (OIDC)
Kerberos
LDAP
Her er det viktig at en setter seg inn i behovene til løsningen og hvilke autentiseringsmetoder som er tilgjengelige og eventuelt ønskelige.
Autorisering
Skillet mellom autentisering og autorisering ligger i at autentiseringen bekrefter hvem du er, mens man i autoriseringen sjekker at du har lov til å utføre en handling.
I likhet med autentisering finnes det flere tilnærminger for hvordan autorisering håndteres, og man er nødt til å sette seg inn i beste praksiser for språk og rammeverk som benyttes.
Det finnes likevel noen hovedprinsipper en alltid skal ta med seg inn i utviklingsforløpet:
Standardtilgang skal alltid være ingen tilgang
Dette er også kjent som default deny, og brukes for å sikre at eksempelvis en uautorisert bruker ikke har tilgang til noe utover det som er eksplisitt tillatt.
Autorisering skal alltid sjekkes
Dersom en bruker forsøker å utføre en handling, skal det alltid sjekkes hvorvidt brukeren faktisk har tilgang til dette. Husk at denne sjekken må skje mot den autoritative kilden for tilganger, og aldri mot data brukeren kan manipulere!
Brukere skal alltid gis minst mulig tilgang
Også kjent som principle of least privilege. En bruker skal aldri få mer tilgang enn det som trengs for å utføre en spesifikk oppgave. Dette gjøres for å redusere angrepsflaten dersom en bruker kompromitteres, slik at skadeomfanget kan begrenses.
Rollebasert brukertilgang
Bruk av roller, role based access control (RBAC) er en vanlig tilnærming for å gi brukertilgang. Målet er å definere standardroller for en applikasjon, slik at tilgang kan baseres på disse. En vanlig måte å håndtere dette på eksempelvis med Entra eller AD er å ha
aksessgrupper med alle brukerne. Aksessgruppene legges som medlemmer i
rollegrupper, som gis tilgangen i applikasjonen.
Dette gir en bedre oversikt over hvem som har tilgang til hva sammenliknet med brukere som har individuelle tilganger.
Trusselmodellering er en øvelse der målet er å identifisere trusler i og rundt en løsning. Dette gjør at risikoene kan identifiseres og vurderes opp mot et totalbilde av sikkerheten i løsningen. Fra en trusselmodell kan mitigerende tiltak identifiseres og implementeres for å redusere risiko.
Dette er en kort introduksjon til trusselmodellering, dataflytdiagrammer, STRIDE og angrepstrær.
Du har nok allerede gjort en enkel trusselmodellering uten at du selv er klar over det. Har du for eksempel tenkt på hvorfor brukerne av systemet du lager må logge seg inn med brukernavn og passord?
Når disse valgene ble tatt så har du automatisk gjort en enkel trusselmodellering. Du ønsker jo selvfølgelig ikke at uvedkommende skal kunne få tilgang til data i systemet ditt og du ønsker ikke at hvem som helst skal se data som overføres mellom brukerne dine og nettstedet ditt.
Hele poenget med trusselmodellering er å tenke som en angriper.
Identifisere trusler
Det finnes flere måter å identifisere trusler mot et system. Den enkleste metoden som ikke krever så mye, er å samle utviklingsteamet til en sosial kveld eller workshop, og prøve å tenke på hvordan man kan angripe systemet. Da vil man antagelig komme opp med mange potensielle trusler. Noen er sikkert allerede adressert, mens andre kanskje må testes ut og eventuelt graves dypere i. Når man har adressert alle trusselene og verifisert at mottiltak er implementert, så gjentar man prosessen. For å få et overblikk over prosessen er det ofte lur å tegne en oversikt (diagram) av systemet.
Prosessen starter ofte med å tegne opp et diagram/oversikt av systemet, så identifisere trusler, adressere truslene, og til slutt validere at mottiltak er implementert, så gjenta.
Dersom man ønsker å benytte mer formaliserte verktøy og prosesser så finnes det to mye brukte metoder for trusselmodellering, angrepstre og datafylytdiagrammer + STRIDE.
Angrepstre
Bruk av angrepstrær er en fin måte å identifisere trusler på dersom man er god til å tenke som en angriper. Dersom dette ikke faller naturlig er bruk av dataflydiagrammer ofte en bedre metode.
Et angrepstre består av et hovedmål på toppen av treet, og med ulike måter å nå hovedmålet som noder.
I dette eksempelet er hovedmålet til en angriper å få tilgang til rapporter i et timeføringssystem. For å nå hovedmålet kan angriperen enten benytte et gyldig passord i systemet eller finne en svakhet i løsningen som gir tilgang. En måte å få tak i et gyldig passord er å bestikke en ansatt. Slik fyller man på med ulike måter for å nå hovedmålet og delmålene. Man går deretter gjennom de identifiserte truslene og verifisere at man har mottiltak på plass eller eventuelt velger å godta at det finnes trusler mot systemet som man ikke vil beskytte seg mot. Kostnaden på mottiltakene bør alltid veies opp mot verdiene som skal beskyttes.
Man starter med å lage et detaljert dataflytdiagram over systemet eller en del av systemet man skal trusselmodellering av.
Når man har tegnet opp dataflyten og tillitsgrensene til systemet, så bruker man STRIDE for å identifisere trusler. STRIDE er et akronym for
Spoofing - Kan man stole på at brukeren er man tror?
Tampering - Kan noen endre på data med vilje eller uforvarende?
Repudiation - Kan det bevises hvem som gjorde en gitt handling i systemet?
Information disclosure - Kan data stjeles eller komme på avveie?
Denial of Service - Kan noen gjøre at tjenester blir utilgjengelige?
Elevation of privilege - Kan noen tilegne seg utvidede rettighter i systemet?
Her er et eksempel på et dataflytdiagram som viser dataflyten ved innlogging med brukernavn og passord. Pilene mellom tjenestene representerer kall. SSL-proxy er et sikkerhetslag som krypterer informasjon mellom tjenester. HTTPS er kall der informasjonen som sendes med er kryptert, og HTTP er kall der informasjonen som sendes med ikke er kryptert.
I dataflytdiagrammet over kan man se at det er en fare for at noen med tilgang til nettverket mellom SSL-proxyen og timeføringssystemet kan lese og endre brukernavnet og passordet som ikke er kryptert over HTTP. Ved å gå gjennom alle dataflytene mens man tenker på mulige angrep i henhold til STRIDE-modellen kan man bygge opp en liste over mulige trusler mot systemet.
Trusselmodellen må versjoneres og holdes oppdatert. Når en har identifisert trusler må mottiltak beskrives og effekten av disse vurderes. En vanlige tilnærming er å gi trusselen en verdi som indikerer alvorlighetsgrad, eksempelvis 1-10 der 10 er verst. Mottiltak vurderes tilsvarende, men med motsatt skala der 1 er liten effekt og 10 (eller opp til kritikalitet) er høyest effekt. Summen av disse gir en residuell risiko som sier noe om hva en sitter igjen med:
Når en har identifisert en risiko, er det viktig at den som eier denne risikoen involveres, da det er denne som har ansvaret for å påse at prosjektet leverer kvalitet i tråd med forventninger og krav.
Det er viktig at mottiltak valideres for at dette skal ha noen hensikt. Trusselmodellen bør hentes opp med jevne mellomrom for å se hvordan situasjonen har endret seg, og dersom den totale kritikaliteten eller den residuelle risikoen overstiger en grense bør en vurdere tiltak for å redusere disse.
Veien videre
Verktøy
Microsoft Threat Modeling Tool gir deg en kick-start ved at en del vanlige trusler for diverse tjenester allerede er beskrevet. Dette verktøyet er særlig nyttig dersom man opererer i Microsoft Azure.
OWASP Threat Dragon er et tilsvarende open source verktøy, som det kan være verdt å ta en titt på.
Riktig kompetanse er viktig for alle team, ikke minst når det kommer til sikkerhet. Teamet må identifisere hvilke gap en har, slik at tiltak som eksempelvis opplæring kan iverksettes for å dekke disse.
Sikkerhet er for mange et ukjent og kanskje litt skummelt område, der en ikke helt vet hvor man skal begynne. Når et nytt prosjekt startes opp er det derfor viktig at en vurderer behovet for kompetanseheving hos teammedlemmene. I utgangspunktet er dette rettet mot tema relatert til sikkerhet, men bruk av ny teknologi kan også utgjøre en risiko dersom en bruker den på feil måte.
Det er viktig at teamet ser over hele utviklingsløpet med alle fasene og vurderer hvert enkelt punkt opp mot hva teamet kan, hva en ser på som relevant for prosjektet og hvor en kan få bistand.
Vi har mange ulike sikkerhetsmiljøer og enkeltpersoner med høy kompetanse som kan bidra innad i Bouvet; dersom akkurat ditt team har behov, ta det gjerne opp på din lokale Security-Champions-kanal på Bouvet-Slack, #sikkerhet eller med din regionale kvalitetsleder.