Skip to content

Le password memorizzate sono sicure?

Il nostro team specializzato dopo alcuni giorni di lavoro e raccolta dati, abbiamo trovato i dati necessari, speriamo che siano molto utili nel tuo piano.

Soluzione:

State toccando un punto dolente...

Storicamente i computer erano mainframe dove molti utenti distinti lanciavano sessioni e processi sulla stessa macchina fisica. I sistemi Unix-like (ad esempio Linux), ma anche VMS e i suoi parenti (e questa famiglia comprende tutti i Windows della linea NT, quindi 2000, XP, Vista, 7, 8...), sono stati strutturati in modo da supportare il modello mainframe.

Pertanto, l'hardware fornisce livelli di privilegio. Un elemento centrale del sistema operativo è il kernel che viene eseguito al livello di privilegio più alto (sì, so che ci sono delle sottigliezze per quanto riguarda la virtualizzazione) e gestisce i livelli di privilegio. Le applicazioni vengono eseguite a un livello inferiore e il kernel impedisce loro di leggere o scrivere la memoria dell'altra. Le applicazioni ottengono la RAM da pagine (in genere 4 o 8 kB) dal kernel. Un'applicazione che tenta di accedere a una pagina appartenente a un'altra applicazione viene bloccata dal kernel e punita severamente ("segmentation fault", "general protection fault"...).

Quando un'applicazione non ha più bisogno di una pagina (in particolare quando l'applicazione esce), il kernel prende il controllo della pagina e può cederla a un altro processo. I sistemi operativi moderni "svuotano" le pagine prima di restituirle, dove "svuotare" significa "riempire di zeri". In questo modo si evita la fuga di dati da un processo all'altro. Si noti che Windows 95/98/Millenium faceva non pagine bianche e potevano verificarsi perdite... ma questi sistemi operativi erano pensati per un singolo utente per macchina.

Naturalmente, ci sono modi per sfuggire all'ira del kernel: alcune porte sono disponibili per le applicazioni che hanno "privilegi sufficienti" (non lo stesso tipo di privilegi di cui sopra). Su un sistema Linux, questo è ptrace(). Il kernel consente a un processo di leggere e scrivere la memoria dell'altro, tramite ptrace(), a condizione che entrambi i processi siano eseguiti con lo stesso ID utente o che il processo che esegue ptrace() sia un processo "root". Una funzionalità simile esiste in Windows.

Il punto fondamentale è che le password nella RAM non sono più sicure di quelle consentite dal sistema operativo. Per definizione, memorizzando alcuni dati riservati nella memoria di un processo, ci si affida al sistema operativo per non cederli a terzi. Il sistema operativo è il vostro amico perché se il sistema operativo è un nemico, allora avete perso del tutto.


Ora viene la parte divertente. Poiché il sistema operativo impone la separazione dei processi, molte persone hanno cercato di trovare il modo di superare queste difese. E hanno trovato alcune cose interessanti...

  • La "RAM" che le applicazioni vedono non è necessariamente vera "memoria". Il kernel è un maestro delle illusioni e fornisce pagine che non esistono necessariamente. L'illusione viene mantenuta scambiando il contenuto della RAM con uno spazio dedicato sul disco, dove lo spazio libero è presente in quantità maggiore; questo è chiamato memoria virtuale. Le applicazioni non devono esserne consapevoli, perché il kernel riporterà le pagine quando necessario (ma, ovviamente, il disco è molto più lento della RAM). Una conseguenza spiacevole è che alcuni dati, presumibilmente conservati in RAM, arrivano su un supporto fisico dove rimarranno fino a quando non verranno sovrascritti. In particolare, rimarranno lì se viene tolta la corrente. Ciò consente attacchi in cui il malintenzionato afferra la macchina e scappa con essa, per ispezionare i dati in un secondo momento. Oppure le perdite possono verificarsi quando una macchina viene dismessa e venduta su eBay, e il sysadmin ha dimenticato di cancellare il contenuto del disco.

    Linux offre un sistema chiamato mlock() che impedisce al kernel di inviare alcune pagine specifiche allo spazio di swap. Poiché il blocco delle pagine nella RAM può esaurire le risorse disponibili per altri processi, è necessario disporre di alcuni privilegi (di nuovo root) per utilizzare questa funzione.

    Una circostanza aggravante è che non è necessariamente facile tenere traccia della posizione della password nella RAM. Come programmatore, si accede alla RAM attraverso l'astrazione fornita dal linguaggio di programmazione. In particolare, i linguaggi di programmazione che utilizzano la Garbage Collection possono copiare in modo trasparente gli oggetti nella RAM (perché è molto utile per molti algoritmi di GC). La maggior parte dei linguaggi di programmazione è quindi interessata (ad esempio Java, C#/.NET, Javascript, PHP, ... l'elenco è quasi infinito).

  • L'ibernazione ripropone gli stessi problemi, ma con una certa frequenza. Per sua natura, l'ibernazione deve scrivere l'intera RAM sul disco, comprese le pagine che sono state bloccate e persino il contenuto dei registri della CPU. Per evitare perdite attraverso l'ibernazione, si deve ricorrere a misure drastiche come la crittografia dell'intero disco, che naturalmente implica la digitazione della password di sblocco ogni volta che si risveglia la macchina.

  • Il modello di mainframe presuppone che possa eseguire diversi processi ostili l'uno all'altro, pur mantenendo una pace e un isolamento perfetti. L'hardware moderno rende questo molto difficile. Quando due processi vengono eseguiti sulla stessa CPU, condividono alcune risorse, tra cui la memoria cache; gli accessi alla memoria sono molto più veloci nella cache che altrove, ma la dimensione della cache è molto limitata. Questa caratteristica è stata sfruttata per recuperare le chiavi crittografiche utilizzate da un processo da un altro. Sono state sviluppate varianti che utilizzano altre risorse simili alla cache, ad esempio la predizione dei rami in una CPU. Mentre la ricerca su questo argomento si concentra sulle chiavi crittografiche, che sono segreti di alto valore, in realtà potrebbe applicarsi a qualsiasi dato.

    Su una nota simile, le schede video possono effettuare l'accesso diretto alla memoria. Se il DMA non può essere abusato per leggere o scrivere memoria da altri processi dipende da quanto l'hardware non documentato, i driver closed-source e i kernel collaborano per far rispettare i controlli di accesso appropriati. Non ci scommetterei la mia ultima camicia...


Conclusione: sì, quando si memorizza una password nella RAM, ci si affida al sistema operativo per mantenerla riservata. Sì, il compito è difficile, persino quasi impossibile sui sistemi moderni. Se alcuni dati sono altamente confidenziali, non si dovrebbe utilizzare il modello del mainframe e non permettere a entità potenzialmente ostili di eseguire il loro codice sulla vostra macchina.

(Il che, tra l'altro, significa che le macchine virtuali ospitate e il cloud computing non possono essere in definitiva sicuri. Se siete seriamente interessati alla sicurezza, usate hardware dedicato).

Penso che il sistema operativo faccia il suo lavoro ed eviti che i processi accedano alla memoria allocata da altri. Ma credo che questo sia in qualche modo fattibile.

Sì, è possibile accedere alla memoria di un altro processo. In Windows, ciò equivale ad avere SE_DEBUG_PRIVILEGE e utilizzare ReadProcessMemory() per estrarre le informazioni desiderate.

È possibile fare la stessa cosa da un driver di Windows, anche se è un po' più difficile da ottenere a causa di alcune complicazioni con la memoria attualmente impaginata nella metà inferiore.

In entrambi i casi, è necessario avere accesso a un account amministrativo, o a un processo assegnato in modo errato SE_DEBUG_PRIVILEGEo un processo con questo privilegio che possa essere convinto a fare ciò che serve.

Si tratta quindi di assicurarsi che nessuno possa scalare per ottenere questi privilegi. Più realisticamente, ci assicuriamo che solo gli utenti fidati possano avere questi privilegi. Se si ha accesso a un account amministrativo, si può facilmente leggere una password direttamente dalla memoria dei processi di un altro account.

In linux, si può ottenere la stessa cosa con ptrace() e il PTRACE_PEEK_DATA .

Ci si potrebbe chiedere perché queste funzioni esistono? In realtà, sono incredibilmente utili per il debug dei processi. È plausibile che un utente amministratore voglia fare questo. Al contrario, gli utenti normali non dovrebbero averne bisogno e dovrebbero essere isolati gli uni dagli altri.

Questo è il motivo per cui da tempo si consiglia di non eseguire tutto con l'account di amministratore.

Lavoro nel settore dell'elettronica di consumo e la sicurezza è un po' diversa rispetto all'ambiente server. Qui dobbiamo presumere che il prodotto si trovi in un ambiente ostile. Per questo motivo, ai fini della gestione degli abbonati, le chiavi vengono tenute al sicuro. La prima linea di difesa è che il SoC ha registri nascosti a cui nemmeno il sistema operativo può accedere, che sono stati masterizzati al momento della produzione e i fusibili del chip sono saltati per impedire l'accesso. Inoltre, non possiamo vedere le chiavi perché sarebbe insicuro per la produzione, ma sono preconfezionate con una chiave batch che non conosciamo, ma che solo il fornitore del chip e la persona che ha creato la chiave conoscono (la chiave master può essere distrutta dopo l'uso nel chip). Una volta che il chip è stato caricato con i segreti, può essere bloccato e mai* sbloccato.

Se non si può accedere alle chiavi, come si fa a decifrare qualcosa? Con un co-processore crittografico sul SoC è possibile caricare le posizioni delle chiavi senza conoscere effettivamente il valore all'interno. Inoltre non si vede mai il microcodice del cripto-processore, perché anche al momento della produzione non si può iniettare nulla.

Se si dispone di chiavi o certificati che non possono essere inseriti nei generosi registri del chip, è necessario memorizzarli nella RAM e/o nella NVM, ma grazie al cripto-processore non è necessario esporre tali valori. La RAM o la NVM stessa possono essere criptate dal chip con una chiave che non è nota a nessuno se non a se stesso.

Infine, a differenza dei computer, i sistemi embedded sicuri hanno anche una certa sicurezza fisica. Le tracce di connessione della RAM non possono trovarsi sulla superficie del circuito stampato ("buried vias"). Questo perché se ci sono elementi che sono in chiaro nella RAM è necessario limitarne l'accesso, è possibile rallentare o bloccare la CPU e quindi sondare la RAM.

Infine, per le smart card è stato possibile intercettare le transazioni tra il SoC e la carta. La soluzione consiste nel criptare le transazioni tra la carta e il SoC e nel legarle l'una all'altra in modo che non possano essere scambiate o condivise.

So che la sicurezza dei DRM/contenuti è impopolare con alcune persone su internet, ma ho pensato di condividere alcuni concetti di alto livello da un settore che ha particolari requisiti di sicurezza.

*In teoria.

Ti mostriamo recensioni e punteggi

Apprezziamo che desideri aggiungere valore al nostro contenuto informativo assistendo con la tua esperienza nelle cronache.



Utilizzate il nostro motore di ricerca

Ricerca
Generic filters

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.