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 (Linux Security Modules)-grensesnitt. 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 identitet til brukeren som startet prosessen, rolle og domene 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.3. Sikkerhetskontekster og Unix-brukere

I praksis får brukeren, under innlogging, tildelt en standard 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 du 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-politikk.
Selvsagt gjelder ikke rettighetene for alle objekter (filer, kataloger, stikkontakter, enheter, etc.). 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.4. Automatiske overganger mellom domener

14.5.2. Oppsett av SELinux

SELinux-støtte er innebygd i standardkjernene som følger med Debian. Kjernen i Unix-verktøyet støtter SELinux uten noen modifikasjoner. Det er dermed relativt enkelt å aktivere SELinux.
Kommandoen apt install selinux-basics selinux-policy-default vil automatisk installere de nødvendige pakkene til å sette opp 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. Brukersesjoner 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 permissive/givende-modus der avviste handlinger logges, men fremdeles blir utført. Du bør derfor endre GRUBs oppsettsfil for oppstart ved å legge til de ønskede parametere. En enkel måte å gjøre dette på er å modifisere GRUB_CMDLINE_LINUX-variabelen i /etc/default/grub, og å kjøre update-grub. SELinux vil være aktivert etter en omstart.
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 er opprettet mens SELinux ennå ikke var aktiv, og mens merking skjer).

14.5.3. Å håndtere SELinux-system

SELinux-opplegget er et modulbasert sett med regler, og installasjonen oppdager og aktiverer automatisk alle relevante moduler basert på den allerede installerte tjenesten. 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 kan du klare å definere rollene som hver bruker kan slutte seg til, og dette kan gjøres med semanage-kommandoen.
De to kommandoer kan dermed brukes til å endre den 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 (pakke) (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 -l
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åndtere identiteter

Hver gang en bruker logger inn, får de tildelt en SELinux-identitet. Denne identiteten definerer rollene de kan støtte. Disse to adressingene (fra brukeren til identiteten, og fra denne identiteten til roller) kan settes opp med semanage-kommandoen.
You should definitely read the semanage(8) manual page. All the managed concepts have their own manual page; for instance, semanage-login(8). Even if the command's syntax tends to be similar for all the concepts which are managed, it is recommended to read its manual page. You will find common options to most sub-commands: -a to add, -d to delete, -m to modify, -l to list, and -t to indicate a type (or domain).
semanage login -l lister gjeldende adressering mellom brukeridentifikatorer og SELinux-identiteter. Brukere som ikke har noen eksplisitt inngang, får identiteten angitt i __default__-inngangen. semanage login -a -s user_u bruker-kommandoen vil knytte user_u-identiteten til den gitte brukeren. Tilslutt, semanage login -d bruker dropper asdresseringsinngangen knyttet til 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, for å 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 restart. 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 innenfor .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. eksempel.fc-file

# 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 formidle alle typene du bruker (med gen_require-makro), og bruke standard direktiver for å gi rettigheter. Vær imidlertid oppmerksom på at du kan bruke grensesnitt som tilbys av andre moduler. Den neste seksjonen 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">
##      Domain allowed to transition.
## </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">
##      Domain allowed to read the log files.
## </param>
#
interface(`myapp_read_log',`
        gen_require(`
                type myapp_log_t;
        ')

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

14.5.4.3. Å skrive en .te-fil

Se på eksempel.te-filen:
policy_module(myapp,1.0.0) 1

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

type myapp_t; 2
type myapp_exec_t;
domain_type(myapp_t)
domain_entry_file(myapp_t, myappLikewise, some rights are in fact sets of rights which are replaced by their values at compilation time._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. Dette direktivet er nødvendig.

2

Hvis modulen introduserer nye typer, må den si ifra om dem med direktiver 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 til å 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 is an interface provided by the reference policy. It indicates that files labeled with the given type are log files which ought to benefit from the associated rules (for example, granting rights to logrotate so that it can manipulate them).

5

Direktivet allow er basen direktivet bruker 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 (fil, mappe, socket, fifo, etc.). 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/viser dem.
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 som det skal. 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 med syslogd-programmet.
name="xconsole"Målobjektet ble navngitt xconsole. Noen ganger kan du også ha en «sti»-variabel - med hele banen - i stedet.
dev=tmpfsThe device hosting the target object is a tmpfs (an in-memory filesystem). For a real disk, you could see the partition hosting the object (for example, “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.
By observing this log entry, it is possible to build a rule that would allow this operation. For example, allow syslogd_t device_t:fifo_file { read write }. This process can be automated, and it's exactly what the audit2allow command (of the policycoreutils package) offers. This approach is only useful if the various objects are already correctly labeled according to what must be confined. In any case, you will have to carefully review the generated rules and validate them according to your knowledge of the application. Effectively, this approach tends to grant more rights than are really required. The proper solution is often to create new types and to grant rights on those types only. It also happens that a denied operation isn't fatal to the application, in which case it might be better to just add a “dontaudit” rule to avoid the log entry despite the effective denial.

14.5.4.4. Å kompilere filene

Once the 3 files (example.if, example.fc, and example.te) match your expectations for the new rules, rename them to myapp.extension and run make NAME=devel to generate a module in the myapp.pp file (you can immediately load it with semodule -i myapp.pp). If several modules are defined, make will create all the corresponding .pp files.