Miliony binárek poté. Jak se Linux upevnil

Miliony binárek poté. Jak se Linux upevnilTL;DR. V tomto článku prozkoumáme bezpečnostní schémata (hardening schemes), která fungují přímo z krabice v pěti populárních distribucích Linuxu. Pro každou z nich jsme vzali výchozí konfiguraci jádra, nainstalovali všechny balíčky a analyzovali bezpečnostní schémata ve vnořených binárních souborech. Uvažujeme o distribucích OpenSUSE 12.4, Debian 9, CentOS, RHEL 6.10 a 7, a také Ubuntu 14.04, 12.04 a 18.04 LTS.

Výsledky potvrzují, že i základní schémata, jako jsou stack canaries a position-independent code, ještě nejsou široce využívána. Situace je ještě horší u kompilátorů, pokud jde o ochranu proti zranitelnostem, jako je stack clash, které se dostaly do centra pozornosti v lednu po zveřejnění informací o zranitelnostech v systemd. Ale není všechno tak beznadějné. Ve významné části binárních souborů jsou implementovány základní ochranné metody, a jejich počet roste s každou verzí.

Kontrola ukázala, že nejvíce ochranných metod je implementováno v Ubuntu 18.04 na úrovni operačního systému a aplikací, následuje Debian 9. Na druhou stranu, v OpenSUSE 12.4, CentOS 7 a RHEL 7 jsou také implementována základní ochranná schémata, a ochrana proti stack clash je široše aplikována s mnohem hustším souborem balíčků ve výchozím nastavení.

Úvod

Zajištění vysoké kvality softwaru je obtížné. Navzdory obrovskému množství pokročilých nástrojů pro statickou analýzu kódu a dynamickou analýzu za běhu, jakož i značnému pokroku v vývoji kompilátorů a programovacích jazyků, moderní software stále trpí zranitelnostmi, které jsou neustále zneužívány útočníky. Situace je ještě horší v ekosystémech, které zahrnují zastaralý kód. V takových případech čelíme nejen věčnému problému hledání potenciálně zneužitelných chyb, ale jsme také omezeni tvrdými rámci zpětné kompatibility, které často vyžadují zachování omezeného, a ještě horšího zranitelného nebo chybového kódu.

Zde přicházejí na scénu metody ochrany nebo zpevnění softwaru (hardening). Některé typy chyb nemůžeme zabránit, ale můžeme ztížit život útočníkovi a částečně vyřešit problém tím, že zamezíme nebo ztížíme jejich provádění. provozování těchto chyb. Tato ochrana se používá ve všech moderních operačních systémech, přičemž metody se výrazně liší v obtížnosti, účinnosti a výkonnosti: od zásobníkových kanárků (stack canaries) a ASLR až po komplexní ochrany CFI a ROP. V tomto článku se podíváme na to, jaké metody ochrany se používají v nejpopulárnějších distribucích Linuxu v defaultním nastavení, a také prozkoumáme vlastnosti binárníků, které se šíří prostřednictvím systémů správy balíků každé distribuce.

CVE a bezpečnost

Všichni jsme viděli články s názvy jako "Nejzranitelnější aplikace roku" nebo "Nejzranitelnější operační systémy". Obvykle tam uvádějí statistiky o celkovém počtu záznamů o zranitelnostech typu CVE (Common Vulnerability and Exposures), získaných z Národní databáze zranitelnosti (NVD) od NIST a dalších zdrojů. Později jsou tyto aplikace nebo operační systémy hodnoceny podle počtu CVE. Bohužel, ačkoliv jsou CVE velmi užitečné pro sledování problémů a informování dodavatelů a uživatelů, příliš toho neříkají o skutečné bezpečnosti softwaru.

Pro příklad zvažme celkový počet CVE za poslední čtyři roky pro jádro Linux a pět nejpopulárnějších serverových distribucí, konkrétně Ubuntu, Debian, Red Hat Enterprise Linux a OpenSUSE.

Miliony binárek poté. Jak se Linux upevnil
Obr. 1

Co nám říká tento graf? Znamená větší počet CVE, že jedna distribuce je zranitelnější než jiná? Odpověď je ne. Například v tomto článku uvidíte, že v Debianu byla implementována přísnější ochranná opatření ve srovnání třeba s OpenSUSE nebo RedHat Linux, a přesto má Debian více CVE. Neboť to neznamená oslabování bezpečnosti: ani přítomnost CVE neznamená, že zranitelnost je zneužitelná. Hlavní skóre závažnosti poskytuje představu o tom, jak je pravděpodobné využití zranitelnosti, ale nakonec je zneužitelnost do značné míry závislá na ochraně přítomné v postižených systémech a také na zdrojích a možnostech útočníků. Navíc, absence zpráv CVE nic neříká o jiných nezaregistrovaných nebo neznámých Zranitelnostech. Rozdíl v CVE může být vysvětlen nejen kvalitou softwaru, ale také dalšími faktory, včetně prostředků vyčleněných na testování nebo velikosti uživatelské základny. V našem příkladu může větší počet CVE u Debianu jednoduše naznačovat, že Debian poskytuje více softwarových balíčků.

Samozřejmě, systém CVE poskytuje užitečné informace, které umožňují vytvářet odpovídající ochrany. Čím lépe chápeme příčiny selhání programu, tím snadněji můžeme určit možné způsoby zneužití a vyvinout odpovídající mechanismy detekce a reakce. Na obr. 2 jsou znázorněny kategorie zranitelností pro všechny distribuce za poslední čtyři roky (zdroj). Je zřejmé, že většina CVE spadá do následujících kategorií: odmítnutí služby (DoS), vykonání kódu, přetečení, poškození paměti, únik (exfiltrace) informací a eskalace privilegií. Ačkoli mnohé CVE jsou zohledněny několikrát v různých kategoriích, celkově se stejné problémy udržují rok co rok. V další části článku posoudíme použití různých ochranných schémat k prevenci zneužití uvedených zranitelností.

Miliony binárek poté. Jak se Linux upevnil
Obr. 2

Úkoly

V tomto článku se chystáme odpovědět na následující otázky:

  • Jaká je bezpečnost různých distribucí Linuxu? Jaké ochranné mechanismy existují v jádru a aplikacích uživatelského prostoru?
  • Jak se v průběhu času změnilo přijetí ochranných mechanismů pro různé distribuce?
  • Jaké jsou průměrné závislosti balíčků a knihoven u každé distribuce?
  • Jaké ochrany jsou implementovány pro každý binární soubor?

Volba distribucí

Ukazuje se, že je obtížné najít přesnou statistiku o instalacích distribucí, protože v mnoha případech počet stažení neodráží počet skutečných instalací. Nicméně varianty Unixu tvoří většinu serverových systémů (na webových serverech 69,2 %, podle statistikách W3techs a dalších zdrojů), a jejich podíl neustále roste. Proto jsme se v našem výzkumu zaměřili na distribuce dostupné přímo na platformě Google Cloud. Konkrétně jsme vybrali následující operační systémy:

Distribuce/verze
Jádro
Build

OpenSUSE 12.4
4.12.14-95.3-default
#1 SMP Wed Dec 5 06:00:48 UTC 2018 (63a8d29)

Debian 9 (stretch)
4.9.0-8-amd64
#1 SMP Debian 4.9.130-2 (2018-10-27)

CentOS 6.10
2.6.32-754.10.1.el6.x86_64
#1 SMP Tue Jan 15 17:07:28 UTC 2019

CentOS 7
3.10.0-957.5.1.el7.x86_64
#1 SMP Fri Feb 1 14:54:57 UTC 2019

Red Hat Enterprise Linux Server 6.10 (Santiago)
2.6.32-754.9.1.el6.x86_64
#1 SMP Wed Nov 21 15:08:21 EST 2018

Red Hat Enterprise Linux Server 7.6 (Maipo)
3.10.0-957.1.3.el7.x86_64
#1 SMP Thu Nov 15 17:36:42 UTC 2018

Ubuntu 14.04 (Trusty Tahr)
4.4.0–140-generic

#166~14.04.1-Ubuntu SMP Sat Nov 17 01:52:43 UTC 20…

Ubuntu 16.04 (Xenial Xerus)
4.15.0–1026-gcp
#27~16.04.1-Ubuntu SMP Fri Dec 7 09:59:47 UTC 2018

Ubuntu 18.04 (Bionic Beaver)
4.15.0–1026-gcp
#27-Ubuntu SMP Thu Dec 6 18:27:01 UTC 2018

Tabulka 1

Analýza

Prozkoumáme výchozí konfiguraci jádra i vlastnosti balíčků dostupných prostřednictvím správce balíčků každé distribuce hned po instalaci. Zvažujeme pouze balíčky z výchozích zrcadel každé distribuce, ignorujeme balíčky z nestabilních repozitářů (např. zrcadla 'testing' v Debianu) a balíčky třetích stran (např. balíčky Nvidia ze standardních zrcadel). Navíc se nezabýváme uživatelsky kompilovanými jádry nebo konfiguracemi s vyšší úrovní zabezpečení.

Analýza konfigurace jádra

Použili jsme skript pro analýzu založený na otevřeném kontroloru kconfig. Zohledňujeme výchozí bezpečnostní nastavení zmiňovaných distribucí a srovnáváme je s seznamem od Projektu ochrany jádra (KSPP). Pro každé konfigurační nastavení tabulka 2 popisuje požadované nastavení: tik je za distribuce, které odpovídají doporučením KSSP (objasnění pojmů viz. zde; v budoucích článcích podrobně popisujeme, jak byly některé z těchto ochranných metod vyvinuty a jak lze systém hacknout v jejich nepřítomnosti).

Miliony binárek poté. Jak se Linux upevnil

Miliony binárek poté. Jak se Linux upevnil

Obecně platí, že nová jádra mají přísnější výchozí nastavení. Například CentOS 6.10 a RHEL 6.10 na jádře 2.6.32 postrádají většinu kritických funkcí implementovaných v novějších jádrech, jako jsou SMAP, přísná povolení RWX, randomizaci adres nebo ochranu copy2usr. Je důležité poznamenat, že mnohé z volitelných konfigurací z tabulky chybí ve starších verzích jádra a v reálném použití nejsou použitelné — v tabulce je to však stále uvedeno jako nedostatečné zabezpečení. Podobně, pokud konfigurace v dané verzi chybí, ale pro zabezpečení by měla být tato konfigurace zakázána, považuje se to za rozumné nastavení.

Ještě jeden aspekt interpretace výsledků: některé konfigurace jádra, které zvyšují útočnou plochu, mohou být zároveň použity pro bezpečnost. Takové příklady zahrnují uprobes a kprobes, moduly jádra a BPF/eBPF. Naše doporučení je použít výše uvedené mechanismy pro zajištění skutečné ochrany, neboť jejich použití není triviální a předpokládá, že se škodlivé subjekty již dostaly do systému. Ale pokud jsou tyto volby aktivovány, měl by systémový administrátor aktivně monitorovat zneužívání.

Dalším zkoumáním zápisů v tabulce 2 vidíme, že moderní jádra nabízí několik možností pro ochranu před zneužitím takových zranitelností, jako je únik informací a přetečení zásobníku/haldy. Pozorujeme však, že i ty nejnovější populární distribuce ještě neimplementovaly složitější ochranu (například s patchem grsecurity) nebo moderní ochranu proti útokům na opětovné použití kódu (například kombinace randomizace se schématy typu R^X pro kód). Co je ještě horší, i tyto pokročilejší ochranné prostředky nechrání před celým spektrem útoků. Je tedy pro systémové administrátory mimořádně důležité doplnit rozumné konfigurace řešeními, která nabízejí detekci a prevenci exploitů v reálném čase.

Analýza aplikací

Není překvapením, že jednotlivé distribuce mají různé vlastnosti balíčků, možnosti kompilace, závislosti knihoven atd. Rozdíly existují i mezi příbuznými distribucemi a balíčky s malým počtem závislostí (například coreutils v Ubuntu nebo Debianu). Abychom ohodnotili rozdíly, stáhli jsme všechny dostupné balíčky, extrahovali jejich obsah a analyzovali binární soubory a závislosti. Pro každý balíček jsme sledovali další balíčky, od kterých závisel, a pro každý binární soubor jsme sledovali jeho závislosti. V této části shrneme naše závěry.

Distribuce

Celkově jsme stáhli 361 556 balíčků pro všechny distribuce, přičemž jsme zrcadlo používali pouze pro výchozí balíčky. Ignorovali jsme balíčky bez vykonatelných ELF souborů, jako jsou zdrojové kódy, písma atd. Po filtrování zůstalo 129 569 balíčků, které obsahují celkem 584 457 binárních souborů. Rozdělení balíčků a souborů podle distribucí je znázorněno na obr. 3.

Miliony binárek poté. Jak se Linux upevnil
Obr. 3

Je patrné, že čím modernější distribuce, tím více balíčků a binárních souborů obsahuje, což je logické. Balíčky Ubuntu a Debian zahrnují také mnohem více binárních souborů (jak vykonatelných, tak dynamických modulů a knihoven) než CentOS, SUSE a RHEL, což potenciálně ovlivňuje útočnou plochu Ubuntu a Debian (je třeba poznamenat, že čísla odrážejí všechny binárky všech verzí balíčku, tedy některé soubory jsou analyzovány několikrát). To je zvlášť důležité, pokud vezmeme v úvahu závislosti mezi balíčky. Zranitelnost v binárním souboru jednoho balíčku může ovlivnit mnoho částí ekosystému, jak může zranitelná knihovna ovlivnit všechny binární soubory, které ji importují. Jako výchozí bod se podívejme na rozdělení počtu závislostí podle balíčků v různých operačních systémech:

Miliony binárek poté. Jak se Linux upevnil
Obr. 4

V téměř všech distribucích má 60% balíčků minimálně 10 závislostí. Kromě toho má několik balíčků výrazně více závislostí (více než 100). Totéž platí pro zpětné závislosti balíčků: jak se očekávalo, několik balíčků je používáno mnoha jinými balíčky v distribuci, a proto mají zranitelnosti v těchto několika vybraných vysoké riziko. Jako příklad je v následující tabulce uvedeno 20 balíčků s nejvyšším počtem zpětných závislostí v SLES, CentOS 7, Debian 9 a Ubuntu 18.04 (v každé buňce je uveden balíček a počet zpětných závislostí).

Miliony binárek poté. Jak se Linux upevnil
Tabulka 3

Zajímavý fakt. I když všechny analyzované OS jsou postaveny pro architekturu x86_64 a většina balíčků je definována jako x86_64 a x86, balíčky často obsahují binární soubory pro jiné architektury, jak je znázorněno na obr. 5.

Miliony binárek poté. Jak se Linux upevnil
Obr. 5

V následující části se hlouběji zaměříme na charakteristiky analyzovaných binárních souborů.

Statistika ochrany binárních souborů

Jako absolutní minimum je třeba se seznámit se základním souborem možností ochrany pro existující binární soubory. Několik distribucí Linuxu přichází se skripty, které tyto kontroly provádějí. Například v Debianu/Ubuntu existuje takový skript. Zde je příklad jeho fungování:

$ hardening-check $(which docker)
/usr/bin/docker:
 Pozice nezávislý spustitelný soubor: ano
 Ochrana zásobníku: ano
 Fortify Source funkce: ne, nalezeny pouze nechráněné funkce!
 Přenosové adresy pouze pro čtení: ano
 Ihned vazba: ano

Skript kontroluje pět ochranných funkcí:

  • Pozice nezávislý spustitelný soubor (PIE): ukazuje, zda lze umístit textovou část programu do paměti s cílem dosáhnout randomizace, pokud je v jádře povoleno ASLR.
  • Ochrana zásobníku: jsou zapnuty zásobníkové kanárky na ochranu proti útokům způsobeným přetečením zásobníku.
  • Fortify Source: jsou nebezpečné funkce (například strcpy) nahrazeny jejich bezpečnějšími alternativami, a u volání kontrolovaných za běhu – jejich neověřenými alternativami (např. memcpy místo __memcpy_chk).
  • Relokace pouze pro čtení (RELRO): jsou záznamy tabulky relokací označeny jako „pouze pro čtení“, pokud jsou aktivovány před výpočtem.
  • Ihned vazba: umožňuje linkeru runtime provést všechny relokace před začátkem vykonávání programu (to je ekvivalentní plnému RELRO).

Jsou uvedené mechanismy dostatečné? Bohužel ne. Existují známé způsoby, jak obcházet všechny výše uvedené ochrany, ale čím přísnější je ochrana, tím vyšší je práh pro útočníka. Například metody obcházení RELRO je těžší implementovat, pokud je aktivní PIE a ihned vazba. Podobně plné ASLR vyžaduje dodatečnou práci pro vytvoření funkčního exploit. Nicméně rafinovaní útočníci jsou již připraveni tyto ochrany překonat: jejich absence v podstatě urychlí prolomení. Proto je nesmírně důležité, aby byly tyto opatření považovány za nezbytné. minimum.

Chtěli jsme prozkoumat, kolik binárních souborů v posuzovaných distribucích je chráněno těmito a dalšími třemi metodami:

  • Nepoužitelný bit (NX) zabraňuje vykonávání v jakékoli oblasti, která nemá být vykonávaná, například na haldě zásobníku atd.
  • RPATH/RUNPATH označuje cestu vykonávání, kterou používá dynamický načítač k nalezení odpovídajících knihoven. První z nich je povinný pro všechny moderní systémy: jeho absence umožňuje útočníkům náhodně zapisovat payload do paměti a vykonávat jej tak, jak je. Co se týče druhého, nesprávné konfigurace prováděcích cest pomáhají zavést nespolehlivý kód, který může vést k řadě problémů (například, eskalace privilegií, a také další problémy).
  • Ochrana před kolizí zásobníku zabezpečuje ochranu proti útokům, které nutí zásobník překrýt jiné oblasti paměti (např. hromadu). Vzhledem k nedávným exploitům zneužívajícím zranitelnosti kolize hromady v systemd, považovali jsme za vhodné zahrnout tento mechanismus do naší datové sady.

Takže bez dalších formalit přejdeme k číslům. Tabulky 4 a 5 obsahují shrnutí analýzy spustitelných souborů a knihoven různých distribucí.

  • Jak vidno, ochrana NX je implementována všude, s výjimkou několika málo. Zvlášť lze poznamenat její o něco nižší použití v distribucích Ubuntu a Debian ve srovnání s CentOS, RHEL a OpenSUSE.
  • Zásobníkové kanárky jsou na mnoha místech nedostatečné, zejména ve starších jádrech distribucí. Nějaký pokrok je vidět v posledních distribucích CentOS, RHEL, Debian a Ubuntu.
  • S výjimkou Debianu a Ubuntu 18.04 je v většině distribucí špatná podpora PIE.
  • Ochrana proti kolizím zásobníku je slabě implementována v OpenSUSE, CentOS 7 a RHEL 7 a prakticky chybí v ostatních.
  • Všechny distribuce s moderními jádry mají určitou podporu RELRO, přičemž vedoucí je Ubuntu 18.04 a na druhém místě Debian.

Jak již bylo zmíněno, metriky v této tabulce jsou průměry přes všechny verze binárního souboru. Pokud se zaměříme pouze na poslední verze souborů, čísla budou jiná (např. viz pokrok Debianu s implementací PIE). Kromě toho většina distribucí obvykle při výpočtu statistik kontroluje ochranu pouze několika funkcí v binárním kódu, zatímco v naší analýze je uvedeno skutečné procento zpevnili funkcí. Proto, pokud je v binárním souboru chráněno 5 z 50 funkcí, uvedeme mu hodnocení 0,1, což odpovídá 10% zpevněných funkcí.

Miliony binárek poté. Jak se Linux upevnil
Tabulka 4. Vlastnosti ochrany pro spustitelné soubory zobrazené na obr. 3 (implementace odpovídajících funkcí v procentech z celkového počtu spustitelných souborů)

Miliony binárek poté. Jak se Linux upevnil
Tabulka 5. Vlastnosti ochrany pro knihovny zobrazené na obr. 3 (implementace odpovídajících funkcí v procentech z celkového počtu knihoven)

Takže pokrok je? Určitě je: to je vidět ze statistik k jednotlivým distribucím (např., Debian), a také z výše uvedených tabulek. Jako příklad na obr. 6 je zobrazeno zavádění ochranných mechanismů ve třech po sobě jdoucích distribucích Ubuntu LTS 5 (vynechali jsme statistiku ochrany před přetečením zásobníku). Zaznamenáváme, že s každou verzí více souborů podporuje zásobníkové kanárky a také se postupně stále více binárních souborů dodává s plnou ochranou RELRO.

Miliony binárek poté. Jak se Linux upevnil
Obr. 6

Bohužel, řada spustitelných souborů v různých distribucích stále nemá žádnou z výše uvedených ochran. Například u Ubuntu 18.04 lze pozorovat binární soubor ngetty (náhrada getty), stejně jako shell mksh a lksh, interpretr picolisp, balíčky nvidia-cuda-toolkit (populární balíček pro aplikace s GPU akcelerací, jako jsou frameworky strojového učení) a klibc-utils. Podobně, binární soubor mandos-client (administrační nástroj umožňující automatické restartování strojů s šifrovanými souborovými systémy), stejně jako rsh-redone-client (nová implementace rsh a rlogin) jsou dodávány bez ochrany NX, ačkoliv mají oprávnění SUID :(. Kromě toho u několika suid-binárních souborů chybí základní ochrana, jako například zásobníkové kanárky (například binární soubor Xorg.wrap z balíčku Xorg).

Shrnutí a závěrečná poznámka

V tomto článku jsme vyzdvihli několik bezpečnostních vlastností moderních distribucí Linuxu. Analýza ukázala, že v poslední distribuci Ubuntu LTS (18.04) se průměrně implementuje nejsilnější ochrana na úrovni OS a aplikací mezi distribucemi s relativně novými jádry, jako jsou Ubuntu 14.04, 12.04 a Debian 9. Nicméně zvažované distribuce CentOS, RHEL a OpenSUSE v našem datovém souboru standardně dodávají hustší sadu balíčků, a v posledních verzích (CentOS a RHEL) mají vyšší procento implementace ochrany proti přetečení zásobníku ve srovnání se svými konkurenty na bázi Debianu (Debian a Ubuntu). Porovnáním verzí CentOS a RedHat si všímáme výrazných zlepšení v zavedení zásobníkových kanárků a RELRO z verzí 6 na 7, ale průměrně má CentOS více funkcí než RHEL. Celkově by všem distribucím měla být věnována zvláštní pozornost ochraně PIE, která, s výjimkou Debianu 9 a Ubuntu 18.04, byla implementována v méně než 10 % binárních souborů z našeho datového souboru.

Nakonec je třeba poznamenat: ačkoliv jsme prováděli výzkum ručně, existuje mnoho bezpečnostních nástrojů (například, Lynis, Tiger, Hubble), které provádějí analýzu a pomáhají se vyhnout nebezpečným konfiguracím. Bohužel ani silná ochrana v rozumných konfiguracích nezaručuje absenci exploitu. Proto jsme pevně přesvědčeni, že je životně důležité zajistit spolehlivý monitoring a prevenci útoků v reálném čase, zaměřením se na vzory exploatace a jejich předcházení.

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster