Jag ställer in Linux-funktioner för att driva servertjänster enligt minimalprincipen och därmed endast tilldela de absolut nödvändiga delrättigheterna. På så sätt minskar jag Attackyta märkbart, utan att blockera funktioner.
Centrala punkter
- Minsta privilegium Konsekvent: Tjänsterna tilldelas endast exakt de kompetenser som behövs.
- Finkornig I stället för root: Cirka 40–50 behörigheter ersätter full åtkomst.
- Separation av processer: Separation av behörigheter minskar skadorna vid utnyttjande av sårbarheter.
- Fil Funktioner: Koppla behörigheter direkt till binärfiler.
- Kan granskas: getcap ger en tydlig överblick över särskilda behörigheter.
Varför root-behörighet är riskabelt – och hur Capabilities förändrar detta
Förr kördes nästan alla servertjänster med Roträttigheter, vilket vid en säkerhetsöverträdelse omedelbart kunde leda till att systemet togs över. Idag fördelar jag behörigheter på ett målinriktat sätt genom att använda funktioner som CAP_NET_BIND_SERVICE tilldela för portar under 1024 och ta bort alla andra omfattande behörigheter. På så sätt får webbservern binda portar, men inte ladda in kärnmoduler eller ändra filägare, vilket Säkerhet ökar avsevärt. En tydlig uppdelning av uppgifterna gör attackerna mindre effektiva, eftersom en process som utnyttjas endast får utföra ett begränsat antal åtgärder. Den som vill skapa mer struktur i detta koncept kan finjustera behörigheterna mycket noggrant fördela i detalj och på så sätt systematiskt begränsa kritiska operationer. En monolitisk roottjänst omvandlas därmed till en uppsättning tjänster med minimala, tydligt definierade befogenheter.
Så här fungerar kapacitetsuppsättningar i kärnan
Varje process har flera Kompetensuppsättningar, som kärnan kontrollerar vid känsliga åtgärder. Effective-set avgör vad en process får göra just nu, medan Permitted-set innehåller den samling av möjliga rättigheter som finns. Genom Inheritable-set kan jag styra vad som vid execve() överförs till underprocesser, vilket är särskilt viktigt när det gäller wrappers och startskript. Bounding-setet definierar en strikt övre gräns, så att vissa behörigheter aldrig kan återfås, inte ens vid fel i applikationen. Med Ambient-setet överför jag behörigheter utan SUID till vanliga program och behåller Attackväg liten. Tillsammans ger dessa inställningar mig möjlighet till en mycket finjusterad styrning som går långt utöver det klassiska ”allt eller inget”-principen i UID 0.
| Set | Syfte | Typisk användning | Risk för felkonfigurering |
|---|---|---|---|
| Effektiv | Förmågor som är aktiva just nu | Granskning av varje privilegierad operation | Processen kan omedelbart leda till för mycket |
| Tillåtet | Utbud av tillåtna färdigheter | Källa för Effective-Set | Onödiga reserver förblir tillgängliga |
| Ärftligt | Ärftliga förmågor | Kontrollerad vidarebefordran vid execve() | Barn ärver rättigheter i onödan |
| Avgränsning | Den övre gränsen för alla rättigheter | Definiera permanenta uteslutningar | Det är möjligt att återfå omfattande rättigheter |
| Ambient | Vidarebefordran utan SUID | Vanliga program får funktioner | En bredare och tystare tilldelning av rättigheter |
I praktiken är två ytterligare aspekter viktiga: För det första avgör Securebits om en process efter ett byte av användar-ID (t.ex. via setuid()) behåller sina funktioner. Med PR_SET_KEEPCAPS Detta kan styras på ett målinriktat sätt – typiskt förfarande: starta kortvarigt som root, skapa nödvändiga socklar eller resurser, byta UID till en användare utan privilegier och behålla endast de nödvändiga behörigheterna. För det andra gäller att: Det Bounding-Set finns nu definitivt i den aktuella processkedjan. Den som här, tidigt i startprocessen, tar bort onödiga behörigheter kan senare inte längre få „otillåtna“ behörigheter, inte ens på grund av felaktiga konfigurationer.
Styra filrättigheter med filfunktioner
I stället för en tjänst, en varaktig Särskilda rättigheter för att undvika detta föredrar jag att koppla dem direkt till binärfilen. Via setcap cap_net_bind_service=+eip /usr/bin/node tillåter jag portbindningar utan att processen behöver köras som root. Med getcap /usr/bin/node eller rekursivt getcap -r / 2>/dev/null kontrollerar jag tilldelningen och behåller kontrollen. Borttagning sker via setcap -r /sökväg/till/binärfilen, så att jag återkallar de tillfälliga behörigheterna efter insatsen. Vid kopiering går ofta kapaciteterna förlorade, därför säkrar jag dem uttryckligen vid driftsättningen för att Regression för att undvika detta. På så sätt förblir buildarna reproducerbara och rättigheterna dokumenteras alltid på ett spårbart sätt.
Filfunktioner finns som utökade attribut (säkerhet.kapacitet) i filsystemet. Detta förutsätter ett kompatibelt filsystem och lämpliga monteringsalternativ. Verktyg som tjära och rsync måste XAttrs anges uttryckligen (t.ex. tar --xattrs, rsync -XA), annars försvinner behörigheterna utan förvarning. Pakethanterare kan ställa in kapaciteter i steg efter installationen; jag föredrar att fastställa detta i bygg- och släppprocessen för att undvika överraskningar vid uppgraderingar. En annan viktig punkt är att tolkskript (t.ex. med shebang) inte ärver filkapaciteter på samma sätt som ELF-binärer. Kraftfulla kapaciteter på Tolkar Att lägga in det är ändå riskabelt – jag kopplar hellre bort det och arbetar med små, dedikerade hjälpbinärer.
Minimalprincipen för servertjänster i praktiken
Jag startar webbservern som en användare utan särskilda behörigheter och beviljar endast CAP_NET_BIND_SERVICE, så att processen kan binda till 80/443 och inga ytterligare Privilegier medför. Jag fortsätter att styra filer och kataloger via POSIX-behörigheter samt, som tillval, MAC-profiler, vilket innebär att konfiguration och innehåll förblir separat skyddade. Övervaknings- eller loggningsagenter tilldelas specifika nätverksbehörigheter och läsbehörigheter till loggar, men inga befogenheter alls att göra systemändringar. I container-miljöer begränsar jag dessutom uppsättningen av kapaciteter och kombinerar den med systemanropsfilter för att hålla beteendet strikt begränsat. Denna kombination minskar effekten av framgångsrika exploateringar och ökar Öppenhet de faktiska befogenheterna. Tjänsterna fortsätter att fungera, men handlingsutrymmet är fortfarande begränsat.
I stället för att tilldela behörigheter tar jag ibland bort dem helt: Socket-aktivering tillhandahåller privilegierade lyssnare (t.ex. 443/tcp) via init-processen och överlämnar endast den öppna filbeskrivaren till tjänsten. Applikationsprocessen behöver då ingen CAP_NET_BIND_SERVICE mer. På samma sätt kan engångsåtgärder som kräver root-behörighet (t.ex. att skapa en PID-katalog) utföras i förväg, varefter behörigheterna sedan konsekvent kan återlämnas. Ju färre befogenheter överhuvudtaget ju fler som deltar, desto mer motståndskraftigt är systemet mot kedjefel.
Genomföra privilegieseparation på ett korrekt sätt
Jag delar upp omfattande tjänster i flera Delprocesser, som var och en endast har de nödvändiga behörigheterna. En frontend-process hanterar TLS och ansluter till portar, men har inga filsystembehörigheter för kritiska ändringar. En backend-process bearbetar data internt, har minimala läsrättigheter till konfigurationen och kommunicerar med databaser utan egna nätverksfunktioner. Administrativa uppgifter som loggrotation eller underhåll sköts via dedikerade verktyg med tidsbegränsade befogenheter. Om en angripare attackerar en del av systemet förblir resten av systemet opåverkat, eftersom Behörigheter är snävt definierade. På så sätt anpassas säkerheten efter applikationens struktur istället för att bygga på allomfattande systemrättigheter.
För denna uppdelning lämpar sig en tydlig startkoordinering. I traditionella konfigurationer sköts detta av en supervisor; i dagens system föredrar jag att använda systemd, eftersom det har inbyggt stöd för capabilities, cgroups och namespaces. På så sätt kan jag starta nätverksfrontend, arbetare och administrationsverktyg i varsin egen sandlåda, begränsa resurserna och låta dem startas om automatiskt vid fel – utan att någonsin dela ut root-rättigheter generellt.
Kombinera säkerhetskontroller: POSIX, MAC och kapaciteter
Funktioner fungerar bäst när jag kombinerar dem med klassiska Filrättigheter och MAC-system. SELinux eller AppArmor kan ytterligare begränsa åtgärder trots tilldelade behörigheter och därmed skapa flerlagersskydd. På så sätt får en process visserligen binda sig till en port, men hindras genom en policy från att läsa känsliga filer. Den som vill fördjupa sig i skillnaderna mellan dessa tillvägagångssätt hittar en tydlig jämförelse i SELinux jämfört med AppArmor och kan sedan välja en lämplig policy-strategi. Sammantaget skapas ett försvarsnätverk som stoppar attacker på flera nivåer och Attackyta minskas ytterligare. Tilldelningen av rättigheter förblir därmed kontrollerbara, repeterbar och konsekvent.
Det blir särskilt restriktivt när jag dessutom NoNewPrivileges Aktivera: Processer och underprocesser får då inte erhålla nya behörigheter (t.ex. via SUID eller nyställda filbehörigheter). Tillsammans med en strikt lista över behörighetsbegränsningar skapas en säkerhetsbarriär som förhindrar senare utökning av behörigheter även vid felaktig konfiguration.
Säkerställa en säker fördelning och granskning av funktioner
Jag anser att den tilldelade Kompetensprofil så liten som möjligt och undvik allt som låter som „andra root“, till exempel CAP_SYS_ADMIN. Tolkar som Python, Perl eller shell-skript får inga kraftfulla funktioner, eftersom deras funktionsomfång lätt kan missbrukas. Genom regelbundna granskningar av getcap -r / 2>/dev/null upptäcker jag avvikelser och rättar till dem. Binärfiler med behörigheter är skrivskyddade, tillhör root och finns inte i sökvägar som vanliga användare får ändra. Dessutom kontrollerar jag mina egna binärfiler före varje release och dokumenterar ändringar, så att Granskning och att reproduktionen fungerar på ett tillförlitligt sätt. På så sätt förblir rättighetstilldelningen hanterbar och ändringarna spårbara.
Under körningen kontrollerar jag processer via /proc//status (Fält CapEff, CapPrm, CapInh). Det ger hexvärdena för de aktiva uppsättningarna och visar omedelbart om en applikation kan göra mer än vad som är avsett. Verktyg som capsh --print eller . getpcaps underlättar felsökningen. Med Linux Audit-subsystemet loggar jag dessutom ändringar av kapaciteter eller av säkerhet.kapacitet-filattribut för att spåra manipulationer. Den som behandlar kapaciteter som konfigurationsobjekt och noggrant granskar ändringar gör revisioner reproducerbara och förenklar eftervisandet av efterlevnad.
Vanliga fallgropar och hur jag undviker dem
En typisk fälla: När man kopierar Attribut förloras, vilket kan leda till att tjänster plötsligt inte längre startar eller tvärtom inte är tillräckligt begränsade. Jag säkrar därför behörigheterna uttryckligen i byggprocessen, eller så tilldelar jag dem automatiskt i steget efter installationen. Ett annat misstag är att generöst använda universella kapaciteter som öppnar upp mer än nödvändigt. Det är bättre att använda specifika kapaciteter som CAP_NET_RAW eller . CAP_CHOWN endast där de aktiverar en faktisk funktion. Även Ambient-Set använder jag sparsamt, så att inga oönskade Att föra vidare utbredd. Den som målmedvetet minskar antalet och regelbundet kontrollerar förhindrar säkerhetsbrister till följd av användarfel.
En annan viktig punkt: Avskaffa SUID-binärfiler systematiskt. I de fall där SUID tidigare var nödvändigt (t.ex. för att skicka ICMP) går det ofta att lösa med CAP_NET_RAW arbeta – eller, ännu bättre, flytta funktionen till en så liten hjälpprocess som möjligt med mycket snäva kravspecifikationer. Dessutom undviker jag att placera Capabilities på tillfälliga eller användarredigerbara sökvägar. Ett strikt ägar- och distributionssystem (Root:root, 0755/0555, oföränderliga sökvägar) förhindrar att behörigheter „går förlorade“ på grund av ersatta binärfiler.
Funktioner inom containerteknik och DevSecOps
I container-miljöer minskar jag Kapacitet aggressivt och tar bort allt som arbetsbelastningen inte absolut behöver. Dessutom skapar jag en Seccomp-profil som blockerar riskfyllda systemanrop och därmed skapar ytterligare ett hinder. I byggpipelines definierar jag kapaciteter deklarativt, testar dem i staging-miljön och registrerar dem med versionsinformation. Detta gynnar efterlevnaden, eftersom jag kan styrka att principen om minsta möjliga behörighet följs och dokumentera behörighetsändringar fullständigt. På så sätt hålls containrarna strikt kontrollerade utan att deras uppgifter hindras, och Attackyta förblir liten. I kombination med bilder som endast innehåller det nödvändigaste ökar säkerheten ytterligare.
Viktigt i samband med containrar: Capabilities finns i namnutrymmen Relativ. Inom ett användarnamnsutrymme kan en process visserligen vara „root“, men dess befogenheter gäller endast de tillhörande namnsutrymmena – vilket avsevärt minskar skadans omfattning. Å andra sidan är „--privilegierad“ är praktiskt taget alltid tabu: Det inaktiverar den strikta avgränsningen och öppnar upp långt mer än nödvändigt. Jag startar därför containrar som standard med „släpp allt, lägg till selektivt“ och lägger till NoNewPrivileges, cgroup-gränser och skrivskyddade monteringar. För tjänster som endast behöver lyssna använder jag socket-aktivering eller sidecars för att helt kunna klara mig utan ytterligare behörigheter.
Systemd-exempel: Deklarativ begränsning av kapaciteter
I service-enheterna fastställer jag vad en process får göra som mest – tydligt, repeterbart och versionshanterbart. Ett kortfattat exempel på en webbtjänst som endast får ansluta till port 443 och i övrigt är starkt begränsad:
[Unit]
Description=Minimal webbtjänst utan root-behörighet
[Service]
User=web
Group=web
ExecStart=/usr/bin/my-web
AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
ReadWritePaths=/var/lib/my-web
RestrictAddressFamilies=AF_INET AF_INET6
SystemCallFilter=@basic-io @network-io
LockPersonality=yes
MemoryDenyWriteExecute=yes
[Install]
WantedBy=multi-user.target
Kombinationen av AmbientCapabilities och en tuff CapabilityBoundingSet ser till att tjänsten endast tilldelas den nödvändiga kapaciteten och inget utöver det. NoNewPrivileges förhindrar efterhandsuppgradering av privilegier, ProtectSystem och ReadWritePaths reglerar skrivåtkomsten, och ett strikt filter för systemanrop förhindrar onödiga ingångspunkter till kärnan.
Vanliga funktioner – och säkra alternativ
- CAP_NET_BIND_SERVICE: Anslutning till portar <1024. Alternativ: Socket-aktivering, placera en omvänd proxy före.
- CAP_NET_RAW: Rohsockets (Ping, DHCP). Alternativ: en liten hjälpprocess istället för omfattande tolkrättigheter.
- CAP_CHOWN/CAP_FOWNER: Ägare/ACL-justeringar. Alternativ: förberedda kataloger, särskilda underhållsverktyg.
- CAP_SYS_PTRACE: Felsökning/spårning – endast i staging, aldrig i full skala i produktion.
- CAP_SYS_ADMIN: „Andra root“ – undvik detta; specificera vad som verkligen behövs.
Jag väljer alltid den minsta mängd som exakt aktiverar den funktion som behövs. Om en kapacitet öppnar upp flera angreppsvägar (t.ex. RAW-socklar) kapslar jag in funktionen i en separat, kortlivad process och återtar behörigheterna när arbetet är klart.
Checklista för robusta kapaciteter i praktiken
- Starts tjänsten utan root-behörighet? Om inte: Varför inte – och går det att lösa med socket-aktivering eller små hjälpbinärer?
- Är alla Är de tilldelade funktionerna bevisligen nödvändiga (funktionsbevis, testfall)?
- Är avgränsningsmängden så snäv som möjligt och fastställd i ett tidigt skede?
- Bevaras XAttrs på ett konsekvent sätt vid kompilering, distribution och säkerhetskopiering (rsync/tar-flaggor, paketskript)?
- Avstår jag konsekvent från att använda ”capabilities” i tolkar och SUID-binärer?
- Är ägar- och filrättigheter (Root:root, 0755/0555) samt sökvägar skyddade mot ändring?
- Fungerar ytterligare säkerhetskontroller (NoNewPrivileges, Seccomp, MAC-profiler)?
- Granskas processkapaciteterna under körning (
/proc//status, getpcaps) och har ändringarna dokumenterats? - Är containrarna som standard konfigurerade med „drop all, add minimal“ och utan „privileged“?
Kortfattat sammanfattat
Linux Capabilities delar upp klassiska root-rättigheter i små, hanterbara enheter och tillämpar därmed minimalprincipen på ett tekniskt korrekt sätt. Jag tilldelar tjänster endast de funktioner de verkligen behöver och kombinerar detta med POSIX-rättigheter samt MAC-policyer. Filkapaciteter säkerställer att behörigheter är direkt kopplade till binärfilerna och att granskningar tydligt visar vem som får göra vad. Med behörighetsseparering, begränsade behörigheter för containrar och systemanropsfilter begränsar jag skadorna om en sårbarhet utnyttjas. Regelbundna kontroller, strikta ägar- och skrivrättigheter samt en dokumenterad releaseprocess håller tilldelningen smidig. På så sätt förblir servertjänsten funktionsduglig, men Utrymme för manövrering för angripare hålls konsekvent på en låg nivå.


