RAND_bytes() failed je tvrdenie o jednom lokálnom primitive, nie o účte, predzdieľanom kľúči alebo vzdialenom porte. Dve veľmi odlišné poruchy vytvárajú rovnaký riadok a zanechávajú rôzne stopy. Jedna je kryptografický backend, ktorý odmieta vydávať bajty; druhá je proces, ktorý nedosiahne zdroj entropie, pre ktorý bol jeho kód postavený. Oddeliť ich vyžaduje jedno prečítanie fronty chýb a jeden pohľad na súborový systém uväzneného procesu, a táto kontrola patrí pred všetko, čo sa vytvorí pod /dev.

Čo návratová hodnota rozlišuje

Dokumentovaný kontrakt rozlišuje tri výsledky, nie dva: 1 pre úspech, -1 keď načítaná metóda RAND nepodporuje požiadavku, a 0 pre ostatné zlyhania, pričom vysvetlenie zostáva vo fronte chýb. Referencia RAND_bytes pridáva bod, ktorý sa dá ľahko prehliadnuť: predvolený generátor sa na podporovaných platformách seeduje z operačného systému, a keď toto seedovanie zlyhá, zostane v chybovom stave, namiesto toho, aby vracal predvídateľné bajty.

Len jedno z tých čísel opisuje prostredie. -1 je otázka buildu, poskytovateľa alebo funkcie, pretože kód žiadal niečo, čo aktívna implementácia neponúka. 0 so sťažnosťou na seedovanie je otázka prostredia, pretože generátor nemohol entropiu vôbec získať. Číslo samo nikdy nepovie ktoré, a názov funkcie tiež nie.

Kedy je skutočnou príčinou skrytý uzol zariadenia

Obmedzená služba vidí iný strom ako shell, do ktorého píšete. Chrootové väzenia, obrazy kontajnerov a spevnené unit súbory pravidelne predkladajú /dev s menej uzlami, než má hostiteľ. Ak zlyhávajúca implementácia otvára /dev/urandom podľa cesty, tento rozdiel stačí na rozbitie štartu, zatiaľ čo hostiteľ sám vyzerá úplne zdravo. Zariadenie existujúce mimo väzenia nič nedokazuje o tom, čo uväznený proces smie otvoriť.

Nie každé náhodné rozhranie však potrebuje cestu. Systémové volanie getrandom v Linuxe neprijíma žiadne meno súboru ani deskriptor súboru a jeho manuálová stránka poznamenáva, že táto vlastnosť je užitočná práve tam, kde chroot skrýva cesty zariadení.

Vysvetlenie chýbajúceho uzla je teda hypotéza o jednej vetve kódu, nie pravidlo o náhodných číslach všeobecne. Drží, keď dôkazy menujú cestu, a je dohadom, keď dôkazy menujú niečo iné.

Najprv prečítajte frontu chýb, potom pohľad procesu

Najrýchlejší spôsob, ako otázku vyriešiť, je prečítať, čo knižnica už zaznamenala, a potom sa pozrieť priamo na pohľad vnútri väzenia. Začnite buildom OpenSSL, ktorý služba skutočne načítala, pretože zásobníky poskytovateľov sa líšia medzi hlavnými verziami a medzi distribúciami. Potom sa opýtajte systemd, ktorý proces beží a aké obmedzenia preň platia. Až keď obe skutočnosti ležia na stole, stojí za to vypísať uzly, ktoré tento proces vidí.

openssl version -a
systemctl show openvpn-server@lab -p MainPID -p PrivateDevices -p DevicePolicy
pid=$(systemctl show -p MainPID --value openvpn-server@lab)
sudo ls -l /proc/"$pid"/root/dev/urandom /proc/"$pid"/root/dev/random

Spúšťajte tieto čítania proti rovnakému procesu, nie proti shellu, ktorý je práve otvorený. Porovnávať /dev hostiteľa s pohľadom nesúvisiaceho procesu je spôsob, akým sa nesprávna závislosť opraví dvakrát.

Závislosť pridajte až vtedy, keď ju viete pomenovať

Keď dôkazy cestu skutočne menujú, oprava je malá: sprístupnite tú jednu cestu vnútri väzenia a všetko ostatné nechajte tak. Bind mount jediného uzla zvyčajne stačí a mknod so štandardnými major a minor číslami uzla dáva rovnaký výsledok v inštaláciách, kde mount nie je možnosťou. Rozšírenie sandboxu, pridelenie prístupu ku každému znakovému zariadeniu alebo vypnutie PrivateDevices vymení cielenú opravu za trvalú bezpečnostnú regresiu.

Entropický démon túto opravu nenahrádza. Balíčky ako haveged menia, ako sa kŕmi jadrový pool; nemôžu vytvoriť cestu, ktorú uväznený proces smie otvoriť. Inštalácia jedného môže vylepšiť graf zdravia, zatiaľ čo volanie open stále zlyháva. Držte oba problémy oddelené, inak bude ďalšie zlyhanie zase pripísané nesprávnej vrstve.

Overte generátor a tunel oddelene

Reštart je jediný test, ktorý znovu použije rovnakú konfiguráciu, rovnaký unit súbor a rovnaké obmedzenie, ktoré zlyhanie spôsobili. Spustite ho a potom čítajte najnovšie záznamy žurnálu, nie vzorku z predchádzajúceho štartu.

sudo systemctl restart openvpn-server@lab
sudo journalctl -u openvpn-server@lab --since -5min --no-pager | grep -iE 'rand|entropy|Initialization Sequence'

Hľadajte v tom výstupe dve oddelené veci: miznúcu správu o náhodnom zdroji a tunel dosahujúci svoj obvyklý štartovný míľnik. Generátor, ktorý zase funguje, odstráni jednu lokálnu poruchu a nehovorí nič o identite servera, prihlasovacích údajoch ani routovaní. Otestujte to s rovnakou klientskou konfiguráciou, ktorá predtým zlyhala, aby bol výsledok porovnateľný a nielen lepší.

Súvisiace články