Portál AbcLinuxu, 13. prosinec 2017 21:23

Nebojte se SELinuxu – 3 (pravidla TE, role)

1. 9. 2009 | Michal Svoboda
Články - Nebojte se SELinuxu – 3 (pravidla TE, role)  

Abychom mohli pokračovat v nastavování SELinuxu, potřebujeme dohnat trochu teorie. Dnes dokončíme popisy pravidel mechanismu TE z minula a povíme si potřebný základ pro mechanismus RBAC. Nakonec se podíváme na praktickou ukázku, jak tyto mechanismy spolu tvoří funkční a zabezpečený systém.

Obsah

AV pravidla

link

minulém díle jsme se věnovali pasivnímu pozorování TE pravidel. Všimli jsme si, že pomocí pravidel typu allow podmět předmět akce jsou povoleny interakce mezi dvěma typy objektů ve formě „podmět provede akci na předmětu“, přičemž akce se ještě dělí na třídu objektu a typ akce (např. file read). Nebo při jiném úhlu pohledu bychom mohli říci, že předmět se dělí na typ a třídu objektu (shadow_t:file).

Kromě allow lze nastavit ještě přístupy typu auditallowdontaudit, přičemž auditallow je totéž co allow, ale je navíc generována hláška do logu (stejná jako při zamítnutí akce, když není povolena). U dontaudit je naopak akce zakázána, a hláška se negeneruje žádná. Smysl použití dontaudit je v situaci, kdy nějaký program funguje správně, i pokud se nějaká akce zamítne, tj. ve skutečnosti nepotřebuje hrabat na nějaké prostředky. Tudíž chceme akci zamítnout, ale nepotřebujeme, aby se nám kvůli tomu plnil log. Souhrnně se tato pravidla nazývají AV pravidla, kde AV je zkratka z Access Vector. Řetězec avc, který se zobrazuje v logu, je pak odvozen ze slov Access Vector Cache, což je centrální mechanismus, který pravidla vyhodnocuje.

Všimněme si, že v AV pravidlech nelze explicitně zakázat nějakou akci. Pravidla fungují tak, že co není explicitně povoleno, je zakázáno, a co je jednou povoleno, již nelze vzít zpět. Existují pouze dva záchranné mechanismy, ve formě pravidel neverallowconstrain, které umí „hlídat“ před příliš nebezpečnými pravidly. Od jádra verze 2.6.28 také funguje mechanismus typebound, který zavádí mezi typy vztah rodič–potomek a nedovolí potomkovi, aby měl širší práva než jeho rodič (typebounds se používají prominentně například v SELinuxovém modulu pro Apache). O těchto věcech se zmíním podrobněji v některém z příštích dílů.

Typy akcí

link

Seznam všech možných akcí, které lze povolovat, lze najít například na webu Tresys, případně lze pro výpis akcí podporovaných na konkrétním systému použít již zmíněnou utilitu apol. Seznam akcí a jejich tříd je navíc rozřazen podle toho, která komponenta systému se o ně stará. U SELinuxu totiž nemusíme nastavovat pouze politiku akcí, které obsluhuje jádro (tj. syscally), ale také libovolné jiné akce, které může obsluhovat userspace [uživatelský prostor] program. Příkladem tohoto je X server. Z pohledu jádra je přístup k X serveru pouze odeslání dat po socketu, na úrovni X serveru můžeme ale jednotlivé akce odlišit a definovat politiku typu, zda nějaký proces smí číst clipboard nebo měnit kurzor myši. Důležité je, že ve všech těchto politikách, ať již to je pro X server, databázi nebo jádro, vystupují tytéž bezpečnostní kontexty a že tato politika je centralizovaná a vynucená správcem systému i pro superuživatele.

Pravidla přeměny typů (type transitional rules)

link

Kromě pravidel typu „toto je povoleno“ je ještě potřeba systému říct, jakým způsobem přechází objekt z jednoho typu na jiný. To je samozřejmě možno provést ručně, máme-li příslušnou akci povolenu (například programem chcon pro soubor a runcon pro proces). Ve většině případů ale chceme, aby se tato přeměna stala automaticky: Například pokud program init spustil naše getty, spustilo se ve svém vlastním kontextu, nikoliv v kontextu původního procesu. Podobně je to zapotřebí i u souborů: Představme si, že různé procesy zapisují do nějakého společného adresáře, například do /var/run soubor s číslem procesu (démon.pid). Pokud se ale podíváme do tohoto adresáře, vidíme věci jako:

-rw-r--r-- 1 root     root     system_u:object_r:httpd_var_run_t:s0          5 2009-08-16 06:25 apache2.pid
-rw-r--r-- 1 root     root     system_u:object_r:dhcpc_var_run_t:s0          5 2009-08-15 11:45 dhclient.eth0.pid
-rw-r--r-- 1 root     root     system_u:object_r:sshd_var_run_t:s0           5 2009-08-15 11:45 sshd.pid

Tuto automatickou přeměnu typů lze specifikovat pravidlem type_transition. Pomocí sesearch --type -s sshd_t se můžeme podívat, jaké přeměny se aplikují na objekty vytvářené procesem typu sshd_t (což je ssh démon). Například

type_transition sshd_t var_run_t : file sshd_var_run_t;

říká, že pokud sshd_t vytvoří file v adresáři, který je označkován typem var_run_t, tak tento soubor bude označkován typem sshd_var_run_t. Připomeňme, že toto pravidlo je povinné, takže se přeměna uskuteční vždy, nedáme-li příslušnému procesu právo explicitně přeznačkovat soubory. Je také rozumné, aby bylo toto pravidlo doprovozeno příslušným pravidlem allow, aby vůbec ssh démon mohl ve /var/run něco vytvořit.

Podobně se chovají pravidla pro přeměnu procesů. Všimneme si, že soubor /usr/bin/ssh má na disku typ ssh_exec_t a podíváme se, jaká má definována pravidla přeměny:

# sesearch --type -t ssh_exec_t
   type_transition sysadm_t ssh_exec_t : process sysadm_ssh_t;
   type_transition user_t ssh_exec_t : process user_ssh_t;
   type_transition staff_t ssh_exec_t : process staff_ssh_t;

Což nám říká, že má-li proces typ sysadm_t a zavolá syscall execve() na soubor s typem ssh_exec_t, změní se typ procesu na sysadm_ssh_t. Obdobně pro další typy user_tstaff_t. Tyto typy se obvykle přiřazují různě oprávněným uživatelům (přesněji řečeno jejich shellu). Např. user_t může být shell obyčejného uživatele, a sysadm_t může být shell administrátora. Pokud oba spustí program ssh, budou výsledkem dva procesy ssh běžící pod různými typy. To znamená, že i pokud by uživatel nějak získal pravomoc roota nebo jiným způsobem mohl na klasickém UNIXu ovlivňovat ssh administrátora, TE politika mu v tom zabrání díky různým typům spuštěných ssh.

Poznamenejme, že pravidel proměn je poměrně málo vzhledem ke všem možným kombinacím, kdo co může spustit nebo vytvořit. Je to opět důsledek „targeted“ politiky, kde se ošetřují pouze interakce s bezpečnostními důsledky. Problémy typu, že všichni uživatelé mají rovnocenné právo spustit sed pod svým vlastním bezpečnostním kontextem, nás až tak netrápí.

Role a uživatelé

link

Když už známe principy, jak je ošetřena interakce existujících typů, je potřeba ještě zajistit, aby nově přihlášený uživatel dostal shell (nebo jiný program) pod správným bezpečnostním kontextem, případně nějak vymezit, jaké kontexty může tento uživatel nabývat. O to se stará mechanismus uživatelů a rolí označovaný jako RBAC (ačkoliv do skutečného RBAC má poměrně daleko).

Uživatel v SELinuxu, tj. první část bezpečnostního kontextu, je MAC (tedy povinně bezpečnostní) verze UNIXového uživatele. V klasickém UNIXu je možné UID měnit libovolně, máme-li práva roota. SELinuxová identita zůstává stejná, i pokud se mění UNIXové UID. Změnit ji může obvykle pouze program, který zajišťuje přihlášení uživatele (např. ssh démon), ale už ne libovolný program spuštěný administrátorem. Na druhou stranu není nutné, ani žádoucí, aby měl každý UNIXový uživatel přiřazenou jednoznačnou SELinuxovou identitu.

Seznam SELinuxových uživatelů v systému zjistíme příkazem semanage user -l a pohledem na první sloupec vypsané tabulky. Na většině systémů platí pravidlo, že procesy spouštěné systémem při startu mají identitu system_u. Ostatní identity jsou víceméně určeny uživatelům-lidem, přičemž jednotlivé identity jsou různě omezovány. Mapování unixových uživatelů na SELinuxové identity zjistíme příkazem semanage login -l. Řádek označený jako __default__ určuje identitu, která se přiřadí, pokud v tabulce není nalezen záznam pro konkrétního uživatele.

Mechanismus, který zajišťuje omezování uživatelů, využívá role, tj. druhé pole v bezpečnostním kontextu. Podle tabulky z příkazu semanage user -l lze dohledat, jaké role může která SELinuxová identita nabývat. Může se stát, že jeden uživatel může mít více rolí (například staff_u může mít staff_rsysadm_r). V tom případě se lze mezi rolemi přepínat pomocí příkazu newrole -r novárole. U některých přihlašovacích mechanismů je možné roli specifikovat hned při přihlášení: ssh uživatel/role@počítač nebo sudo -r role příkaz.

Přiřazená role je pak pouze seznam typů, které smí daný proces nabývat. Tento seznam je nadřazený TE pravidlům o přeměně typů, takže uživatel s danou rolí například nemůže dostat bezpečnostní kontext HTTP serveru, pokud daný typ nemá obsažen ve své roli. Takto lze bezpečným způsobem vytvářet specializované role, například administrátor webu nebo administrátor DNS, kde uživatel sice má práva roota, ale může manipulovat pouze s pevně danou částí systému. Seznam rolí a jejich obsah je možno opět dohledat pomocí programu apol, v záložce Policy Components a Roles.

Posledním prvkem v této poměrně komplikované mašinérii je sada souborů default_contextsusers/* v adresáři /etc/selinux/default/contexts, jejichž smysl si ukážeme na příkladu. Přihlásíme-li se jako pht pomocí ssh na server, proběhne po ověření všech hesel toto:

  1. Z mapování UNIXových uživatelů na SELinuxové identity se pro uživatele pht odvodí identita staff_u.
  2. Pro zjištění zbytku nového kontextu se ssh démon podívá do souboru users/staff_u, pakliže tento neexistuje, tak do default_contexts.
  3. V tomto souboru se najde řádek, který odpovídá současnému kontextu vyjma první části, tj. system_r:sshd_t.
  4. Na tomto řádku je dejme tomu řetězec staff_r:staff_t sysadm_r:sysadm_t. Toto jsou kontexty, které, včetně uživatelské části staff_u, a v daném pořadí ssh démon postupně vyzkouší nastavit. Pokud se nastavení povede (je možné vzhledem k politice), spustí se uživatelův shell.
  5. Některé přihlašovací programy, včetně sshd, dovolí uživateli předem specifikovat roli, kterou chce po přihlášení obdržet. V tom případě se neprojíždí seznam celý, ale najde se v něm kontext s příslušnou rolí a změna kontextu se vyzkouší pouze jednou.

Tímto mechanismem lze tedy jednak specifikovat implicitní typ pro danou roli a jednak implicitní roli pro daného uživatele, a to vše v závislosti na programu (respektive jeho kontextu), který uživatele přihlásil.

Existuje však jedna výjimka, a to je zmíněný program newrole (a další, které mění kontext procesu, ale neprovádějí přihlášení uživatele). Tento program hledá implicitní typ k dané roli v souboru default_type.

Jak to celé dohromady funguje

link

Pro lepší pochopení uživatelů a rolí uvedeme praktickou ukázku. Nejprve se přihlásíme do systému, kde je mapování nastaveno výše uvedeným způsobem.

pht@stanice$ ssh server
pht@server's password:
Last login: Thu Aug 20 14:44:43 2009 from stanice

pht@server$ id
uid=1000(pht) gid=1000(pht) groups=50(staff),1000(pht) context=staff_u:staff_r:staff_t:s0

Uživatelé s identitoustaff_u jsou uživatelé, kteří kromě běžné práce v systému mají možnost systém spravovat. V základní roli staff_r a typu staff_t ale nejsou privilegia odlišná od ostatních uživatelů. Díky omezené interakci typů vidíme pouze svoje procesy a nemůžeme hrabat na systémové soubory.

pht@server$ ls -lZ /usr/sbin/sshd
ls: cannot access /usr/sbin/sshd: Permission denied

pht@server$ ps xauZ
LABEL                           USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
staff_u:staff_r:staff_t:s0      pht      16197  0.0  0.0  21844  4744 pts/2    Ss   14:48   0:00 -bash
staff_u:staff_r:staff_t:s0      pht      16233  0.0  0.0  16012  1104 pts/2    R+   14:54   0:00 ps xauZ

Přepnutím na roota toho moc nezískáme.

pht@server$ su -
Password:
-su: /root/.bash_profile: Permission denied

root@server# ps xauZ
LABEL                           USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
staff_u:staff_r:staff_t:s0      pht      16197  0.0  0.0  21844  4744 pts/2    Ss   14:48   0:00 -bash
staff_u:staff_r:staff_t:s0      root     16298  0.0  0.0  20004  3176 pts/2    S    15:00   0:00 -su
staff_u:staff_r:staff_t:s0      root     16314  0.0  0.0  16012  1108 pts/2    R+   15:03   0:00 ps xauZ

root@server# ping seznam.cz
ping: icmp open socket: Permission denied

Nelze ani získat shell běžící pod „lepším“ typem, protože nám to nedovoluje současná role.

root@server# runcon -t sysadm_t /bin/bash
runcon: invalid context: staff_u:staff_r:sysadm_t:s0: Invalid argument

Lze ale přepnout roli, protože nám to dovoluje současná identita.

root@server# newrole -r sysadm_r
Password:

root@server# id
uid=0(root) gid=0(root) groups=0(root) context=staff_u:sysadm_r:sysadm_t:s0

root@server# ping seznam.cz
PING seznam.cz (77.75.72.3) 56(84) bytes of data.
64 bytes from www.seznam.cz (77.75.72.3): icmp_seq=1 ttl=248 time=1.53 ms

root@server# ls -lZ /usr/sbin/sshd
-rwxr-xr-x 1 root root system_u:object_r:sshd_exec_t:s0 474640 Jan 14  2009 /usr/sbin/sshd

Všimněme si, že i přes změnu role a UID uživatele máme stále stejnou identitu staff_u.

Příkaz newrole lze provést i pod uživatelem pht se stejným výsledkem, tj. změnou role. K úspěšnému administrování systému nám budou pro některé operace stále chybět práva roota, ty lze ale získat různými způsoby (su, sudo, seteuid programy). Pro správu systému je tedy důležitější než UID spíše SELinuxová identita a role.

Pod rolí sysadm_r a typem sysadm_t můžeme dělat téměř vše, ale ne úplně:

root@server# cat /etc/shadow
cat: /etc/shadow: Permission denied

Pro tuto operaci musíme použít program vipw -s. V průběhu editování stopneme vi (pomocí ctrl-z) a podíváme se, pod jakým kontextem běží:

root@server# ps uZ | grep vipw
staff_u:sysadm_r:sysadm_passwd_t:s0 root 16395  0.0  0.0   8068   688 pts/2    T    15:21   0:00 vipw -s

Spuštěním programu vipw tedy došlo k automatické přeměně kontextu na typ sysadm_passwd_t. Tento typ může sice zapisovat do shadow, ale má zase omezená práva jinde.

CVUT logo

Příště

link

V příštím díle si povíme o tzv. referenční politice, což je v současné době jediná politika, která se instaluje z balíčků. Podíváme se, jak tato politika funguje, jak se v ní vyznat, případně jak si sestavit vlastní modul s pravidly.

Poděkování

link

Článek vznikl za podpory ČVUT FEL, Katedra kybernetiky, kde jsou k dispozici, mimo jiné, studijní programy Otevřená informatikaKybernetika a robotika.

Seriál SELinux – nebojte se (dílů: 6)

První díl: Nebojte se SELinuxu – 1 (úvod, první spuštění), poslední díl: Nebojte se SELinuxu – 6 (MLS a MCS).
Předchozí díl: Nebojte se SELinuxu – 2 (kontext, politika a pravidla TE)
Následující díl: Nebojte se SELinuxu – 4 (reference policy)

Související články

Novější jádra a starší SELinux politiky
Smack: zjednodušená kontrola přístupu
SMACK a Jediný Správný Bezpečnostní Modul
Začíná diskuze o AppArmor
Linuxové bezpečnostní ne-moduly a AppArmor
LCA: Diskuze o bezpečnosti
Bezpečnostní modul Snet a API LSM
TOMOYO Linux a bezpečnost založená na pathname
Budoucnost API pro linuxové bezpečnostní moduly (LSM)

Odkazy a zdroje

SELinux
SELinux userspace, IDE, setools, referenční politika)
se-postgres+apache

Další články z této rubriky

V sobotu se uskuteční konference CryptoFest
Pozor na androidové aplikace
Silent Circle představil bezpečný smartphone Blackphone 2
Android je bezpečnější, řada hrozeb však stále přetrvává
Avast varuje před nebezpečnými aplikacemi v Google Play

Diskuse k tomuto článku

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.