- SELinux lägger till obligatorisk åtkomstkontroll till Linuxkärnan genom taggar och policyer som går utöver traditionella DAC-behörigheter.
- Säkerhetskontexter (användare, roll, typ, nivå) och typbaserade policyer möjliggör mycket detaljerad åtkomstkontroll över processer, filer och portar.
- Verktyg som getenforce, chcon, semanage, semodule och booleans underlättar den praktiska hanteringen av SELinux i produktion.
- När SELinux är korrekt konfigurerat minskar det nolldagsangrepp och felkonfigurationer genom att strikt begränsa vad varje tjänst eller applikation kan göra.

SELinux kanske låter som teknik reserverad för kärnnördar, men det är faktiskt ett av de kraftfullaste säkerhetsverktygen som finns tillgängliga i Linux idag . Om du hanterar servrar, Docker-containersäkerhet , molninfrastruktur eller till och med något känsliga stationära datorer, gör förståelsen för hur SELinux fungerar hela skillnaden mellan ett system som helt enkelt är "välkonfigurerat" och ett som är svårt att kompromettera, även med nolldagssårbarheter.
Trots sitt rykte om sig att vara "komplicerat" erbjuder SELinux en mycket logisk modell: den definierar vad varje process kan göra och vilka objekt den kan kommunicera med, och om något avviker från det skriptet stoppar kärnan det omedelbart . Istället för att blint lita på att roten kommer att bete sig korrekt eller att dina daemoner inte kommer att ha buggar, tillämpar SELinux obligatorisk åtkomstkontroll som gäller även för superanvändaren, med hjälp av mycket detaljerade etiketter och policyer.
Vad är SELinux och vilket problem löser det?
Security-Enhanced Linux (SELinux) är en säkerhetsmodul för Linuxkärnan baserad på LSM (Linux Security Modules). Den utvecklades ursprungligen av NSA i samarbete med Red Hat och andra partners, och sedan kärnversion 2.6 har den varit en officiell del av kärnan. Det är inte en separat applikation, utan snarare ett kärntillägg som lägger till ett obligatoriskt åtkomstkontrollsystem (MAC) och rollbaserad åtkomstkontroll (RBAC).
Till skillnad från den klassiska Unix-åtkomstkontrollen (DAC) – ägare , grupp, andra och rwx-behörigheter – baseras åtkomstbeslut i SELinux inte på filägarens val, utan snarare på en global policy som fastställts av säkerhetsadministratören. DAC finns fortfarande kvar och har företräde: om DAC nekar ingriper inte SELinux; men även om DAC tillåter kan SELinux fortfarande blockera operationen enligt sin policy.
SELinux-arkitekturen separerar tydligt komponenterna: å ena sidan kärnkoden som fattar säkerhetsbeslut , och å andra sidan policymodulerna som definierar vad som är tillåtet och vad som inte är det. Denna separation möjliggör justering av reglerna utan att kompilera om kärnan och effektiviserar antalet komponenter som kan påverka systemsäkerheten.
SELinux har antagits som standard i distributioner som Fedora, Red Hat Enterprise Linux, CentOS och Scientific Linux, och är även djupt integrerat i system som Android, där det används för att begränsa systemprocesser och appar till mycket specifika domäner. I BSD- och GNU/Linux-världen finns det alternativ som AppArmor, TOMOYO och TrustedBSD (på macOS/FreeBSD), men SELinux utmärker sig genom den granularitetsnivå det erbjuder över alla systemobjekt.
Från DAC till MAC: varför den klassiska modellen inte längre räcker till
I ett traditionellt Unix-system hanteras domän-objektmodellen med hjälp av DAC: varje fil eller resurs har en ägare och behörigheter, och alla processer som körs som den användaren kan göra vad de vill med dessa resurser . Det betyder att om en daemon körs som root, kan alla exploaterbara buggar öppna dörren för att kontrollera halva systemet med dess root-kontext.
Typiska exempel inkluderar databaser vars datafiler endast ska manipuleras via DBMS, men som faktiskt är läsbara och modifierbara av processer med rot-UID:t ; eller kritiska daemoner som körs med för många privilegier. Ett programmeringsfel, ett buffertöverskott eller dålig inmatningsvalidering kan förvandla tjänsten till en motorväg för hela systemet.
SELinux lägger till ett obligatoriskt åtkomstkontrolllager (MAC) ovanpå DAC. "Obligatoriskt" betyder att åtkomstkontrollen definieras centralt av administratören genom policyer, och varken användare eller processer kan lätta på dessa regler på egen hand. Operativsystemet upprätthåller dessa policyer genom att utvärdera varje relevant kärnoperation innan den tillåts.
Kärnan, med hjälp av LSM-hooks, frågar SELinux vid varje känsligt systemanrop (öppning av filer, skapande av sockets, montering av filsystem, kommunikation via IPC, etc.). Vid varje beslutspunkt utvärderar SELinux operationen baserat på den laddade policyn och säkerhetskontexten för subjektet och objektet . Om policyn inte uttryckligen ger behörighet nekas åtgärden, oavsett om processen är root eller inte.
Driftlägen: tvingande, tillåtande och inaktiverade
SELinux kan fungera i tre tydligt differentierade driftlägen, vilka är viktiga att förstå för att undvika att bli galen i produktionen:
- drivaSELinux är aktiverat och tillämpar policyn fullt ut. Alla åtgärder som inte tillåts enligt reglerna blockeras och loggas.
- TolerantSELinux är aktivt, laddar policyn och märker filsystemet, men blockerar inte Den registrerar bara transaktionerna som om de nekades. Detta är idealiskt för felsökning och justering av policyer.
- DisabledSELinux är inaktiverat. Inga policyer tillämpas och ingen taggning utförs. Systemet använder den klassiska DAC-modellen.
För snabba och tillfälliga ändringar mellan tvingande och tillåtande lägen används kommandot `setenforce` , där läget anges som 0 (tillåtande) eller 1 (tvingande). Det är viktigt att veta att denna ändring är volatil: efter nästa omstart återgår läget till det som definierats i konfigurationen.
Om du behöver en permanent ändring måste du redigera filen. /etc/selinux/config (eller /etc/sysconfig/selinux i vissa distributioner) och justera värdet på direktivet SELINUX=disabled|permissive|enforcingÄndringarna kommer att tillämpas vid nästa uppstart och kommer i många fall att innebära att filsystemet namnges om.
För att kontrollera det aktiva läget kan du använda kommandon som getenforce eller sestatus . Det förra returnerar helt enkelt Enforcing, Permissive eller Disabled; det senare ger en mer fullständig sammanfattning av SELinux-status, laddade policyer och aktiva moduler.
Säkerhetskontexter och märkningssystem
Hjärtat i SELinux är dess system av säkerhetsetiketter eller kontexter . Varje fil, process, nätverksport, socket, enhet etc. har en associerad kontext som beskriver hur den kan användas. Denna kontext består av flera fält som tillsammans bildar SELinux vy av det objektet.
Det allmänna formatet för ett kontext är user_u:role_r:type_t:level , med vissa nyanser beroende på policyn (särskilt om MLS/MCS används). Varje fält har ett specifikt syfte: SELinux-användaren, rollen, typen (även kallad domän när det refereras till processer) och känslighetsnivån eller kategorin.
I praktiken är det mest kritiska elementet typen (det tredje fältet), eftersom den stora majoriteten av policyregler formuleras som relationer mellan typer . Till exempel att tillåta processer av typen httpd_t att komma åt filer märkta httpd_sys_content_t, eller att tillåta en specifik domän att kommunicera med sockets märkta http_port_t.
Dessa kontexter lagras som utökade filsystemattributDärför är det viktigt att använda filsystem som stöder xattrs (som ext4, XFS, etc.). När det gäller processer exponeras den aktuella kontexten och andra relaterade kontexter genom pseudofilsystemet. /proc/<pid>/attr/ i filer som current, exec, fscreate, prev, sockcreate eller keycreate.
Typiska exempel på sammanhang i ett system med riktad policy skulle vara:
- system_u:object_r:httpd_sys_content_t:s0 för webbinnehåll som serveras av Apache eller Nginx.
- system_u:objekt_r:hemanvändare_t:s0 för användarnas hemkataloger.
- system_u:system_r:httpd_t:s0 för själva webbserverns exekveringsdomän.
Att bryta ner komponenterna i SELinux-kontexten
När du stöter på ett sammanhang som unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 , kan det verka som hieroglyfer, men varje del motsvarar ett specifikt koncept inom SELinux och dess referenspolicy.
El SELinux-användare (enligt konvention med suffix) _uDetta är inte samma sak som Unix-användaren i /etc/passwd. SELinux underhåller sin egen användardatabas och mappar dem till Linux-användare. En SELinux-användare kan gruppera flera Unix-användare, eftersom idén är att MAC-lagret ska vara oberoende av DAC:n.
El SELinux-roll (med suffix _rDetta definierar vilka roller en användare eller domän kan anta. Om det används strikt kallas det fullständig RBAC. De flesta filobjekt använder rollen object_r, medan roller som system_r, user_r, staff_r eller sysadm_r tillämpas på processer beroende på vilket säkerhetskontext de måste anta.
El SELinux-typ eller domän (ändelse _tI praktiken är typen det avgörande elementet. Typen beskriver objektklassen eller exekveringsdomänen för en process. Policyn specificerar vilka interaktioner som är tillåtna mellan typer: vilka domäner som kan läsa, skriva, exekvera eller kommunicera med vilka andra typer av objekt.
Nivåer och kategorier används när policyer för säkerhet på flera nivåer (MLS) eller säkerhet på flera kategorier (MCS) är aktiverade. Känsligheter är hierarkiska (t.ex. s0, s1, etc.), medan kategorier inte är det (c0, c1, c2, ...). I mycket kritiska miljöer – till exempel vissa myndigheter – används de för att säkerställa att data bara kan läsas nedåt och skrivas till samma nivå eller uppåt , och för att isolera data enligt mycket specifika fack.
SELinux-policyer: riktade, strikta, MLS/MCS och modularitet
Säkerheten som upprätthålls av SELinux bestäms av den laddade policyn . En policy är helt enkelt en stor uppsättning regler som beskriver vilka domäner som kan göra vad på vilka typer, såväl som andra element (övergångar, taggningsregler etc.). Distributioner paketerar vanligtvis standardpolicyer så att du inte behöver skriva allt från grunden.
Den vanligaste policyn kallas riktad . I det här läget körs endast specifika processer – främst nätverkstjänster och högriskdaemoner som Apache, Nginx, DNS, proxyservrar, SNMP, syslog etc. – inom begränsade domäner. Alla andra användarprocesser körs i "obegränsade" domäner, där standard Linux-säkerhet i huvudsak tillämpas, tillsammans med loggning av vissa åtgärder.
Det finns också den strikta policyn , där praktiskt taget alla processer är begränsade till en specifik policy. Den är mycket säkrare, men den kan också vara betydligt svårare att underhålla om modellen inte är väl förstådd, eftersom eventuella avvikelser i etiketter eller regler kan störa standardarbetsflöden.
För högsäkerhetsmiljöer finns MLS/MCS-policyer (Multi-Level/Multi-Category Security) som utnyttjar känsligheter och kategorier för att införa ännu finare kontroller. Dessa är typiska för mycket rigida militära eller administrativa miljöer och används sällan utanför specifika sammanhang på grund av deras höga operativa komplexitet.
Moderna policyer distribueras modulärt . Istället för en enda monolitisk policyfil används separata moduler för specifika tjänster, vilket avsevärt förenklar hantering och uppdateringar. Dessa moduler hanteras med verktyg som semodule och semanage module , som låter dig installera, ta bort, aktivera eller inaktivera delar av policyn utan att kompilera om hela policyn varje gång.
Hur SELinux bestämmer: subjekt, objekt, klasser och behörigheter
När en process (subjektet) försöker komma åt en resurs (objektet) ställer SELinux konceptuellt frågan: "Kan en domän av typ X utföra operation Y på ett objekt av typ Z som tillhör klass C?" . Svaret söks sedan i policyn genom de definierade reglerna.
I Type Enforcement (TE)-policyer, som används av de flesta distributioner och Android, tillhör varje objekt en klass (fil, dir, fifo_file, tcp_socket, process, etc.) och policyn definierar vilka behörigheter som är möjliga för varje klass: läsa, skriva, exekvera, binda, ansluta, getattr, öppna och en lång fil.
TE-regler uttrycks mycket direkt. Ett enkelt exempel skulle vara:
tillåt httpd_t http_port_t:tcp_socket namn_bind;
Med den här regeln indikerar policyn att processer i httpd_t-domänen kan utföra name_bind-operationen på TCP-sockets märkta http_port_t. Metoden fokuserar på objekttyper och klasser, inte specifika sökvägar , vilket förhindrar överraskningar vid flytt av filer eller ändring av katalogstrukturer.
I Android, till exempel, används SELinux-attribut för att gruppera typer under mer generella etiketter som `appdomain` , så att en enda regel kan gälla för flera domäner (`untrusted_app`, `isolated_app`, etc.) utan att upprepa definitioner. Makron som `rw_file_perms` används också för att gruppera flera vanliga filbehörigheter och minska fel orsakade av förbiseenden.
Interna statusar, AVC och avslagsregister
När en åtkomstförfrågan inträffar konsulterar SELinux först Access Vector Cache (AVC) , en cache som lagrar de senaste åtkomstbesluten för att påskynda processen. Om beslutet redan finns i cachen används den direkt; annars frågas brandväggen (den interna delen av SELinux i kärnan), som utvärderar operationen baserat på policyn och subjekt- och objektkontexten.
Om det inte finns någon regel som uttryckligen tillåter den begärda åtgärden är standardbeslutet att neka . Denna "neka som standard"-filosofi är en av grundpelarna i SELinux och det som ger den dess robusthet mot tillåtande konfigurationsfel.
När en avslag sker i tvingande läge loggar kärnan ett meddelande av typen avc: nekad i systemloggarna. Beroende på distributionen kan den visas i /var/log/audit/audit.logVid /var/log/messages eller fångas upp av auditd-daemonen. Dessa meddelanden inkluderar processkontexten (context), objektkontexten (tcontext), klassen, den begärda operationen och annan data som är mycket användbar för felsökning.
I tillåtande läge är operationen tillåten men händelsen avc: denied genereras fortfarande , markerad med permissive=1. Detta är rent guld för att bygga och justera policyer, eftersom det låter dig se vad som skulle orsaka förstörelse i systemet om tillämpning implementerades utan att avbryta normal drift.
Integrera SELinux i distributioner och Android
I Linux-server- och skrivbordsekosystemet är SELinux aktiverat som standard i Fedora, RHEL, CentOS och derivatorDebian och Ubuntu erbjuder fullt stöd i sina kärnor och paket, även om aktivering vanligtvis är valfritt och kräver installation av paket som selinux-basics, selinux-policy-default och auditd, följt av global omtaggning med fixfiles relabel.
Android införlivade initialt SELinux i version 4.3 i permissivt läge, övergick till delvis användning i 4.4 (endast för kritiska domäner som installd, netd, vold och zygote), och har varit helt integrerat sedan Android 5.0 . Androids policy fokuserar på att isolera appar, systemtjänster och känsliga processer med hjälp av typer och attribut, i syfte att minimera effekten av en kompromiss på någon av dessa komponenter.
Android använder koncept som typen untrusted_app för vanliga applikationsprocesser, appdomain-attribut för att gruppera appdomäner och MLS/MCS-kategorier för att isolera data mellan appar och mellan fysiska användare. Allt detta fungerar tillsammans för att förhindra att en komprometterad applikation undkommer sin sandlåda, även om den får mycket breda användarbehörigheter.
Viktigt: Android förenklar SELinux-modellen genom att ignorera användare, roller och avancerade känsligheter. Det finns bara en SELinux-användare (u), två grundläggande roller (r för subjekt och object_r för objekt), och känsligheten är alltid s0. Kategorier är det som gör skillnaden för dataisolering.
Jämförelse med AppArmor och andra LSM:er
I många diskussioner uppstår oundvikligen jämförelsen mellan SELinux och AppArmor , eftersom båda är Linux-säkerhetsmoduler och erbjuder MAC-adresser. Deras tillvägagångssätt är dock helt olika, och det är värt att förstå detta innan man väljer den ena eller den andra för sin miljö.
SELinux definierar en policy centrerad kring objekt och deras typer: varje objekt i systemet (filer, processer, sockets, portar, enheter, IPC:er, etc.) tilldelas en etikett. Åtkomstbeslut fattas baserat på subjekt- och objektkontexter, utan att vara beroende av den exakta filsökvägen. Detta gör systemet mer stabilt vid ändringar i katalogstrukturen eller alternativa filsystemvyer (chroot, containrar, bind-mounts, etc.).
AppArmor, å andra sidan, tillämpar en uppgiftscentrerad , sökvägsbaserad policy. Den definierar profiler för varje program och anger vilka filsökvägar, portar etc. som den kan komma åt och med vilka behörigheter. Den är mer intuitiv att konfigurera och generellt mer användarvänlig för administratörer som inte vill bli experter på SELinux, men dess kontroll är något mindre detaljerad och mer beroende av filsystemets struktur.
Båda delar principen att neka som standard, men de tillämpar den på olika sätt: AppArmor nekar som standard endast de uppgifter som täcks med profiler, medan SELinux, i strikt läge, utökar den till hela systemet och alla taggade objekt. Som ett resultat erbjuder SELinux vanligtvis en djupare nivå av instängning , på bekostnad av en mer omfattande och komplex policy.
Praktiska verktyg för att hantera SELinux
Att arbeta med SELinux förlitar sig på en serie kommandoradsverktyg som förenklar hanteringen av lägen, taggning, booleska värden och policymoduler. Även om detta kan verka som en överväldigande arsenal till en början, täcker ett fåtal verktyg de flesta dagliga uppgifter.
För att visa säkerhetskontexten för filer och processer kan du använda alternativet -Z i vanliga kommandon som ls, ps eller id. Till exempel, ls -Z Förutom DAC-behörigheter visar den SELinux-kontexten för varje fil, så att du snabbt kan kontrollera om taggningen är som förväntat.
Kommandot `chcon` ("ändra kontext") låter dig manuellt ändra hela kontexten för en fil eller bara specifika delar (roll, typ, intervall) med hjälp av alternativ som `-r`, `-to` och `-l`. Det är användbart för engångskorrigeringar, men det är viktigt att komma ihåg att dina ändringar kan gå förlorade om etiketten tillämpas igen enligt policyn med verktyg som `restorecon` eller `fixfiles`.
Semanage- verktyget är den schweiziska armékniven för hantering av runtime-policyer. Med olika underkommandon kan du hantera permanenta filkontexter (fcontext), inloggningsmappningar mellan Linux- och SELinux-användare (login), SELinux-användare och deras roller (user), taggade portar (port), booleska värden och till och med policymoduler. Allt detta utan att behöva kompilera om hela policyn från källkoden.
För att kontrollera och ändra tillståndet för booleska värden – små brytare som aktiverar eller inaktiverar regelblock inom policyn – används getsebool och setsebool , utöver själva setsebool-värdet . Ett typiskt booleskt värde är httpd_enable_homedirs, vilket, när det är aktivt, tillåter webbservern att komma åt användarnas hemkataloger (användbart för ~user/public_html/).
Slutligen tillåter kommandon som fixfiles dig att tvinga fram en fullständig ommärkning av filsystemet enligt de definierade reglerna, och semodule tar hand om att installera, lista, aktivera eller inaktivera policymoduler (.pp) som paketeras och distribueras av referenspolicyn eller av administratören.
Skapande och justering av anpassade policyer
När en applikation inte har en egen SELinux-modul eller om du behöver mer specifik begränsning är det dags att sätta igång och skapa anpassade policyer . Det kanske låter komplicerat, men arbetsflödet är ganska väldefinierat om du följer vissa steg noggrant.
Det första steget är att säkerställa att relevanta objekt (körbara filer, datakataloger, sockets etc.) är märkta med lämpliga typer. Detta kan uppnås genom att definiera filkontextregler med ` semanage fcontext` och tillämpa dem med `restorecon`, med hjälp av reguljära uttryck för att omfatta hela katalogträd.
Systemet sätts sedan vanligtvis i tillåtande läge för den maskinen (eller, i vissa fall, för en specifik domän) och applikationen tillåts köras normalt medan SELinux loggar alla ` avc: denied`-satser som skulle ha inträffat. Dessa loggar, vanligtvis analyserade med verktyg som audit2allow , används för att extrahera kandidatregler.
Referenspolicyer är vanligtvis strukturerade i tre filer per applikation: en .te-fil som innehåller TE-regler (allow, type, domain_type, etc.), en .fc-fil som innehåller filkontextregler och en .if-fil som innehåller publika gränssnitt som andra moduler kan återanvända. Allt detta kompileras till .pp-moduler med hjälp av make och laddas med semodule.
Det är avgörande att inte blint lita på allt som audit2allow föreslår: det tenderar att vara mer tillåtande än absolut nödvändigt . Helst bör du manuellt granska de föreslagna reglerna, skapa nya typer där det är lämpligt för att separera känsliga data från irrelevanta data, och när en nekad åtgärd inte är kritisk, överväga att använda dontaudit-regler för att stoppa inspelning av brus utan att bevilja behörigheter.
I miljöer som SUSE Linux Micro eller Android tillhandahålls ytterligare verktyg (till exempel Udica för att generera containerpolicyer från JSON-beskrivningar) som automatiserar en del av processen genom att snabbt anpassa policyn till specifika containrar utan att behöva lära sig hela policyspråket från grunden.
Hela detta ekosystem av kontexter, modulära policyer, booleska värden och hanteringsverktyg gör SELinux till en extremt robust och flexibel säkerhetsplattform . Med en viss initial investering i inlärning möjliggör det mycket exakta begränsningar av vad varje tjänst eller applikation kan göra, vilket drastiskt härdar systemets attackyta mot exploateringar, skadlig kod och mänskliga fel.
Index
- 1 Vad är SELinux och vilket problem löser det?
- 2 Från DAC till MAC: varför den klassiska modellen inte längre räcker till
- 3 Driftlägen: tvingande, tillåtande och inaktiverade
- 4 Säkerhetskontexter och märkningssystem
- 5 Att bryta ner komponenterna i SELinux-kontexten
- 6 SELinux-policyer: riktade, strikta, MLS/MCS och modularitet
- 7 Hur SELinux bestämmer: subjekt, objekt, klasser och behörigheter
- 8 Interna statusar, AVC och avslagsregister
- 9 Integrera SELinux i distributioner och Android
- 10 Jämförelse med AppArmor och andra LSM:er
- 11 Praktiska verktyg för att hantera SELinux
- 12 Skapande och justering av anpassade policyer