GNU/Linux >> Znalost Linux >  >> Linux

Je použití /dev/urandom vždy dobrou radou ve věku kontejnerů a izolace?

Napsal jsem odpověď, která podrobně popisuje getrandom() bloky čekající na počáteční entropii.

Myslím si však, že trochu přehání urandom tím, že říká, že "jediný okamžik, kdy /dev/urandom může znamenat bezpečnostní problém kvůli nízké entropii, je během prvních okamžiků nové automatické instalace OS."

Vaše obavy jsou opodstatněné. Mám otevřenou otázku ohledně této věci a jejích důsledků. Problém je v tom, že trvalému náhodnému seedu trvá nějakou dobu, než se přesune ze vstupního fondu do výstupního fondu (blokovací fond a CRNG). Tento problém znamená, že /dev/urandom bude vydávat potenciálně předvídatelné hodnoty několik minut po spuštění. Řešením je, jak říkáte, použít buď blokovací /dev/random , nebo použijte getrandom() nastavit na blokování.

Ve skutečnosti není neobvyklé vidět řádky jako tento v logu jádra při časném bootování:

random: sn: uninitialized urandom read (4 bytes read, 7 bits of entropy available)
random: sn: uninitialized urandom read (4 bytes read, 15 bits of entropy available)
random: sn: uninitialized urandom read (4 bytes read, 16 bits of entropy available)
random: sn: uninitialized urandom read (4 bytes read, 16 bits of entropy available)
random: sn: uninitialized urandom read (4 bytes read, 20 bits of entropy available)

To vše jsou případy, kdy byl neblokující fond zpřístupněn ještě předtím, než bylo shromážděno dostatečné množství entropie. Problém je v tom, že množství entropie je příliš nízké na to, aby bylo v tomto bodě dostatečně kryptograficky bezpečné. Měly by existovat 2 možné 4bajtové hodnoty, avšak s dostupnými pouze 7 bity entropie, to znamená, že existují pouze 2 nebo 128 různých možností.

Zdá se také, že Halderman říká, že zásoba entropie se vyplní při každém spuštění, a ne, jak říká Pornin ve své odpovědi, při úplně první instalaci OS. Ačkoli to pro moji aplikaci není tak důležité, ptám se:co to je?

Je to vlastně otázka sémantiky. Aktuální pool entropie (stránka paměti uchovávaná v jádře, která obsahuje náhodné hodnoty) je při každém bootu vyplněna trvalým semenem entropie a okolním šumem. Entropie však semeno samotný je soubor, který je vytvořen v době instalace a je aktualizován novými náhodnými hodnotami pokaždé, když se systém vypne. Představuji si, že Pornin považuje náhodné semeno za součást zásoby entropie (jako součást obecného systému distribuce a sběru entropie), zatímco Halderman ji považuje za samostatnou (protože zásoba entropie je technicky stránka paměť, nic víc). Pravdou je, že zárodek entropie je přiváděn do zásoby entropie při každém spuštění, ale může trvat několik minut, než zásobu skutečně ovlivní.

Shrnutí tří zdrojů náhodnosti:

  1. /dev/random - Blokovací znakové zařízení snižuje "počet entropie" pokaždé, když je přečteno (přestože entropie není ve skutečnosti vyčerpána). Blokuje však také, dokud se při spouštění nenashromáždí dostatečná entropie, takže je bezpečné jej brzy používat.

  2. /dev/urandom - Neblokující znakové zařízení bude vydávat náhodná data, kdykoli z něj někdo čte. Jakmile bude shromážděna dostatečná entropie, bude na výstupu prakticky neomezený proud nerozeznatelný od náhodných dat. Bohužel z důvodů kompatibility je čitelný i na začátku bootování, než se nashromáždí dostatek jednorázové entropie.

  3. getrandom() - Systémové volání, které bude vydávat náhodná data, pokud je fond entropie správně inicializován s minimálním požadovaným množstvím entropie. Ve výchozím nastavení se čte z neblokujícího fondu. Pokud je uveden GRND_NONBLOCK příznak, vrátí chybu, pokud není dostatek entropie. Pokud je uveden GRND_RANDOM flag, bude se chovat identicky jako /dev/random , jednoduše blokovat, dokud nebude k dispozici entropie.

Doporučuji použít třetí možnost, getrandom() systémové volání. To umožní procesu číst kryptograficky zabezpečená náhodná data vysokou rychlostí a zablokuje se pouze na začátku bootování, když není shromážděno dostatečné množství entropie. Pokud je os.urandom() Pythonu funkce funguje jako obal tohoto syscall, jak říkáte, pak by mělo být v pořádku použít. Vypadá to, že se ve skutečnosti hodně diskutovalo o tom, zda by to tak mělo být nebo ne, a nakonec to skončilo blokováním, dokud nebude k dispozici dostatek entropie.

Zamyslete se trochu dále:jaké jsou osvědčené postupy pro prostředí, která jsou tak svěží a naivní, jak jsem popsal výše, ale která fungují na zařízeních s poměrně mizernými vyhlídkami na počáteční generování entropie?

Toto je běžná situace a existuje několik způsobů, jak ji řešit:

  • Ujistěte se, že blokujete při časném spouštění, například pomocí /dev/random nebo getrandom() .

  • Pokud je to možné, ponechte si trvalý náhodný zdroj (tj. pokud můžete zapisovat do úložiště při každém spuštění).

  • A co je nejdůležitější, použijte hardwarový RNG . Toto je nejúčinnější opatření č. 1.

Použití hardwarového generátoru náhodných čísel je velmi důležité. Linuxové jádro inicializuje svůj fond entropie s jakýmkoli podporovaným rozhraním HWRNG, pokud takové existuje, čímž se zcela odstraní zaváděcí díra v entropii. Mnoho vestavěných zařízení má své vlastní generátory náhodnosti.

To je zvláště důležité pro mnoho vestavěných zařízení, protože nemusí mít časovač s vysokým rozlišením, který je vyžadován pro jádro, aby bezpečně generovalo entropii z okolního hluku. Některé verze procesorů MIPS například nemají čítač cyklů.

Jak a proč navrhujete používat urandom k nasévání (tuším uživatelské země?) CSPRNG? Jak to překonává getrandom?

Neblokující zařízení náhodnosti není navrženo pro vysoký výkon. Až donedávna bylo zařízení obscénně pomalé kvůli použití SHA-1 pro náhodnost spíše než proudové šifry jako nyní. Použití rozhraní jádra pro náhodnost může být méně efektivní než místní CSPRNG v uživatelském prostoru, protože každé volání jádra vyžaduje nákladné přepínání kontextu. Jádro bylo navrženo tak, aby odpovídalo aplikacím, které z něj chtějí intenzivně čerpat, ale komentáře ve zdrojovém kódu jasně ukazují, že to nepovažují za správnou věc:

/*
 * Hack to deal with crazy userspace progams when they are all trying
 * to access /dev/urandom in parallel.  The programs are almost
 * certainly doing something terribly wrong, but we'll work around
 * their brain damage.
 */

Populární kryptoknihovny, jako je OpenSSL, podporují generování náhodných dat. Mohou být nasazeny jednou nebo příležitostně znovu nasazeny a jsou schopny více těžit z paralelizace. Navíc umožňuje psát přenosný kód, který se nespoléhá na chování žádného konkrétního operačního systému nebo verze operačního systému.

Pokud nepotřebujete velké množství náhodnosti, je zcela v pořádku použít rozhraní jádra. Pokud vyvíjíte kryptoaplikaci, která bude během své životnosti potřebovat hodně náhodnosti, možná budete chtít použít knihovnu jako OpenSSL, která se s tím vypořádá za vás.


Systém může být ve třech stavech:

  1. Neshromáždil dostatek entropie k bezpečné inicializaci CPRNG.
  2. Shromáždil dostatek entropie k bezpečné inicializaci CPRNG a:

    2a. Vydal více entropie, než bylo shromážděno.

    2b. Vydal méně entropie, než kolik shromáždil.

Historicky si lidé mysleli, že rozdíl mezi (2a) a (2b) je důležitý. To způsobilo dva problémy. Za prvé, je to špatně – rozdíl je pro správně navržený CPRNG bezvýznamný. A za druhé, důraz na rozlišení (2a)-vs-(2b) způsobil, že lidé přehlédli rozdíl mezi (1) a (2), který je ve skutečnosti opravdu důležitý. Lidé se tak nějak zhroutili (1) a stali se zvláštním případem (2a).

To, co opravdu chcete, je něco, co blokuje ve stavu (1) a neblokuje ve stavu (2a) nebo (2b).

Bohužel za starých časů záměna mezi (1) a (2a) znamenala, že to nebylo možné. Vaše jediné dvě možnosti byly /dev/random , která byla blokována v případech (1) a (2a) a /dev/urandom , který nikdy neblokoval. Ale stav (1) téměř nikdy nenastane – a nenastává vůbec v dobře nakonfigurovaných systémech, viz níže – pak /dev/urandom je lepší pro téměř všechny systémy, téměř vždy. Odtud pocházejí všechny ty blogové příspěvky o „vždy používejte urandom“ – snažily se přesvědčit lidi, aby přestali dělat nesmyslné a škodlivé rozlišování mezi stavy (2a) a (2b).

Ale ano, ani jedno z toho není to, co vlastně chceš. Tedy novější getrandom syscall, které ve výchozím nastavení blokuje ve stavu (1) a neblokuje ve stavech (2a) nebo (2b). Na moderním Linuxu by se tedy ortodoxie měla aktualizovat na:vždy používejte getrandom s výchozím nastavením .

Extra vrásky:

  • getrandom také podporuje jiný než výchozí režim, kde se chová jako /dev/random , o kterou lze požádat prostřednictvím GRND_RANDOM vlajka. AFAIK tento příznak není nikdy ve skutečnosti užitečný, ze stejných důvodů, které byly popsány u starých blogových příspěvků. Nepoužívejte to.

  • getrandom má také některé další bonusové výhody oproti /dev/urandom :funguje bez ohledu na rozvržení vašeho souborového systému a nevyžaduje otevření deskriptoru souboru, což je obojí problematické pro generické knihovny, které chtějí učinit minimální předpoklady o prostředí, ve kterém budou používány. To neovlivňuje kryptografické zabezpečení , ale provozně je to pěkné.

  • Dobře nakonfigurovaný systém bude mít vždy k dispozici entropii, dokonce i v časném spouštění (tj. nikdy byste se neměli dostat do stavu (1). Existuje mnoho způsobů, jak to zvládnout:uložit nějakou entropii z předchozího spouštění a použít ji při dalším. Nainstalujte hardwarový RNG. Kontejnery Docker používají jádro hostitele, a tak získávají přístup k jeho fondu entropie. Vysoce kvalitní nastavení virtualizace mají způsoby, jak umožnit hostujícímu systému načíst entropii z hostitelského systému prostřednictvím rozhraní hypervisoru (např. vyhledat „virtio rng“). Ale samozřejmě ne všechny systémy jsou dobře nastavené. Pokud máte špatně nakonfigurovaný systém, měli byste se podívat, zda jej můžete místo toho dobře nakonfigurovat. V zásadě by to mělo být snadné a levné, ale ve skutečnosti lidé neupřednostňují zabezpečení, takže... to může vyžadovat provedení věcí, jako je změna poskytovatele cloudu nebo přechod na jinou vestavěnou platformu. A bohužel můžete zjistit, že je to dražší, než jste vy (nebo váš šéf) ochotni zaplatit, takže budete muset řešit špatně nakonfigurovaný systém. Pokud ano, mé sympatie.

  • Jak poznamenává @forest, pokud potřebujete hodně hodnot CPRNG, pak pokud jste velmi opatrní, můžete to urychlit spuštěním vlastního CPRNG v uživatelském prostoru při použití getrandom pro (znovu)setí. To je však do značné míry věc „pouze pro odborníky“, stejně jako každá situace, kdy se ocitnete při implementaci svých vlastních kryptoprimitiv. Měli byste to udělat pouze v případě, že jste to změřili a zjistili pomocí getrandom přímo je pro vaše potřeby příliš pomalé a máte významné kryptografické znalosti. Je velmi snadné zpackat implementaci CPRNG tak, že vaše zabezpečení bude totálně narušeno, ale výstup stále „vypadá“ náhodně, takže si toho nevšimnete.


Linux
  1. Linux:Rozdíl mezi /dev/console, /dev/tty a /dev/tty0?

  2. Jak přenosné jsou /dev/stdin, /dev/stdout a /dev/stderr?

  3. /dev/random Extrémně pomalé?

  1. Kdy mám použít /dev/shm/ a kdy /tmp/?

  2. Linux:Rozdíl mezi /dev/console , /dev/tty a /dev/tty0

  3. jádro:deaktivace /dev/kmem a /dev/mem

  1. Jak Linux používá /dev/tty a /dev/tty0

  2. echo nebo print /dev/stdin /dev/stdout /dev/stderr

  3. Proč jsou < nebo > vyžadovány pro použití /dev/tcp