L'archiviazione locale può mai essere considerata sicura? [chiuso]


161

Sono tenuto a sviluppare un'applicazione Web che funzionerà offline per lunghi periodi. Affinché ciò sia fattibile, non posso evitare di salvare i dati sensibili (dati personali ma non il tipo di dati che memorizzeresti solo l'hash) nella memoria locale.

Accetto che questa non sia una pratica consigliata, ma data la poca scelta, sto facendo quanto segue per proteggere i dati:

  • crittografando tutto ciò che va nella memoria locale usando la libreria crittografica javascript di Stanford e AES-256
  • la password dell'utente è la chiave di crittografia e non è memorizzata sul dispositivo
  • servire tutto il contenuto (quando online) da un singolo server fidato su ssl
  • convalida di tutti i dati da e verso l'archiviazione locale sul server utilizzando il progetto antisamy owasp
  • nella sezione di rete dell'appcache, non usando *, e invece elencando solo gli URI richiesti per la connessione con il server fidato
  • in generale, cercando di applicare le linee guida suggerite nel cheat sheet di OWASP XSS

Apprezzo il fatto che il diavolo sia spesso nei dettagli e so che c'è molto scetticismo sull'archiviazione locale e sulla sicurezza basata su javascript in generale. Qualcuno può commentare se ci sono:

  • difetti fondamentali nell'approccio sopra?
  • eventuali soluzioni per tali difetti?
  • un modo migliore per proteggere l'archiviazione locale quando un'applicazione HTML 5 deve funzionare offline per lunghi periodi?

Grazie per qualsiasi aiuto.


"Accetto che questa non sia una pratica raccomandata" - È così? Non è il contrario che è stato creato proprio per quello?
hakre,

2
Per chiarire, intendevo non raccomandare la pratica di archiviare dati sensibili nella memoria locale.
user1173706

Come se non dovessi trasmettere dati sensibili su reti di grandi dimensioni?
Hakre,

@ user1173706 Perché l'applicazione deve funzionare deve funzionare per lunghi periodi offline? Come sono gli utenti? Quali browser devi supportare? Penso che sia possibile, ma ho bisogno di conoscere i dettagli del tuo scenario.
Benjamin Gruenbaum,

@Benjamin ho aggiornato la domanda. Grazie.
user1173706

Risposte:


74

WebCrypto

I problemi con la crittografia nel javascript lato client (browser) sono dettagliati di seguito. Tutte queste preoccupazioni, tranne una, non si applicano all'API WebCrypto , che ora è ragionevolmente ben supportata .

Per un'app offline, è comunque necessario progettare e implementare un keystore sicuro.

A parte: se si utilizza Node.js, utilizzare l' API crittografica integrata.

Crittografia nativa-Javascript (pre-WebCrypto)

Presumo che la preoccupazione principale sia che qualcuno abbia accesso fisico al computer che sta leggendo localStorageper il tuo sito e desideri che la crittografia aiuti a impedire tale accesso.

Se qualcuno ha accesso fisico sei anche aperto ad attacchi diversi e peggiori della lettura. Questi includono (ma non sono limitati a): keylogger, modifica di script offline, iniezione di script locale, avvelenamento da cache del browser e reindirizzamenti DNS. Tali attacchi funzionano solo se l'utente utilizza la macchina dopo che è stata compromessa. Tuttavia, l'accesso fisico in tale scenario significa che hai problemi più grandi.

Quindi tieni presente che lo scenario limitato in cui la crittografia locale è preziosa sarebbe se la macchina viene rubata.

Esistono librerie che implementano la funzionalità desiderata, ad esempio Stanford Javascript Crypto Library . Ci sono debolezze intrinseche, tuttavia (come indicato nel collegamento dalla risposta di @ ircmaxell):

  1. Mancanza di entropia / generazione di numeri casuali;
  2. La mancanza di un keystore sicuro, ovvero la chiave privata deve essere protetta da password se memorizzata localmente o memorizzata sul server (che impedisce l'accesso offline);
  3. Mancanza di cancellazione sicura;
  4. Mancanza di caratteristiche di temporizzazione.

Ognuna di queste debolezze corrisponde a una categoria di compromesso crittografico. In altre parole, mentre potresti avere "cripto" per nome, sarà molto al di sotto del rigore a cui aspiri nella pratica.

Detto questo, la valutazione attuariale non è così banale come "La crittografia Javascript è debole, non usarla". Questa non è un'approvazione, rigorosamente un avvertimento e richiede di comprendere completamente l'esposizione dei punti deboli di cui sopra, la frequenza e il costo dei vettori che affronti e la tua capacità di mitigazione o assicurazione in caso di fallimento: Javascript crypto, in nonostante i suoi punti deboli, può ridurre la tua esposizione ma solo contro i ladri con capacità tecnica limitata. Tuttavia, dovresti presumere che la crittografia Javascript non abbia alcun valore nei confronti di un aggressore determinato e capace che prende di mira tali informazioni. Alcuni considererebbero fuorviante chiamare i dati "crittografati" quando sono noti così tanti punti deboli inerenti all'implementazione. In altre parole, puoi ridurre marginalmente la tua esposizione tecnica ma aumenti la tua esposizione finanziaria dalla divulgazione. Naturalmente, ogni situazione è diversa e l'analisi della riduzione dell'esposizione tecnica all'esposizione finanziaria non è banale. Ecco un'analogia illustrativa:Alcune banche richiedono password deboli , nonostante il rischio intrinseco, poiché la loro esposizione a perdite dovute a password deboli è inferiore ai costi dell'utente finale per il supporto di password complesse.

🔥 Se leggi l'ultimo paragrafo e pensi "Qualcuno su Internet di nome Brian dice che posso usare Javascript crittografato", non usare Javascript crittografico.

Per il caso d'uso descritto nella domanda sembrerebbe più sensato per gli utenti crittografare la propria partizione locale o directory home e utilizzare una password complessa. Questo tipo di sicurezza è generalmente ben collaudato, ampiamente affidabile e comunemente disponibile.


C'è ulteriore documentazione (citazioni) disponibile per la posizione generale di "non utilizzare la crittografia JavaScript" fornita dal gruppo NCC dal 2011: crittografia JavaScript considerata dannosa (in particolare a causa della cattura-22 del download dello strumento per verificare i download ... qualità PRNG ... ecc.)
amcgregor,

58

Bene, la premessa di base qui è: no, non è ancora sicuro.

Fondamentalmente, non puoi eseguire crypto in JavaScript: JavaScript Crypto considerato dannoso .

Il problema è che non è possibile ottenere in modo affidabile il codice crittografico nel browser e, anche se fosse possibile, JS non è progettato per consentirti di eseguirlo in modo sicuro. Quindi fino a quando i browser non disporranno di un contenitore crittografico (fornito da Encrypted Media Extensions, ma non saranno sottoposti a rally per i loro scopi DRM), non sarà possibile farlo in modo sicuro.

Per quanto riguarda un "Modo migliore", non ce n'è uno in questo momento. L'unica alternativa è archiviare i dati in testo semplice e sperare per il meglio. O non conservare affatto le informazioni. In entrambi i casi.

O quello, o se hai bisogno di quel tipo di sicurezza e hai bisogno di spazio di archiviazione locale, crea un'applicazione personalizzata ...


8
Downvoter: puoi fornire una risposta migliore? Mi rendo conto che si tratta di una questione piuttosto controversa in cui vi è un notevole disaccordo tra i professionisti della sicurezza (e anche i non professionisti), quindi vale la pena condividere il punto di vista alternativo. A meno che non effettui il downvoting per un altro motivo, nel qual caso come posso migliorare questa risposta?
ircmaxell,

9
@ircmaxell non sono io, ma non sono d'accordo con questa risposta. "Il problema è che non è possibile ottenere in modo affidabile il codice crittografico nel browser e, anche se fosse possibile, JS non è progettato per consentirti di eseguirlo in modo sicuro." - Perché? Qual è il problema intrinseco ? È possibile utilizzare la libreria di crittografia JavaScript di Stanford e crittografare / decrittografare al suo interno. Puoi fare hash e puoi fare tutto in sicurezza. Non vedo il problema inerente qui in un'app offline in JS che fa crpyto standard, proprio come farebbe un'app costruita in qualsiasi altra lingua.
Benjamin Gruenbaum,

11
@BenjaminGruenbaum: il problema è che ci sono più posti in cui quel codice crittografico dovrebbe interagire con codice di terze parti. L'intero punto di questo articolo a cui ho collegato è che non puoi controllare l'ambiente di esecuzione. Quindi installi la libreria Stanford Crypto. Quindi cosa succede se alcuni plug-in del browser sostituiscono sjcl.encryptper inviare via e-mail la chiave all'attaccante? In JS questo è possibile al 100% e non c'è niente che tu possa fare per fermarlo. E questo è il punto fondamentale. Non esistono meccanismi di "sicurezza" per impedire ad altri JS di eseguire operazioni dannose sui dati. E questo è un problema .
Ircmaxell,

13
@ircmaxell Se dormi con i cani non puoi aspettarti di non svegliarti con le pulci. Se l'utente installa un componente aggiuntivo malware che è lo stesso dell'utente che installa un virus sul proprio PC, non è diverso da esso. Il tuo programma Java o C può essere il più sicuro possibile, ma non appena l'attaccante ha la capacità di eseguire il codice sei fregato. Non è diverso per JS. I componenti aggiuntivi non appaiono solo magicamente nel browser. Inoltre, non salvare le informazioni crittografate non aiuterebbe in alcun modo se l'utente ha malware, poiché potrebbe semplicemente dirottare i dati in tempo reale.
Benjamin Gruenbaum,

9
@BenjaminGruenbaum: non sono d'accordo. In una normale applicazione, avresti bisogno di compromettere l'applicazione stessa (per leggere locazioni di memoria), o l'accesso di root guadagno al box (compromettere il sistema operativo). Ad ogni modo, devi compromettere qualcosa di più profondo del semplice comportamento normale. JS lo consente nel comportamento normale. Qual è il problema ...
Ircmaxell,

12

Come esplorazione di questo argomento, ho una presentazione intitolata "Protezione di TodoMVC mediante l'API di crittografia Web" ( video , codice ).

Utilizza l' API di crittografia Web per memorizzare l'elenco di todo crittografato in localStorage mediante la protezione dell'applicazione tramite password e l'utilizzo di una chiave derivata da password per la crittografia. Se si dimentica o si perde la password, non c'è recupero. ( Dichiarazione di non responsabilità - era un POC e non destinato all'uso in produzione. )

Come affermano le altre risposte, questo è ancora suscettibile all'XSS o al malware installato sul computer client. Tuttavia, tutti i dati sensibili rimarrebbero anche in memoria quando i dati sono archiviati sul server e l'applicazione è in uso. Suggerisco che il supporto offline potrebbe essere il caso d'uso convincente.

Alla fine, la crittografia localStorage probabilmente protegge solo i dati dagli aggressori che hanno accesso in sola lettura al sistema o ai suoi backup. Aggiunge una piccola quantità di difesa in profondità per l' esposizione ai dati A6 sensibili ai primi 10 articoli di OWASP e consente di rispondere "Uno di questi dati è archiviato in chiaro a lungo termine?" correttamente.


3

Questo è un articolo davvero interessante qui. Sto prendendo in considerazione l'implementazione della crittografia JS per offrire sicurezza quando si utilizza l'archiviazione locale. È assolutamente chiaro che questo offrirà protezione solo se il dispositivo viene rubato (e implementato correttamente). Non offrirà protezione contro keylogger ecc. Tuttavia, questo non è un problema di JS in quanto la minaccia keylogger è un problema di tutte le applicazioni, indipendentemente dalla loro piattaforma di esecuzione (browser, nativo). Per quanto riguarda l'articolo "JavaScript Crypto considerato dannoso" a cui fa riferimento la prima risposta, ho una critica; afferma "È possibile utilizzare SSL / TLS per risolvere questo problema, ma è costoso e complicato". Penso che questa sia un'affermazione molto ambiziosa (e forse piuttosto distorta). Sì, SSL ha un costo,

La mia conclusione: esiste un posto per il codice di crittografia sul lato client, tuttavia, come per tutte le applicazioni, gli sviluppatori devono riconoscere i suoi limiti e implementarli se adatti alle loro esigenze e garantire che ci siano modi per mitigare i rischi.


Storicamente ci sono stati costi straordinari (meccanici, non finanziari) associati alla negoziazione iniziale della connessione. Al punto che le aziende utilizzerebbero dispositivi di terminazione SSL dedicati, che potrebbero diventare finanziariamente costosi al di là dell'emissione dei certificati e dei costi di garanzia. Oggi molti di questi problemi sono stati risolti, come la persistenza della sessione di lunga durata per evitare la stretta di mano iniziale sulle richieste successive.
amcgregor,

2

Non accessibile a nessuna pagina Web (true) ma è facilmente accessibile e facilmente modificabile tramite gli strumenti di sviluppo, come chrome (ctl-shift-J). Pertanto, è richiesta una crittografia personalizzata prima di archiviare il valore.

Ma, se javascript deve decrittografare (per convalidare), l'algoritmo di decrittografia è esposto e può essere manipolato.

Javascript ha bisogno di un contenitore completamente sicuro e della capacità di implementare correttamente variabili e funzioni private disponibili solo per l'interprete js. Tuttavia, ciò viola la sicurezza dell'utente, poiché i dati di tracciamento possono essere utilizzati impunemente.

Di conseguenza, JavaScript non sarà mai completamente sicuro.


-29

No.

localStorage è accessibile da qualsiasi pagina Web e, se si dispone della chiave, è possibile modificare qualsiasi dato desiderato.

Detto questo, se riesci a escogitare un modo per crittografare in modo sicuro le chiavi, non importa come trasferisci i dati, se puoi contenere i dati all'interno di una chiusura, i dati sono (in qualche modo) sicuri.


19
Non è possibile accedere a "qualsiasi pagina Web". È accessibile solo alle pagine nel dominio corrente.
dtabuenc,

@dtabuenc al contrario, ho creato una penna un po 'di tempo fa che ti mostra ogni singola coppia chiave / valore nel tuo archivio locale , senza alcun trucco .
hellol11,

3
No! Scusate. La memoria locale è isolata per dominio. Il codice in esecuzione in un dominio non può accedere ai valori archiviati nella memoria locale da un altro dominio. Ad esempio, google.com memorizza un sacco di cose nella memoria locale. Non sarai in grado di elencare nessuna delle chiavi di google.com nel tuo esempio di penna.
dtabuenc,

@dtabuenc l'ha provato, hai ragione.
hellol11,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.