GNU/Linux >> Znalost Linux >  >> Linux

Použití funkcí systemd k zabezpečení služeb

Všechny nejnovější verze nejpopulárnějších distribucí Linuxu používají systemd zavést počítač a spravovat systémové služby. Systemd poskytuje několik funkcí, které usnadňují spouštění služeb a více zabezpečeno. Toto je vzácná kombinace a tento článek ukazuje, proč je užitečné nechat systemd spravovat prostředky a sandbox služby.

Odůvodnění

Proč bychom tedy měli používat systemd pro bezpečnostní sandboxing? Za prvé, někdo by mohl namítnout, že každý kousek této funkce je již vystaven prostřednictvím existujících a dobře známých nástrojů, které lze skriptovat a kombinovat libovolným způsobem. Za druhé, zejména v případě programů napsaných v C/C++ a dalších nízkoúrovňových jazycích lze přímo použít vhodná systémová volání, čímž se dosáhne štíhlé implementace pečlivě přizpůsobené potřebám konkrétní služby.

Existují čtyři hlavní důvody:

1. Zabezpečení je těžké. Centralizovaná implementace ve správci služeb znamená, že službu, která ji využívá, lze výrazně zjednodušit. Tato centralizovaná implementace je bezpochyby složitá, ale díky svému širokému použití je dobře otestována. Pokud vezmeme v úvahu, že se znovu používá přes tisíce služeb, celkově složitost systému je snížena.

2. Bezpečnostní primitiva se mezi systémy liší. Systemd vyhlazuje rozdíly mezi hardwarovými architekturami, verzemi jádra a systémovými konfiguracemi.

Funkcionalita zajišťující zpevnění služeb je implementována v maximální možné míře na daném systému. Například systemd jednotka může obsahovat konfiguraci AppArmor i SELinux. První se používá na systémech Ubuntu/Debian, druhý na Fedora/RHEL/CentoOS a ani jeden pro distribuce, které neumožňují žádný MAC systém. Druhou stránkou této flexibility je, že na tyto funkce nelze spoléhat jako na jediné zadržovací mechanismus (nebo že takové služby se používají pouze na systémech, které podporují všechny požadované funkce).

3. Zabezpečení vyžaduje práci se systémem na nízké úrovni. Funkce poskytované správcem služby jsou nezávislé na jazyku implementace služby, takže je snadné napsat službu v jazyce na vysoké úrovni, např. shell nebo Python nebo cokoli, co je vhodné, a přesto ji uzamknout.

4. Zabezpečení vyžaduje oprávnění. To je paradox, ale k odebrání privilegií jsou zapotřebí privilegia. Často například potřebujeme být root, abychom mohli nastavit vlastní jmenný prostor pro připojení, abychom omezili pohled na souborový systém. Dalším příkladem je, že démon HTTP se často spouští jako uživatel root, aby mohl otevřít port s nízkým číslem a porty s nízkým číslem jsou omezeny ve jménu zabezpečení. Správce služeb stejně musí běžet s nejvyššími oprávněními, ale služby by neměly a nastavení zpřísnění je často jediným důvodem, proč vyžadovat vyšší oprávnění. Jakékoli chyby v implementaci služby v této fázi mohou být nebezpečné. Přesunutím nastavení na správce služeb mohou služby začít bez této rané fáze zvýšených oprávnění.

Abychom to uvedli do kontextu, nedávno vydaná Fedora 32 obsahuje téměř 1800 různých souborů jednotek pro spouštění služeb napsaných v C, C++, Pythonu, Java, Ocaml, Perl, Ruby, Lua, Tcl, Erlang a tak dále – a pouze jeden systemd .

[ Potřebujete více o systemd? Stáhněte si cheat sheet systemd pro další užitečné rady. ]

Několik ekvivalentních způsobů spuštění služby

Nejčastěji systemd služby jsou definovány prostřednictvím souboru jednotky :textový soubor ve formátu inini, který deklaruje příkazy k provedení a různá nastavení. Po úpravě tohoto souboru jednotky systemctl daemon-reload by měl být zavolán, aby šťouchl manažera, aby načetl nová nastavení. Výstup z démona přistane v žurnálu ak jeho zobrazení se použije samostatný příkaz. Při interaktivním spouštění příkazů to vše není příliš pohodlné. systemd-run příkaz říká manažerovi, aby spustil příkaz jménem uživatele, a je skvělou alternativou pro interaktivní použití. Příkaz k provedení je určen podobně jako sudo . První poziční argument a vše za ním je skutečný příkaz a všechny předchozí možnosti jsou interpretovány pomocí systemd-run sám. systemd-run příkaz má možnosti specifikovat konkrétní nastavení, jako je --uid a --gid pro uživatele a skupinu. -E volba nastavuje proměnnou prostředí, zatímco volba "catch-all" -p přijímá libovolné páry klíč=hodnota podobné souboru jednotek.

  $ systemd-run whoamiRunning jako celku:run-rbd26afbc67d74371a6d625db78e33acc.service $ journalctl -u run-rbd26afbc67d74371a6d625db78e33acc.servicejournalctl -u run-rbd26afbc67d74371a6d625db78e33acc.service-- Záznamy začínají na Čt 2020-04-23 19:31:49 CEST, konec v Po 27.04.2020 13:22:35 CEST. --Apr 27 13:22:18 fedora systemd[1]:Spuštěno run-rbd26afbc67d74371a6d625db78e33acc.service.Apr 27 13:22:18 fedora whoami[520662]:root[Apr] 27:18 system fedora rund13:127:18 rbd26afbc67d74371a6d625db78e33acc.service:Úspěšné. 

systemd-run -t připojuje standardní vstupní, výstupní a chybové proudy příkazu k vyvolávacímu terminálu. To je skvělé pro interaktivní spouštění příkazů (všimněte si, že proces služby je stále potomkem správce).

$ systemd-run -t whoamiSpuštění jako jednotka:run-u53517.serviceStiskněte ^] třikrát během 1 s pro odpojení TTY.root 

Konzistentní prostředí

Jednotka vždy začíná v pečlivě definovaném prostředí. Když spustíme jednotku pomocí systemctl nebo systemd-run , příkaz je vždy vyvolán jako potomek správce. Prostředí shellu neovlivňuje prostředí, ve kterém běží servisní příkazy. Ne všechna nastavení, která lze zadat v souboru jednotky, jsou podporována systemd-run , ale většina je, a pokud se budeme držet této podmnožiny, vyvolání prostřednictvím souboru jednotky a systemd-run jsou ekvivalentní. Ve skutečnosti systemd-run vytvoří dočasný soubor jednotky za běhu.

Například:

$ sudo systemd-run -M rawhide -t /usr/bin/grep PRETTY_NAME=/etc/os-release 

Zde sudo promluví s PAM, aby umožnil eskalaci oprávnění, a poté provede systemd-run jako kořen. Dále systemd-run vytvoří připojení k počítači s názvem rawhide , kde mluví se správcem systému (PID 1 v kontejneru) přes dbus. Správce vyvolá grep , která dělá svou práci. grep příkaz se vytiskne na stdout, který je připojen k pseudoterminálu, ze kterého sudo bylo vyvoláno.

Nastavení zabezpečení

Uživatelé a dynamickí uživatelé

Bez dalších okolků si promluvme o některých konkrétních nastaveních, počínaje těmi nejjednoduššími a nejvýkonnějšími primitivy.

Za prvé, nejstarší, nejzákladnější a možná nejužitečnější mechanismus oddělení oprávnění:uživatelé. Uživatele můžete definovat pomocí User=foobar v [Službě] sekce souboru jednotky nebo systemd-run -p User=foobar nebo systemd-run --uid=foobar . Může se to zdát zřejmé – a na Androidu má každá aplikace svého vlastního uživatele – ale ve světě Linuxu máme stále příliš mnoho služeb, které zbytečně běží jako root.

Systemd poskytuje mechanismus pro vytváření uživatelů na vyžádání. Při vyvolání pomocí DynamicUser=yes , je službě přiděleno jedinečné uživatelské číslo. Toto číslo se převádí na dočasné uživatelské jméno. Toto přiřazení není uloženo v /etc/passwd , ale místo toho je generován za běhu modulem NSS, kdykoli je dotazováno číslo nebo odpovídající jméno. Po zastavení služby může být číslo později znovu použito pro jinou službu.

Kdy by měl být pro službu použit běžný statický uživatel a kdy je preferován dynamický? Dynamickí uživatelé jsou skvělí, když je identita uživatele pomíjivá a není potřeba žádná integrace s jinými službami v systému. Ale když máme v databázi politiku umožňující přístup konkrétním uživatelům, adresářům sdíleným s určitou skupinou nebo jakékoli jiné konfiguraci, kde chceme odkazovat na uživatelské jméno, dynamicí uživatelé pravděpodobně nejsou tou nejlepší volbou.

Připojit jmenné prostory

Obecně je třeba poznamenat, že systemd je často pouze zabalovací funkce, kterou poskytuje jádro. Například různá nastavení, která omezují přístup ke stromu souborového systému, činí jeho části pouze pro čtení nebo jsou nepřístupné, se provádí uspořádáním příslušných souborových systémů v nesdíleném jmenném prostoru připojení.

Několik užitečných nastavení je implementováno takto. Dva nejužitečnější a nejobecnější jsou ProtectHome= a ProtectSystem= . První používá nesdílený jmenný prostor pro připojení k vytvoření /home buď pouze pro čtení, nebo zcela nepřístupné. Druhý je o ochraně /usr , /boot a /etc .

Třetím také užitečným, ale velmi specifickým nastavením je PrivateTmp= . Používá jmenné prostory připojení k zviditelnění soukromého adresáře jako /tmp a /var/tmp za službu. Dočasné soubory služby jsou před ostatními uživateli skryty, aby se předešlo problémům způsobeným kolizemi souborů nebo nesprávnými oprávněními.

Zobrazení systému souborů lze spravovat na úrovni jednotlivých adresářů pomocí InaccessiblePaths= , ReadOnlyPaths= , ReadWritePaths= , BindPaths= a ReadOnlyBindPaths= . První dvě nastavení poskytují celý nebo pouze přístup pro zápis do částí hierarchie systému souborů. Třetí je o obnovení přístupu, což je užitečné, když chceme dát plný přístup pouze do některého konkrétního adresáře hluboko v hierarchii. Poslední dva umožňují přesouvání adresářů, nebo, přesněji řečeno, soukromou vazbu-připojení na jiné místo.

Vrátím se k předmětu DynamicUser=yes , takoví přechodní uživatelé jsou možní pouze tehdy, když služba nemá povoleno vytvářet trvalé soubory na disku. Pokud by takové soubory byly viditelné pro ostatní uživatele, ukázalo by se, že nemají žádného vlastníka, v horším případě by k nim mohl přistupovat nový přechodný uživatel se stejným číslem, což by vedlo k úniku informací nebo nechtěné eskalaci oprávnění. Systemd používá jmenné prostory připojení k tomu, aby byla většina stromu systému souborů pro službu nezapisovatelná. Aby bylo umožněno trvalé úložiště, je do stromu souborového systému viditelný pro službu připojen soukromý adresář.

Všimněte si, že tyto ochrany jsou nezávislé na základním mechanismu řízení přístupu k souboru pomocí vlastnictví souboru a masky oprávnění. Pokud je souborový systém připojen pouze pro čtení, ani uživatelé, kteří by mohli upravovat konkrétní soubory na základě standardních oprávnění, to nemohou udělat, dokud není souborový systém znovu připojen pro čtení a zápis. To poskytuje ochranu proti chybám ve správě souborů (koneckonců, není neslýchané, že si uživatelé občas nastaví špatnou masku oprávnění) a je to vrstva strategie ochrany do hloubky.

Prostředky implementované pomocí jmenných prostorů připojení jsou obecně velmi efektivní, protože implementace jádra je efektivní. Režie při jejich nastavení je obvykle také zanedbatelná.

Automatické vytváření adresářů pro službu

Relativně nová funkce, která systemd poskytuje služby je automatická správa adresářů. Různé cesty souborového systému mají různé charakteristiky úložiště a zamýšlené použití, ale spadají do několika standardních kategorií. FHS určuje, že /etc je pro konfigurační soubory /var/cache je pro netrvalé úložiště, /var/lib/ je pro semipermanentní úložiště, /var/log pro protokoly a /run pro nestálé soubory. Služba často potřebuje podadresář v každém z těchto umístění. Systemd nastaví to automaticky, jak je řízeno ConfigurationDirectory= , CacheDirectory= , StateDirectory= , LogsDirectory=RuntimeDirectory= nastavení. Uživatel vlastní tyto adresáře. Když se služba zastaví, manažer runtime adresář odstraní. Obecnou myšlenkou je spojit existenci těchto aktiv souborového systému s životností služby. Není třeba je vytvářet předem a po zastavení služby se náležitě vyčistí.

$ sudo systemd-run -t -p User=user -p CacheDirectory=foo -p StateDirectory=foo -p RuntimeDirectory=foo -p PrivateTmp=yes ls -ld /run/foo /var/cache/ foo /var/lib/foo /etc/foo /tmp/Spuštění jako jednotka:run-u45882.serviceStiskněte ^] třikrát během 1 s pro odpojení uživatele TTY.drwxr-xr-x  2   40 dubna 26 08:21 /run/ foo           ← automaticky vytvořeno a odstraněnodrwxr-xr-x  2 user user 4096 dubna 26 08:20 /var/cache/foo     ← automaticky vytvořenodrwxr-xr-x. 2 uživatel uživatel 4096 13. listopadu 21:50 /var/lib/foo       ← automaticky vytvořendrwxr-xr-x. 2 root    root    4096 Nov 13 21:50 /etc/foo           ← automaticky vytvořeno, ale není vlastněno uživatelem, protože služba (obvykle) nesmí měnit svou vlastní konfiguracidrwxrwxrwt  2 root     ← mp    root ← "root 40  / 8  2 sticky bit" je nastaven, ale tento adresář není ten, který vidí všichni ostatní 

Samozřejmě, že těchto sedm míst (včetně PrivateTmp= jako dvě) nepokrývají potřeby každé služby, ale měly by pro většinu situací stačit. V ostatních případech ruční nastavení nebo vhodná konfigurace v tmpfiles.d je vždy možnost.

Automatická správa adresářů dobře souvisí s DynamicUser= nastavení a automaticky vytvořené uživatele, a to poskytnutím služby, která běží jako samostatný uživatel a není oprávněna upravovat většinu stromu souborového systému (i když by to umožňovala oprávnění k přístupu k souborům). Služba může i nadále přistupovat k vybraným adresářům a ukládat tam data bez jakéhokoli nastavení kromě konfigurace souboru jednotky.

Například webová služba Pythonu může být spuštěna jako:

$ systemd-run -p DynamicUser=yes -p ProtectHome=yes -p StateDirectory=webserver --working-directory=/srv/www/content python3 -m http.server 8000 

nebo prostřednictvím ekvivalentního souboru jednotky:

[Service]DynamicUser=yesProtectHome=yesStateDirectory=webserverWorkingDirectory=/srv/www/contentExecStart=python3 -m http.server 8000 

Zajišťujeme, aby služba běžela jako přechodný uživatel bez možnosti upravovat systém souborů nebo mít jakýkoli přístup k uživatelským datům.

Zde popsaná nastavení lze považovat za „vysokou úroveň“. I když implementace může být složitá, koncepty samotné jsou snadno pochopitelné a účinek na službu je jasný. Existuje velké množství dalších nastavení, která odeberou různá oprávnění a schopnosti, uzamknou síťové protokoly a laditelné prvky jádra a dokonce deaktivují jednotlivá systémová volání. Ty jsou mimo rozsah tohoto krátkého článku. Viz rozsáhlá referenční dokumentace.

Využití toho všeho

Když dobře rozumíme tomu, co služba dělá a potřebuje, můžeme zvážit, jaká oprávnění jsou vyžadována a co můžeme odebrat. Zřejmí kandidáti kandidují jako neprivilegovaný uživatel a omezují přístup k uživatelským datům pod /home . Čím více povolujeme systemd k nastavení věcí za nás (například pomocí StateDirectory= a přátelé), tím je pravděpodobnější, že služba může úspěšně běžet jako neprivilegovaný uživatel. Služba často potřebuje přístup do konkrétního podadresáře a toho můžeme dosáhnout pomocí ReadWritePaths= a podobná nastavení.

Přidávat bezpečnostní opatření jakýmkoli způsobem automaticky není možné. Bez dobrého pochopení toho, co služba potřebuje v různých konfiguračních scénářích a pro různé operace, nemůžeme definovat užitečný sandbox. To znamená, že sandboxing služeb nejlépe provedou jejich autoři nebo správci.

Hodnocení a status quo

Počet možných nastavení je velký a nová jsou přidávána s každým vydáním systemd . Udržet krok s tím je těžké. Systemd poskytuje nástroj pro vyhodnocení použití direktiv sandboxing v souboru jednotek. Výsledky by měly být považovány za nápovědu — koneckonců, jak již bylo zmíněno výše, automatické vytváření bezpečnostní politiky je obtížné a jakékoli hodnocení pouze počítá, co se používá a co ne, bez hlubokého pochopení toho, co je pro danou službu důležité.

$ Systemd-Analyze Security Systemd-Resolved. 0.1✓ PrivateDevices =Služba nemá přístup k hardwarovým zařízením ✓ PrivateMounts =Service Can't Instalace System Mounchs PrivateTMP =Služba běží ve speciální bootovací fázi, možnost se nepoužije ✗ soukromé uživatele =služba má přístup k ostatním uživatelům 0.2 ProtecThome =Služba běží ve speciální fázi spouštěcí fáze , možnost neplatí                ✓ ProtectKernelLogs=     Služba nemůže číst ani zapisovat do kruhové vyrovnávací paměti protokolu jádra          ✓ ProtectKernelModules=  Služba nemůže načíst nebo znovu Moduly jádra ad jádra ✓ ProtectherNelTunables =Service nemůže měnit laditelné jádro (/proc/sys,…) ProtectSystem =Služba běží ve speciální bootovací fázi, možnost se nepoužije ✓ Doplňkové skupiny =Služba nemá žádné doplňkové skupiny ... → Celková úroveň expozice pro Systemd-- vyřešeno.Service:2.1 OK 🙂 $ SYSTEMD-ANALYZE Zabezpečení httpd.service Název Popis expozice ... ✗ User =/Dynamicuser =Service běží jako uživatel 0.4✗ DeviceAllow =Služba nemá žádné zařízení ACL 0,2✗ PrivateDevices =Služba Potenciálně má přístup k hardwarová zařízení                 0,2✓ PrivateMounts=         Služba nemůže nainstalovat systémová připojení                                  ✓ Soukromá Tmp =         Dočasné soubory Ware ✗ Privatesers =Service má přístup k ostatním uživatelům 0,2✗ ProtecTome =Service má plný přístup k domovským adresářům 0.2✗ ProtectKernellogs =Služba může číst nebo zapisovat do vyrovnávací paměti protokolu jádra 0.2✗ ProtectKernelModules =Služba se může načíst nebo číst moduly jádra může načíst nebo číst jádrové modul 0,2✗ ProtectKerNelTunables =Service může změnit laditelné jádro 0,2✗ ProtectSystem =Služba má plný přístup k hierarchii souborů OS 0.2 Doplňkové skupiny =Služba běží jako kořen, na opci nezáleží ... → Celková úroveň expozice pro httpd.Service:9.2 Neuspokojenost /code>

Opět to neznamená, že služba je nezabezpečená, ale že nepoužívá systemd bezpečnostní primitiva.

Při pohledu na úroveň celé distribuce:

$ systemd-analyze security '*' 

Vidíme, že většina služeb má velmi vysoké skóre (tj. špatné). Nemůžeme shromáždit takové statistiky o různých vnitropodnikových službách, ale zdá se rozumné předpokládat, že jsou podobné. Určitě je zde spousta nízko visících plodů a použití relativně jednoduchého sandboxingu by naše systémy učinilo bezpečnějšími.

Zabalit

Nechat systemd správa služeb a sandboxing může být skvělý způsob, jak přidat vrstvu zabezpečení na vaše servery Linux. Zvažte otestování výše uvedených konfigurací, abyste zjistili, co může být pro vaši organizaci přínosem.

V tomto článku jsme se pečlivě vyhnuli jakékoli zmínce o networkingu. Je to proto, že druhá část bude hovořit o aktivaci soketu a sandboxingu služeb pomocí sítě.

[ Nezapomeňte se podívat na cheat sheet systemd, kde najdete další užitečné rady. ]


Linux
  1. Spravujte spouštění pomocí systemd

  2. 10 praktických příkazů systemd:Reference

  3. Jak používat příkaz Systemctl ke správě služeb Systemd

  1. Jak spravovat služby Systemd pomocí Systemctl v systému Linux

  2. Jak vytvořit službu Systemd v Linuxu

  3. Systemd:Použití After a Requires

  1. Jak vypsat Systemd Services v Linuxu

  2. Zkontrolujte spuštěné služby v systému Linux

  3. Ke správě služeb použijte Systemctl