Med Linux Capabilities opdeler jeg root-rettighederne i små, klart definerede privilegier og reducerer dermed risikoen drastisk. På den måde styrer jeg målrettet, hvilke processer der må udføre bestemte handlinger, og begrænser dermed angrebsfladen for hver enkelt applikation.
Centrale punkter
- Finkornet I stedet for at være almægtig: Opdel root-rettighederne i mindre privilegier.
- Filfunktioner I stedet for Set-UID: Bind de nødvendige rettigheder direkte til binærfilerne.
- Kompetencesæt Konfigurer målrettet: Tilladt, Effektiv, Arvelig, Afgrænsende.
- Adskillelse af privilegier: Adskil tjenester, værktøjer og opgaver strengt fra hinanden.
- Forsvar i dybden: Udvid funktionerne med sudo, roller og logfiler.
Hvorfor adskille root-rettigheder?
En root-konto giver Fuld adgang på fil- og procesniveau, men netop det åbner op for alvorlige fejl. En forkert kommando eller et exploit er nok til at få en hel installation til at bryde sammen. Derfor begrænser jeg omfattende handlinger til det absolut nødvendige og reducerer dermed skadeomfanget og gendannelsestiden. Princippet om minimale rettigheder holder tjenesterne små og overskuelige. Jeg deaktiverer direkte root-login, satser på roller og skriver fuldstændige logfiler.
Linux-kapaciteter kort forklaret
Linux-kapaciteter opdeler den klassiske root-beføjelse i klart afgrænsede Privilegier. Hver proces får kun de komponenter, som den virkelig har brug for til sin opgave, f.eks. tilbindning til porte under 1024 eller afsendelse af specielle signaler. På den måde undgår jeg det tidligere »alt eller intet«-princip. Kernen administrerer disse komponenter for hver proces og implementerer dem strengt. På den måde forbliver kontrollen detaljeret og gennemsigtig.
Teknisk set knytter jeg færdigheder enten til Processer (via deres kompetencesæt) eller til Filer (som udvidet attribut sikkerhed.kapacitet (ELF-binærfiler). Ved execve()-Ved opstart sammenlægger kernen filkapaciteterne med proces-sættene: Enkelt sagt kombineres de tilladte kapaciteter fra filattributten samt de arvelige rettigheder fra den kaldende proces til det nye »Permitted-Set« og – hvis det er markeret – aktiveres de samtidig i »Effective-Set«. Dette undgår Set-UID-omveje og holder privilegier synlige og kontrollerbare.
At forstå kapacitetssæt i en procesmæssig sammenhæng
Hver proces har flere sæt rettigheder, som jeg målrettet kontrol. Permitted-set definerer, hvad en proces i princippet må have. Effective-set fastlægger, hvad der aktuelt er aktivt. Inheritable-set regulerer, hvilke privilegier der kan overføres til underprocesser. Bounding-set sætter en fast øvre grænse og forhindrer, at processer overskrider denne.
Ambient Capabilities og Securebits
Ud over de velkendte sæt findes der også Ambient-sæt, som ved execve() ikke udløber automatisk. Jeg bruger det, når en proces uden privilegier målrettet skal have minimale rettigheder over flere Eksekutor-skal bevare rettighederne på tværs af niveauer (f.eks. ved opkald til eksterne hjælpeprogrammer). Ambient-rettigheder indgår kun i de effektive rettigheder, hvis den påkaldte fil ikke selv angiver filkapaciteter – på den måde forhindrer jeg utilsigtet eskalering.
Med de Securebits Jeg styrer detaljerne i overgangene, f.eks. om en proces efter ændringen af UID må beholde de evner, den tidligere havde (keepcaps) eller om han generelt ikke må opnå nye privilegier (no_new_privs). I praksis indstiller jeg Securebits strengt og går på kompromis med brugervenligheden for at bryde udnyttelseskæder.
Filfunktioner i stedet for Set-UID
Jeg erstatter Set-UID-binærfiler med filkapaciteter for at mindske risikoen for sænke. I stedet for at give et program root-rettigheder, tildeler jeg blot den nødvendige rettighed. En typisk ændring ser sådan ud: setcap 'cap_net_bind_service=+ep' /usr/bin/meinserver. Med getcap -r / Jeg tjekker, hvilke filer der indeholder kompetencer. Det reducerer antallet af eskaleringsveje mærkbart.
Det er vigtigt, at filfunktioner kun anvendes på ELF-binærfiler virker. Interpreter-scripts (f.eks. Python, Bash) arver dem ikke pålideligt. I sådanne tilfælde indkapsler jeg den privilegerede handling i et lille, statisk kontrolleret hjælpeprogram eller bruger socket-aktivering, så min tjeneste slet ikke selv behøver at oprette en forbindelse. Desuden holder jeg øje med filrettigheder: Capabilities giver særlige rettigheder over for kernen, men erstatter ikke ingen almindelige ACL'er eller POSIX-rettigheder.
Når man kopierer eller pakker, går færdigheder hurtigt tabt: cp uden XATTR-understøttelse, forkert indstillet umask eller fjerne et build-artefakt i et filsystem uden udvidede attributter sikkerhed.kapacitet uden at sige noget. Derfor arbejder jeg på en reproducerbar måde og bruger: cp --preserve=xattr ..., tar --xattrs, rsync -X. I pakkebygninger angiver jeg filfunktioner eksplicit i installationsskriptet, tester installationen i en ren VM og kontrollerer getcap i CI.
Adskillelse af privilegier med realistiske scenarier
En webserver skal have adgang til port 80/443, men ikke til kernemoduler eller systemgenstarter, derfor indstiller jeg CAP_NET_BIND_SERVICE og intet andet. En backup-agent må læse og skrive filer, men må ikke ændre netværkskonfigurationen. Et overvågningsværktøj får læseadgang til nøgletal, men har ingen rettigheder til at foretage ændringer. Disse tilpasninger begrænser angreb til det lokale niveau i stedet for at lade dem påvirke hele systemet. Netop denne adskillelse gør tjenesterne håndterbare og holder fejlkonfigurationer i skak.
Kombination af sudo og roller
Funktioner kan ikke erstatte en ordentlig Rollestruktur, de supplerer dem. Jeg tildeler sudo-rettigheder med stor tilbageholdenhed, bruger fulde kommandostier og holder mig væk fra generelle regler som „ALL=(ALL) ALL“. Jeg logger hver eneste tildeling. Grupper samler ansvarsområder, mens kapaciteter sætter tekniske grænser for processer. På den måde skabes der klare ansvarsområder uden overdrevne rettigheder.
Almindelige faldgruber og bedste praksis
- CAP_SYS_ADMIN må ikke bruges som forkortelse: Denne lov er en samlebetegnelse. Jeg erstatter den med mere specifikke alternativer (f.eks.
CAP_SYS_CHROOT,CAP_SYS_TIME,CAP_SYS_NICE) eller lad helt være. - Filerettighederne forbliver strenge: Funktioner sætter ikke generelt DAC ud af spil. Uden
CAP_DAC_OVERRIDEKernen respekterer fortsat ejer- og modusbits. Jeg tildeler derfor fortsat kun minimale læserettigheder. - Hærdning af stien: Når jeg tildeler en binærfil filkapaciteter, forhindrer jeg PATH-spoofing (absolutte stier i
sudoers, begrænsede skriverettigheder til mapper i søgestien). - Start tidligt, start ofte: Processer starter i nogle tilfælde med flere rettigheder end nødvendigt. Jeg fjerner de overflødige rettigheder umiddelbart efter det kritiske trin (
prctl()/libcap) og indstilno_new_privs, hvor det er muligt. - Begræns arv: Jeg holder Inheritable- og Ambient-sættet lille. Underprocesser må ikke åbne nye døre.
- Kontrol af build- og deploy-pipeline: Jeg bekræfter, at
sikkerhed.kapacitetbevares, og at ingen staging-trin (containerlag, NFS, artefakt-scanner) fjerner XATTR’er.
Oversigt over vigtige kompetencer og risici
Inden tildelingen fastlægger jeg klart de nødvendige rettigheder og vurderer risikoen ved dem. Den følgende tabel viser typiske eksempler med virkning og klassificering. Jeg tager altid højde for alternativer for at undgå omfattende rettigheder. Især CAP_SYS_ADMIN Jeg tildeler dem yderst sparsomt. Hvor det er muligt, erstatter jeg bredt definerede privilegier med målrettede, snævre varianter.
| Kapacitet | Formål | Risiko | Eksempel |
|---|---|---|---|
| CAP_NET_BIND_SERVICE | Binde til porte < 1024 | Lav til middel | Webserver på 80/443 |
| CAP_SYS_BOOT | Genstart systemet | Høj | Planlagt genstart |
| CAP_SYS_MODULE | Indlæsning/fjernelse af kerne-moduler | Meget høj | Driveradministration |
| CAP_SYS_ADMIN | Alsidige administrative opgaver | Meget høj | Forskellige vedligeholdelsesopgaver |
| CAP_SETUID / CAP_SETGID | Skift UID/GID | Middel til høj | Skift af ret i tjenesten |
Ud over tabellen er jeg lige i gang med at vurdere CAP_SYS_PTRACE (fejlfinding i processer), CAP_NET_ADMIN (netværksparametrisering) og CAP_DAC_OVERRIDE (Omgåelse af filadgangsbegrænsninger) er yderst kritisk. Der findes ofte mønstre, der undgår disse rettigheder: dedikerede metrik-endepunkter i stedet for process-snooping, socket-aktivering eller port-videresendelse i stedet for bind-rettigheder og veldefinerede filrettigheder i stedet for generel omgåelse af DAC.
Hærdning i containere og hosting
I multi-tenant-miljøer anser jeg kompetencer for at være radikalt lille og forhindrer arv i underprocesser. Containere drager stor fordel af det, så snart bounding-sættet er stramt defineret. Jeg kombinerer dette med isolerede filsystem- og procesrum. Denne introduktion hjælper mig med at få et overblik over isoleringsmetoder Procesisolering. På den måde forbliver tjenesterne adskilte, selv hvis et program svigter.
I praksis indstiller jeg som standard containere til „slet alt, tilføj specifikt“: --cap-drop=ALL --cap-add=NET_BIND_SERVICE til webtjenester, ingen mount-rettigheder, ingen SYS_ADMIN. I orkestrerede miljøer opbevarer jeg profilen centralt og kontrollerer den i politikker. Vigtigt: Jeg stoler ikke på filrettigheder i billedet, men tildeler rettigheder under kørsel i orkestratoren – på en måde, der kan gentages og kontrolleres.
Samspil med SELinux og AppArmor
Capabilities styrer, hvad en proces må gøre, mens MAC-profiler fastlægger, hvad den har adgang til, og de to fungerer i harmoni godt. Jeg definerer »capabilities« snævert og lader SELinux eller AppArmor begrænse adgangen til filer og sockets. Det skaber et lagbeskyttelse, der stiller flere hindringer i vejen for exploits. Her finder jeg en hurtig sammenligning: SELinux kontra AppArmor. Dermed forbliver en kompromitteret tjeneste isoleret og kan forårsage mindre skade.
Praksis: Gå frem trin for trin
Jeg begynder med at lave en oversigt over alle tjenester og deres Kravene. Derefter fjerner jeg unødvendige Set-UID-binærfiler eller erstatter dem med målrettede filrettigheder. Jeg konfigurerer sudo restriktivt og dokumenterer hver enkelt indtastning. Jeg tildeler opgaver til roller og grupper og holder rettighederne på et minimum. Derefter tester jeg systemet under belastning og gennemgår logposterne for uventede afvisninger.
En kort tjekliste hjælper mig med overgangen:
- Kravene til hver tjeneste skal fastlægges skriftligt (kun det, der virkelig er nødvendigt).
- Oversigt over eksisterende særrettigheder (
find / -perm -4000,getcap -r /). - Målrettet udskiftning: Afskaf Set-UID, indstil filkapaciteter, fjern rettigheder i god tid.
- Luk arv: Stram bounding-sættet, minimer Inheritable/Ambient.
- Sikring af systemd-/container-profiler (
CapabilityBoundingSet=,NoNewPrivileges=yes). - Test under belastning, gennemgå logfiler og revisionsposter, dokumenter undtagelser.
Overvågning, navneområder og løbende revisioner
Jeg overvåger logfiler, alarmer og systemkald, så uønskede handlinger straks skille sig ud. Jeg kontrollerer regelmæssigt ændringer i capabiliteter, sudo-regler og roller. Hvor det er hensigtsmæssigt, adskiller jeg desuden arbejdsbelastninger ved hjælp af kernel-isoleringsmekanismer. Dette overblik giver et godt udgangspunkt for Navneområder og cgroups. På den måde opdager jeg afvigelser i god tid og holder omgivelserne rene.
I hverdagen bruger jeg enkle tests: capsh --print viser mig den aktuelle sæt af færdigheder, getpcaps opregner procesrettigheder og i /proc//status læser jeg CapEff, CapPrm, CapBnd. Med auditd Jeg følger med i ændringer i kapacitetsstatus (f.eks. regel til capset), sammenholder jeg hændelser med implementeringer og opretter alarmer, hvis der pludselig dukker omfattende rettigheder op. I komplicerede tilfælde hjælper det mig at strace -e capget,capset, for at synliggøre manipulationer af rettigheder.
Praktiske eksempler på systemd og containere
Mange tjenester kører jeg som systemd-enheder, hvor jeg indkapsler rettighederne:
CapabilityBoundingSet=CAP_NET_BIND_SERVICEbegrænser det tilgængelige rettighedsvindue til det absolut nødvendige.AmbientCapabilities=CAP_NET_BIND_SERVICEgiver tjenesten ret til at oprette en forbindelse til port 80/443 uden filfunktioner.NoNewPrivileges=yesforhindrer senere udvidelser af rettighederne.Bruger=,Gruppe=,ProtectSystem=strict,PrivateTmp=yesfuldender isoleringen.
I containere starter jeg processer så minimalt som muligt: docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE --read-only. Til kortvarige opgaver bruger jeg kørselstidsfunktioner i stedet for filfunktioner i billedet, så build-processerne forbliver reproducerbare, og rettighederne er bundet til miljøet.
Konkrete migreringer fra praksis
- ping uden Set-UID: I stedet for
setuid rootsætter jegsetcap 'cap_net_raw=+ep' /bin/ping. Dermed kan enhver bruger åbne ICMP-sockets uden fulde root-rettigheder. Jeg tjekker regelmæssigt medgetcap /bin/ping, om attributten er bevaret. - Webtjeneste på port 80/443: Jeg kører min tjeneste som en bruger uden særlige rettigheder og indtaster kun
cap_net_bind_service. Hvis tjenesten alligevel kører bag en reverse proxy, kan jeg alternativt også binde den til port 80/443 der og bruge en høj port internt – helt uden yderligere kompetencer. - Skift af parter i retssagen: For værktøjer, der kortvarigt har brug for udvidede rettigheder (f.eks. til at indstille nice-niveauer), indstiller jeg
cap_sys_nice, udfør handlingen tidligt og slip derefter evnen igen. Jeg undgår varigt udvidede rettigheder.
Grænser og alternativer
Det er ikke alle anvendelsessituationer, der kræver Capabilities. Ofte findes der sikre alternativer med lavere risiko:
- Aktivering af stik: Init-tjenesten (f.eks. systemd) åbner privilegerede sockets og videregiver dem til processen. Min tjeneste behøver derfor ikke Bind-rettigheder.
- Port-videresendelse: Ved hjælp af firewall-regler omdirigerer jeg 80/443 til en høj port. Tjenesten forbliver uden privilegier, og systemets adfærd ændres ikke.
- Ikke-privilegerede low-ports: Hvor det er hensigtsmæssigt, kan jeg hæve tærsklen for ikke-privilegerede porte. Det udvider dog handlingsrummet for alle processer – jeg afvejer nøje risiko og bekvemmelighed.
- Små hjælpere i stedet for altmuligmænd: Hellere en lille, testet binærfil med præcis én funktion end en stor monolit med et bredt udvalg af rettigheder.
Kort opsummeret
Med Linux-funktioner Jeg opdeler root-rettigheder i små, let håndterbare privilegier. Filkapaciteter erstatter risikable Set-UID-binærfiler og mindsker konsekvenserne af et angreb. I kombination med strenge sudo-regler, roller og MAC-profiler skabes der et lagdelt sikkerhedssystem med klare grænser. Bounding- og Inheritable-sæt begrænser arv og holder processerne på rette spor. Ved at følge denne fremgangsmåde mindskes angrebsfladen mærkbart, og administrationsbyrden holdes på et overskueligt niveau.


