Försvar på djupet: Del 5 Infrastruktur och lagring av data
19 September 2023De första tre artiklarna handlade om att designa och få tag på en access token. I den fjärde artikeln diskuterade vi hur du validerar ett inkommande anrop och bygger en stark behörighetskontroll i vårt API.
I denna artikel kommer vi att diskutera den infrastruktur som du använder för att driftsätta det system vi tagit fram så här långt. Vi kommer också att titta på vad du behöver tänka på när det gäller lagring av data.
Infrastruktur är ett stort och brett område. Baserat på våra erfarenheter från säkerhetsarbete väljer vi att fokusera denna artikel på följande viktiga punkter:
- Minimera publik exponering av tjänster och funktioner
- Kryptera all trafik med TLS end-to-end
- Säkra användning av beroenden till tredje part
- Säkra lagring av data
Minimera publik exponering av tjänster och funktioner
En viktig aspekt av principen “Least Privilege” och försvar på djupet är att inte exponera mer än vad som behövs. Om ditt API inte skall användas av publika klienter, finns det till exempel inte någon anledning att ha tillgång till nätverket från internet. Ett sätt att begränsa de funktioner i vårt nätverk som exponeras är ett skalskydd i form av brandväggar och gateways. Vi ska inte förlita oss på ett skalskydd, men det ger ett ökat skydd mot felkonfiguration och andra misstag längre ner i kedjan av funktionalitet.
Kan jag lita på mitt ramverk för API utveckling?
Det är inte säkert att de som utvecklar det ramverk som du bygger ditt API på prioriterar säkerhet. I många fall är det rekommenderat från leverantören av ditt ramverk att använda en extern produkt med säkerhetsfokus som första skydd.
Begreppen och produkter i detta område har överlappande funktion. Gemensamt för dem är syftet att stärka vårt skydd mot lite enklare, ofta automatiserade attacker.
En klassisk brandvägg ger oss ett bra basskydd mot att vi inte oavsiktligt exponerar tjänster från vår infrastruktur, som tex FTP, delade filsystem och liknande. En angripare som letar efter öppna, svaga tjänster för att få ett fotfäste i vårt system har en svårare uppgift om vi använder en korrekt konfigurerad brandvägg som ett första skydd.
En Web Application Firewall (WAF) kan inspektera inkommande HTTP-paket och till exempel detektera vanliga injektionsattacker, osäkra HTTP-Headers eller vissa XSS.
En “Application Gateway” har ytterligare funktioner som kan vara viktiga i ett säkerhetssammanhang, som t ex att begränsa trafiken från individuella klienter (rate limiting). Vi kan också begränsa utåtgående trafik från vårt system till en lista av godkända adresser. Detta försvårar för en angripare att extrahera data efter att hon fått fotfäste i vårt system.
Ytterligare en viktig funktion från denna typ av produkter är förmågan att förhindra att överbelastningsattacker (DDoS) medför nertid för vårt system.
Enligt principen “Least Privilege” bör du också stänga av alla tjänster och funktioner som du inte använder i ditt system. Detta är särskilt viktigt om du använder servrar och inte molntjänster. Servrar måste också hållas uppdaterade med alla säkerhetspatchar som görs tillgängliga av leverantören.
Lite beroende på din organisation så har molntjänster en fördel här, jämfört med att använda egna servrar. En molnleverantör med stark säkerhetsprofil, erfarenhet och kompetens kring produkten kan ha möjligheter att göra ett bättre säkerhetsarbete jämfört med en egen organisation.
Tänk på att begränsa exponeringen av datakällor i molnet. Ofta är dessa publika per default, även om molnplattformen erbjuder olika typer av nätverksskydd.
Segmentera dina interna nätverk så att en angripare med ett fotfäste i en del av ditt system får svårare att utvidga sin närvaro till andra delsystem. Se också till att alla användarkonton med tillgång till din infrastruktur använder starka lösenord och multifaktorautentisering (MFA).
Hantering av användarkonton är en mycket viktig säkerhetsaspekt som ofta glöms bort. Anställda som inte längre arbetar med systemet ska naturligtvis heller inte ha tillgång till infrastrukturen. Alla konton ska också vara personliga så att vi kan få spårbarhet i vem som har utfört ändringar i systemet. Spårbarhet är en viktig aspekt av undersökning och efterarbete när vi haft ett intrång i våra system.
Rotering av lösenord till tjänster är viktigt av samma skäl. Någon som inte längre arbetar med systemet kan ha kvar gamla lösenord till databaser etc. Se separat kapitel om säker lagring av data för mer information.
Kryptera all trafik med TLS end-to-end
Trafiken i nätverket ska skyddas med TLS. Det är viktigt att förstå vad en krypterad nätverkstrafik både ger oss och inte ger oss. Med hjälp av TLS får vi:
- Integritet
- Konfidentialitet
- Autentisering på klienten av mottagaren av anropet (d v s servern, t ex ett API)
- Möjlighet för mottagaren (servern) till autentisering av klienten via Mutual TLS (mTLS), vilket kräver klientcertifikat
TLS ger oss inte:
- Anonymitet
- Spårbarhet
- Oavvislighet
Även om trafiken är krypterad så kan någon som övervakar en nod se klientens och mottagarens IP-adresser. Det gör att man kan kartlägga vilka parter som kommunicerar, även om vi inte kan se innehållet i trafiken. Vi får med andra ord inte full anonymitet.
TLS ger inte spårbarhet eftersom det helt enkelt endast är en kryptering av kommunikationen.
Oavvislighet är ett starkare begrepp än spårbarhet och betyder att den som utfört en operation inte kan förneka att det skett. Det vill säga att systemet kan kryptografiskt koppla en användare till en given läs- eller skriv-operation. TLS ger oss inte denna starkare spårbarhet eftersom vi inte garanterat kan koppla trafik till en användare.
Martin Altenstedt, Omegapoint
Var noga med att även använda TLS i dina testsystem och utvecklingsmiljöer. Det är fullt rimligt idag att kräva att utvecklare avänder sig av HTTPS under utveckling. Inställningar och konfiguration för att göra undantag i test och utvecklingsmiljöer har visat sig ha en förmåga att leta sig in även i produktionssystem.
Vi anser att all trafik över HTTP med stark TLS (HTTPS) är ett fullgott skydd för att en angripare inte ska kunna titta in i vår trafik. Det ger oss ett skydd för allt data som ingår i anropet. Detta inkluderar angripare som har full kontroll över en nod i nätverket. Det inkluderar inte en angripare som har kontroll över den nod som kör någon del av vårt system, som t ex API eller klient.
TLS krypterar allt data i HTTP-meddelandet, dvs. header, body och query. Däremot skyddas inte mottagarens adress (host).
Se även till att hänvisa all trafik som går över okrypterad HTTP-trafik till HTTPS. Samt att använda dig av HTTP Strict Transport Security (HSTS) för att informera webbläsare om att de enbart ska använda sig av HTTPS.
Val av de krypton som används för TLS är viktigt. Svaga algoritmer ger ett otillräckligt skydd mot en kraftfull angripare. Med till exempel https://ssl-config.mozilla.org/ kan du enkelt generera en säker TLS-konfiguration.
Var man avslutar HTTPS kan variera lite mellan olika system och hur de driftsätts. Vi strävar efter end-to-end kryptering, men det är en balans att avgöra var avslutet sker.
OAuth2 och OpenID Connect förutsätter ett starkt transportlagerskydd med TLS 1.2 eller senare. Att välja var vi avslutar TLS i ett stort system är viktigt och kan vara en svår balans mellan enkelhet, säkerhet och komplexitet.
I en Kubernetesmiljö är det t ex vanligt att TLS avslutas i ingressen, och att all trafik inom klustret sker okrypterat. Detta betyder naturligtvis att en angripare som har fått ett fotfäste inne i klustret har tillgång till all trafik, och där med exempelvis alla access tokens. Är klustret begränsat till ett system med få och väl kontrollerade administratörer öppnar detta inte för någon stor attackyta. Då kan vi kan välja att avsluta TLS i ingressen, vilket är en enklare teknisk lösning jämfört med TLS ända fram till podden.
I stora, osegmenterade nätverk som delas av många system med många administratörer har en angripare däremot en stor attackyta att arbeta med. Ett fotfäste på någon nod i nätverket gör att vi inte längre kan upprätthålla integritet och konfidentialitet för de system som körs i ett osegmenterat nätverk.
Ur ett säkerhetsperspektiv kan det finnas anledning att betrakta ett internt nätverk som publikt, just för att vi anser att det är så stort att vi inte rimligen kan anse att det uppnår en god nivå av integritet eller konfidentialitet för vårt systems syften.
Ett vanligt scenario är att den nod som avslutar TLS vid ingången till ett internt närverk, åter krypterar den fortsatta trafiken inåt. Då har vi ett bra internt skydd av transportlagret, men noterar att den noden kan läsa all trafik och behöver säkras. Ett avslut av TLS innan anropet når vårt API, gör det svårare att hantera certifikatsbundna access tokens då det baseras på mTLS.
Det är fortfarande möjligt att använda certifikatbundna access tokens, även om TLS avslutas innan anropet når vårt API. En lösning är att den nod som avslutar TLS skickar vidare den information om certifikatet vi behöver i vårt API i en HTTP header.
Säkra användning av beroenden till tredje part
Ett modernt system bygger på komponenter och tjänster som vi själva inte utvecklar. Alla dessa beroenden behöver uppdateras kontinuerligt för att inte skapa sårbarheter som kan utnyttjas av en angripare. Till exempel kan en felaktighet i någon av de komponenter vi använder i vår webbklient skapa möjligheter för en angripare att göra en XSS-attack. Säkerhet, långsiktigt underhåll och uppdatering av dessa beroenden är en viktig aspekt när vi väljer komponenter och tjänster.
Notera att detta gäller under systemets hela livslängd, inte bara under dess utvecklingstid. Drift och underhåll av ett system måste inkludera uppdatering av alla komponenter som påverkar säkerheten. Ett noggrant urval där vi bedömer komponentens säkerhetspåverkan och framtida underhåll är en viktig del av vårt säkerhetsarbete.
En modern webbapplikation består av paket som åtminstone till viss del kan hämtas direkt från externa källor. Google Analytics och Google Tag Manager är två exempel där vi ofta laddar ner både paket och annat innehåll till vår JavaScript runtime. Om en angripare kan skaffa sig kontroll över paketkällan och leverera ett eget innehåll, har hon också full kontroll över din applikation. Detta gäller även för vårt API. Utsträckningen av problemet varierar med vilken typ av ramverk vi använder för att bygga vår applikation.
För att minska risken att skadlig kod från tredje part når vår applikation, kan vi hämta paketen när applikationen skapas istället för dynamiskt i runtime. Det ger oss möjlighet att upptäcka problem innan de når ut i våra system.
Detta försvårar för en angripare eftersom hon då behöver kontrollera källan över en längre tid. Om vi ändå väljer att hämta paket direkt från en extern källa vid runtime, bör vi verifiera att paketet inte innehåller oegentligheter eller sårbarheter.
Det finns många verktyg som hjälper oss med både statisk och dynamisk kodanalys när vi skapar applikationen. Exempel på detta är scanners som integreras med din byggpipeline och letar efter kända sårbarheter i både din egen kod och externa paket.
För paket som vi trots allt hämtar dynamiskt i en webbapplikation, kan vi stärka skyddet genom att använda Subresource integrity. Vi verifierar då i vår applikation att vi hämtar rätt paket och att innehållet är som vi förväntar oss. Nackdelen är ökad administration när paket uppdateras.
Säkra lagring av data
Alla konton som används av våra API för åtkomst av data ska ha minimala rättigheter till den datakälla de är kopplade till. Connection-strängar bör roteras med jämna mellanrum. Lösenord i connection-strängar skall alltid vara maskingenererade och ha hög entropi. En människa ska aldrig välja lösenord till databaser.
De användarkonton som används av administratörer för att koppla upp sig mot datakällor skall vara personliga och bör vara så begränsade som möjligt. Dels för att reducera säkerhetsrisken, men också för att minimera omfattningen av mänskliga misstag.
Data skall lagras krypterat, ofta genom stöd i produkt eller operativsystem.
Glöm inte bort hantering av databasbackuper
Flera av de allra största angreppen mot IT-system har varit mot just bristande rutiner för backuper av databaser. Exempel på detta är okrypterade backuper som lagts i en publik S3 bucket.
Vissa typer av data är så pass känsligt att databasens egna kryptering inte räcker, utan innehållet behöver även krypteras av applikationen. Ett bra exempel på detta är lagring av lösenord, som ska hanteras enligt rekommendation (t ex bcrypt eller PBKDF2).
Sammanfattning
I denna artikel har vi diskuterat den infrastruktur som du använder för att driftsätta systemet och vad du behöver tänka på kring datalagring.
På samma sätt som vi behöver centraliserad loggning av vår applikation, behöver vi loggning och övervakning av vår infrastruktur för att kunna detektera intrång och missbruk. Det finns många produkter för loggning och övervakning på marknaden. Välj en lösning som ger dig en bra helhet och goda möjligheter till relevanta, automatiserade larm.
Uppdatering och underhåll av systemet är en väldigt viktig säkerhetsaspekt och innefattar allting från operativsystem och tjänster till mjukvarukomponenter i ditt system.
I nästa artikel ska vi titta närmare på webbläsaren och vilka säkerhetsutmaningar den ger oss när det gäller webbapplikationer.
Se Defense in Depth för ytterligare material och kodexempel kopplade till den här artikelserien.
Fler artiklar i serien:
- Försvar på djupet: Del 1 Modellering av identitet
- Försvar på djupet: Del 2 Claimsbaserad behörighetskontroll
- Försvar på djupet: Del 3 Klienter och sessioner
- Försvar på djupet: Del 4 Säkra API:er
- Försvar på djupet: Del 5 Infrastruktur och lagring av data
- Försvar på djupet: Del 6 Webbläsare
- Försvar på djupet: Del 7 Sammanfattning