Product SiteDocumentation Site

14.5. Introduksjon til SELinux

14.5.1. Prinsipper

SELinux (Security Enhanced Linux) er et Mandatory Access Control-system som bygger på Linux sin LSM-grensesnitt (Linux Security Modules). I praksis spør kjernen SELinux før hver systempåkalling for å vite om prosessen er autorisert til å gjøre den gitte operasjonen.
SELinux bruker et sett med regler - kollektivt kjent som en policy - for å godkjenne eller forby operasjoner. Disse reglene er vanskelige å lage. Heldigvis er to standardregler (targeted (målrettet) og strict (strengt)) laget for å unngå mesteparten av oppsettsarbeidet.
Med SELinux er håndteringen av rettighetene helt forskjellig fra tradisjonelle Unix-systemer. Rettighetene til en prosess er avhengig av sin sikkerhetskontekst . Denne konteksten er definert av identiteten til brukeren som startet prosessen, rollen og domenet som brukeren hadde med seg på det tidspunktet. Rettighetene er egentlig avhengig av domenet, men overgangene mellom domenene er kontrollert av rollene. Til slutt; de mulige overgangene mellom roller avhenger av identiteten.
Sikkerhetskontekster og Unix-brukere

Figur 14.1. Sikkerhetskontekster og Unix-brukere

I praksis får brukeren, under innlogging, tildelt en forvalgt sikkerhetskontekst (avhengig av hvilke roller de skal være i stand til å støtte). Dette definerer det gjeldende domenet, og dermed domenet som alle nye avleggerprosesser vil ha. Hvis du ønsker å endre nåværende rolle og tilhørende domene, må du påkalle newrole -r rolle_r -t domene_t (det er vanligvis bare ett enkelt domene som er tillatt for en gitt rolle, -t-parameteren kan derfor utelates). Denne kommandoen godkjenner deg ved å be deg skrive inn passordet ditt. Denne funksjonen forbyr programmer å automatisk bytte roller. Slike endringer kan bare skje dersom de er uttrykkelig tillatt i SELinux-praksis.
Selvsagt gjelder ikke rettighetene for alle objekter (filer, kataloger, stikkontakter, enheter og så videre). De kan variere fra objekt til objekt. For å oppnå dette blir hvert objekt assosiert med en type (dette kalles merking). Domenene sine rettigheter er dermed uttrykt med sett av (ikke-)tillatte operasjoner for disse typene (og, indirekte, for alle objekter som er merket med den gitte typen).
Som standard arver et program sitt domene fra brukeren som startet det, men standard SELinux-politikk forventer at mange viktige programmer kjører i øremerkede domener. For å oppnå dette er disse kjørbare filer merket med en øremerket type (for eksempel er ssh_t merket med ssh_exec_t, og når et program starter, skifter det automatisk til ssh_t-domenet). Denne automatiske domene-overgangsmekanismen gjør det mulig å gi bare de rettigheter som kreves av hvert program. Dette er et grunnleggende prinsipp for SELinux.
Automatiske overganger mellom domener

Figur 14.2. Automatiske overganger mellom domener

14.5.2. Oppsett av SELinux

SELinux-støtte er innebygd i standardkjernene som følger med Debian. De grunnleggende Unix-verktøyene støtter SELinux uten noen modifikasjoner. Det er dermed relativt enkelt å aktivere SELinux.
Kommandoen apt install selinux-basics selinux-policy-default auditd vil automatisk installere de nødvendige pakkene for oppsett av et SELinux-system.
Pakken selinux-policy-default inneholder et sett med vanlige regler. Som standard begrenser disse reglene kun tilgang til noen allment synlige tjenester. Brukerøkter er ikke begrenset, og det er derfor usannsynlig at SELinux ville blokkere legitime brukeroperasjoner. Men dette forbedrer sikkerheten i systemtjenester som kjører på maskinen. For å sette opp et opplegg som tilsvarer de gamle «strenge» reglene, er det bare å deaktivere unconfined-modulen (modulhåndtering er beskrevet nærmere i denne seksjonen).
Når opplegget er installert, bør du merke alle tilgjengelige filer (som betyr å tildele dem en type). Denne operasjonen må startes manuelt med fixfiles relabel.
SELinux-systemet er nå klart. For å aktivere det bør du legge selinux=1 security=selinux-parameteret til Linux-kjernen. Parameteret audit=1 aktiverer SELinux-logging med registrering av alle de nektede operasjonene. Endelig tar enforcing=1-parameteret reglene i bruk: Uten det virker SELinux i sin standard tillatende modus der avviste handlinger logges, men fremdeles blir utført. Du bør derfor endre GRUBs oppsettsfil for oppstart ved å legge til de ønskede parameterne. En enkel måte å gjøre dette på er å modifisere GRUB_CMDLINE_LINUX-variabelen i /etc/default/grub, og så å kjøre update-grub. Etter omstart vil SELinux være aktivert.
Det er verdt å merke seg at selinux-activate-skriptet automatiserer disse operasjonene, og tvinger en merking ved neste oppstart (som unngår nye ikke-merkede filer som ble opprettet mens SELinux ennå ikke var aktiv, og mens merking foregikk).

14.5.3. Å håndtere et SELinux-system

SELinux-opplegget er et modulbasert sett med regler, og installasjonen oppdager og aktiverer automatisk alle relevante moduler basert på de allerede installerte tjenestene. Systemet er dermed umiddelbart i drift. Men når en tjeneste er installert etter SELinux-opplegget, må du klare å aktivere den tilsvarende modulen manuelt. Det er hensikten med semodule-kommandoen. Videre må du klare å definere rollene som hver bruker kan slutte seg til, og dette kan gjøres med semanage-kommandoen.
De to kommandoene kan dermed brukes til å endre det gjeldende SELinux-oppsettet, lagret i /etc/selinux/default/. I motsetning til andre oppsettfiler du finner i /etc/, skal ikke alle disse filene endres for hånd. Du bør bruke programmer som er laget til dette formålet.

14.5.3.1. Å håndtere SELinux-moduler

Tilgjengelige SELinux-moduler er lagret i /usr/share/selinux/default/-mappen. For å aktivere en av disse modulene i det gjeldende oppsettet bør du bruke semodule -i modul.pp.bz2. Forlengelsen pp.bz2 står for policy package (regelpakke) (komprimert med bzip2).
Å fjerne en modul fra det gjeldende oppsettet gjøres med semodule -r modul. Til slutt, lister semodule -l-kommandoen modulene som er installert. De gir også sine versjonsnumre. Moduler kan selektivt aktiveres med semodule -e, og slås av med semodule -d.
# semodule -i /usr/share/selinux/default/abrt.pp.bz2
libsemanage.semanage_direct_install_info: abrt module will be disabled after install as there is a disabled instance of this module present in the system.
# semodule -l
accountsd
acct
[...]
# semodule -e abrt
# semodule -d accountsd
# semodule -l
abrt
acct
[...]
# semodule -r abrt
libsemanage.semanage_direct_remove_key: abrt module at priority 100 is now active.
semodule laster umiddelbart det nye oppsettet om ikke du bruker dens -n-valg. Det er verdt å merke seg at programmet er standard på det gjeldende oppsettet (som er angitt av SELINUXTYPE-variabelen i /etc/selinux/config), men at du kan endre en annen ved å spesifisere den med -s-valget.

14.5.3.2. Håndtering av identiteter

Hver gang en bruker logger inn, får den tildelt en SELinux-identitet. Denne identiteten definerer rollene brukeren kan støtte. Disse to koblingene (fra brukeren til identiteten, og fra denne identiteten til roller) kan settes opp med semanage-kommandoen.
Du bør absolutt lese manualsiden semanage(8). Alle de administrerte konseptene har sin egen manualside; for eksempel semanage-login(8). Selv om kommandosyntaksen tenderer til å være lik for alle begrepene som håndteres, anbefales det å lese manualsiden. Du finner vanlige valg til de fleste underkommandoer: -a for å legge til, -d for å fjerne, -m for å modifisere, -l til å liste, og -t for å indikere en type (eller et domene).
semanage login -l lister gjeldende koblinger mellom brukeridentifikatorer og SELinux-identiteter. Brukere som ikke har noen eksplisitt angitt oppføring, får koblet sin identitet til __default__-oppføringen. semanage login -a -s user_u bruker-kommandoen vil knytte user_u-identiteten til den gitte brukeren. Til slutt, semanage login -d bruker dropper koblingen tilknyttet denne brukeren.
# semanage login -a -s user_u rhertzog
# semanage login -l

Login Name           SELinux User         MLS/MCS Range        Service

__default__          unconfined_u         s0-s0:c0.c1023       *
rhertzog             user_u               s0                   *
root                 unconfined_u         s0-s0:c0.c1023       *
# semanage login -d rhertzog
semanage user -l viser adresseringen mellom SELinux-brukeridentiteter og tillatte roller. Å legge til en ny identitet krever å definere både de tilsvarende rollene og en merkingsforstavelse som brukes til å tilordne en type til personlige filer (/home/bruker/*). Forstavelsen må velges mellom user, staff, og sysadm. «staff»-forstavelsen resulterer i filer av typen «staff_home_dir_t». Å lage en ny SELinux-brukeridentitet gjøres med semanage user -a -R roller -P prefiks identitet. Til slutt; du kan fjerne en SELinux-brukeridentitet med semanage user -d identitet.
# semanage user -a -R 'staff_r user_r' -P staff test_u
# semanage user -l

                Labeling   MLS/       MLS/                          
SELinux User    Prefix     MCS Level  MCS Range                      SELinux Roles

root            sysadm     s0         s0-s0:c0.c1023                 staff_r sysadm_r system_r
staff_u         staff      s0         s0-s0:c0.c1023                 staff_r sysadm_r
sysadm_u        sysadm     s0         s0-s0:c0.c1023                 sysadm_r
system_u        user       s0         s0-s0:c0.c1023                 system_r
test_u          staff      s0         s0                             staff_r user_r
unconfined_u    unconfined s0         s0-s0:c0.c1023                 system_r unconfined_r
user_u          user       s0         s0                             user_r
# semanage user -d test_u

14.5.3.3. Å håndtere filkontekster, porter og boolske verdier

Hver SELinux-modul har et sett av filmerkingsregler, men det er også mulig å legge til egendefinerte regler for merking for å ta hensyn til et bestemt tilfelle. For eksempel, hvis du vil at nett-tjeneren skal kunne lese filene i /srv/www/-filhierarkiet, kan du kjøre semanage fcontext -a -t httpd_sys_content_t "/srv/www(/.*)?", fulgt av restorecon -R /srv/www/. Førstnevnte kommando registrerer nye regler for merking, og sistnevnte tilbakestiller filtypene etter gjeldende regler for merking.
Tilsvarende er TCP/UDP-portene merket på en måte som sikrer at bare de tilsvarende bakgrunnsprosessene kan lytte til dem. For eksempel, hvis du vil at nett-tjeneren skal kunne lytte på port 8080, bør du kjøre semanage port -m -t http_port_t -p tcp 8080.
Noen SELinux-moduler eksporterer Boolske valg som du kan justere for å endre gjøremålene til standardreglene. getsebool-verktøyet kan brukes til å inspisere disse valgene (getsebool boolsk viser ett valg, og getsebool -a alle). setsebool boolsk verdt-kommandoen endrer den gjeldende verdien av et Boolsk alternativ. -P-valget gjør endringen permanent. Det betyr at den nye verdien blir standard, og blir beholdt etter omstart. Eksempelet nedenfor gir nett-tjenere tilgang til hjemmeområder (dette er nyttig når brukerne har personlige nettsteder i ~/public_html/).
# getsebool httpd_enable_homedirs
httpd_enable_homedirs --> off
# setsebool -P httpd_enable_homedirs on
# getsebool httpd_enable_homedirs
httpd_enable_homedirs --> on

14.5.4. Å tilpasse reglene

Siden SELinux-opplegget er modulbasert, kan det være interessant å utvikle nye moduler for (muligens tilpassede) programmer som mangler dem. Disse nye modulene vil da komplettere referanseregler.
For å lage nye moduler kreves selinux-policy-dev-pakken så vel som selinux-policy-doc. Den siste inneholder dokumentasjonen om standardreglene (/usr/share/doc/selinux-policy-doc/html/) og eksempelfiler som kan brukes som maler for å lage nye moduler. Installer disse filene, og studer dem nærmere:
$ cp /usr/share/doc/selinux-policy-doc/Makefile.example Makefile
$ cp /usr/share/doc/selinux-policy-doc/example.fc ./
$ cp /usr/share/doc/selinux-policy-doc/example.if ./
$ cp /usr/share/doc/selinux-policy-doc/example.te ./
Filen .te er den viktigste. Den definerer reglene. Filen .fc definerer «filkonteksten»; det er typene som er tilordnet filer knyttet til denne modulen. Dataene inni .fc-filen brukes under filmerkingstrinnet. Endelig definerer .if-filen modulens grensesnitt. Det er et sett med «offentlige funksjoner» som andre moduler kan bruke til en riktig samhandling med modulen du oppretter.

14.5.4.1. Å skrive en .fc-fil

Å lese eksemplet nedenfor bør være tilstrekkelig til å forstå strukturen i en slik fil. Du kan bruke vanlige uttrykk for å tilordne den samme sikkerhetskonteksten til flere filer, eller til og med til et helt katalogtre.

Eksempel 14.2. filen eksempel.fc

# myapp executable will have:
# label: system_u:object_r:myapp_exec_t
# MLS sensitivity: s0
# MCS categories: <none>

/usr/sbin/myapp         --      gen_context(system_u:object_r:myapp_exec_t,s0)

14.5.4.2. Å skrive en .if-fil

I eksemplet nedenfor kontrollerer det første grensesnittet (“myapp_domtrans”) hvem som kan kjøre programmet. Det andre («myapp_read_log») gir leserettigheter til programmets loggfiler.
Hvert grensesnitt må generere et gyldig sett med regler som kan legges inn i en .te-fil. Du bør derfor skrive inn alle typene du bruker (med gen_require-makro), og bruke standardanvisninger for å gi rettigheter. Vær imidlertid oppmerksom på at du kan bruke grensesnitt som tilbys av andre moduler. Den neste delen vil gi flere forklaringer om hvordan disse rettighetene skal uttrykkes.

Eksempel 14.3. eksempel.if-fil

## <summary>Myapp example policy</summary>
## <desc>
##      <p>
##              More descriptive text about myapp.  The desc
##              tag can also use p, ul, and ol
##              html tags for formatting.
##      </p>
##      <p>
##              This policy supports the following myapp features:
##              <ul>
##              <li>Feature A</li>
##              <li>Feature B</li>
##              <li>Feature C</li>
##              </ul>
##      </p>
## </desc>
#

########################################
## <summary>
##      Execute a domain transition to run myapp.
## </summary>
## <param name="domain">
##      <summary>
##      Domain allowed to transition.
##      </summary>
## </param>
#
interface(`myapp_domtrans',`
        gen_require(`
                type myapp_t, myapp_exec_t;
        ')

        domtrans_pattern($1,myapp_exec_t,myapp_t)
')

########################################
## <summary>
##      Read myapp log files.
## </summary>
## <param name="domain">
##      <summary>
##      Domain allowed to read the log files.
##      </summary>
## </param>
#
interface(`myapp_read_log',`
        gen_require(`
                type myapp_log_t;
        ')

        logging_search_logs($1)
        allow $1 myapp_log_t:file read_file_perms;
')

14.5.4.3. Å skrive en .te-fil

Se på eksempel.te-filen:
policy_module(example,1.0.0) 1 # a non-base module name must match the file name

########################################
#
# Declarations
#

type myapp_t; 2
type myapp_exec_t;
domain_type(myapp_t)
domain_entry_file(myapp_t, myapp_exec_t) 3

type myapp_log_t;
logging_log_file(myapp_log_t) 4

type myapp_tmp_t;
files_tmp_file(myapp_tmp_t)

########################################
#
# Myapp local policy
#

allow myapp_t myapp_log_t:file { read_file_perms append_file_perms }; 5

allow myapp_t myapp_tmp_t:file manage_file_perms;
files_tmp_filetrans(myapp_t,myapp_tmp_t,file)

1

Modulen må identifiseres med navn og versjonsnummer. Denne anvisningen er nødvendig.

2

Hvis modulen introduserer nye typer, må den si ifra om dem med anvisninger som dette. Ikke nøl med å lage så mange typer som kreves i stedet for å gi for mange ubrukelige rettigheter.

3

Disse grensesnittene definerer myapp_t-typen som et prosessdomene som skal brukes av alle kjørbare merket med myapp_exec_t. Implisitt legger de til en exec_type-attributt til disse objektene, som igjen tillater andre moduler å tildele rettigheter til å kjøre disse programmene, for eksempel tillater userdomain-modulen prosesser med domene user_t, staff_t og sysadm_t å kjøre dem. Domenene til andre avstengte programmer vil ikke ha rettigheter til å kjøre dem, med mindre reglene gir dem lignende rettigheter (dette er tilfelle, for eksempel, med dpkg med sitt dpkg_t-domene).

4

logging_log_file er et grensesnitt som tilbys av referanseopplegget. Det indikerer at filene som er merket med den gitte typen, er loggfiler som burde dra nytte av de tilhørende reglene (for eksempel å gi rettigheter til logrotate slik at den kan håndtere dem).

5

Anvisningen allow er basisanvisningen som brukes til å godkjenne en operasjon. Den første parameteren er prosessdomenet som har lov til å utføre operasjonen. Det andre definerer objektet som en prosess som det tidligere domenet kan håndtere. Denne parameteren har formen «type:klasse», der type er dens SELinux-type og klasse beskriver hva slags objekt det er snakk om (fil, mappe, socket, fifo og så videre). Til slutt beskriver den siste parameteren tillatelsene (de tillatte operasjonene).
Tillatelser er definert som et sett av tillatte operasjoner, og følger denne malen: { operasjon1 operasjon2 }. Men du kan også bruke makroer som representerer de nyttigste tillatelsene. /usr/share/selinux/devel/include/support/obj_perm_sets.spt lister dem opp.
Følgende nettside gir en relativt uttømmende liste over objektklasser og tillatelser som kan gis.
Nå er det bare å finne det minimale settet med regler som kreves for å sikre at målprogrammet eller tjenesten fungerer riktig. For å oppnå dette bør du ha god kunnskap om hvordan programmet fungerer og hva slags data det styrer og/eller genererer.
Imidlertid er en empirisk tilnærming mulig. Etter at de relevante objektene er korrekt merket, kan du bruke programmet i tillatelsesmodus: Operasjonene som vil bli forbudt blir logget, men vil likevel lykkes. Ved å analysere loggene kan du nå identifisere operasjoner som skal tillates. Her er et eksempel på en slik loggoppføring :
avc:  denied  { read write } for  pid=1876 comm="syslogd" name="xconsole" dev=tmpfs ino=5510 scontext=system_u:system_r:syslogd_t:s0 tcontext=system_u:object_r:device_t:s0 tclass=fifo_file permissive=1
For bedre å forstå dette budskapet, la oss studere det bit for bit.

Tabell 14.1. Analyse av et SELinux-spor

BudskapBeskrivelse
avc: deniedEn operasjon er nektet.
{ read write }Denne operasjonen krevde read- og write-tillatelsene.
pid=1876Prosessen med PID 1876 kjørte operasjonen (eller forsøkt å utføre den).
comm="syslogd"Prosessen var et tilfelle av syslogd-programmet.
name="xconsole"Målobjektet ble navngitt xconsole. Noen ganger kan du også ha en «sti»-variabel - med hele banen - i stedet.
dev=tmpfsEnheten som er vert for målobjektet er et tmpfs (et i-minne-filsystem). Med en ekte disk kan du se at partisjonen er vert for objektet (for eksempel «sda3»).
ino=5510Objektet er identifisert med inode-nummer 5510.
scontext=system_u:system_r:syslogd_t:s0Dette er sikkerhetskonteksten for prosessen som utførte operasjonen.
tcontext=system_u:object_r:device_t:s0Dette er sikkerhetskontektsen til målobjektet.
tclass=fifo_fileMålobjektet er en FIFO-fil.
Ved å observere dette i loggen er det mulig å bygge en regel som ville tillate denne operasjonen. For eksempel, allow syslogd_t device_t:fifo_file { read write }. Denne prosessen kan automatiseres, og det er akkurat hva audit2allow-kommandoen (i policycoreutils-pakken) tilbyr. Denne tilnærmingen er bare nyttig hvis de ulike objektene allerede er korrekt merket med det som måtte være begrenset. I alle fall må du lese nøye gjennom de genererte reglene, og validere dem i henhold til dine kunnskaper om programmet. Faktisk tenderer denne tilnærmingen å gi flere rettigheter enn det som virkelig er nødvendig. Den riktige løsningen er ofte å lage nye typer og bare tildele rettigheter til disse typene. Det hender også at en nektet operasjon er fatalt for programmet, og da kan det være bedre å bare legge til en «dontaudit»-regel for å unngå loggoppføringen til tross for en effektiv nektelse.

14.5.4.4. Å kompilere filene

Så snart de 3 filene (eksempel.if, eksempel.fc, og eksempel.te) svarer til dine forventninger for de nye reglene, skift navnene til myapp.extension og kjør make NAME=devel for å generere en modul i myapp.pp-filen (du kan umiddelbart laste den med semodule -i myapp.pp). Hvis flere moduler er definert, vil make lage alle de korresponderende .pp-filene.