Come dovrebbe un'applicazione memorizzare le proprie credenziali

27

Contesto

Quando sviluppi applicazioni desktop, dovrai occasionalmente memorizzare le credenziali da qualche parte per poter autenticare la tua applicazione. Un esempio di questo è un ID app Facebook + segreto , un altro è credenziali MySQL.

L'archiviazione di questi testi in chiaro nel codice sorgente delle applicazioni non fornisce alcuna protezione reale dal momento che non è un problema per decodifica un programma . Raccogliere le credenziali da un server non farà il trucco, dal momento che gli hacker possono facilmente eseguire le richieste da soli. Nemmeno la crittografia delle credenziali memorizzate può fare alcuna differenza in quanto l'applicazione avrà bisogno di accedere alla chiave di decodifica per poter utilizzare le credenziali.

Domanda

In che modo è possibile memorizzare credenziali specifiche per le applicazioni? Preferibilmente cross-OS.

Nota: Il linguaggio pertinente è Java, tuttavia, credo (penso) che questa è una domanda non specifica della lingua.

    
posta Zar 17.09.2012 - 19:50
fonte

2 risposte

23

Non inserire mai password o chiavi crittografiche nel programma.

La regola generale è: le uniche credenziali che dovresti memorizzare sul computer di un utente sono le credenziali associate a quell'utente , ad esempio le credenziali che consentono a quell'utente di accedere al suo account.

Non dovresti memorizzare le tue credenziali dello sviluppatore sulla macchina dell'utente . Non è sicuro.

Devi presumere che qualsiasi cosa memorizzata sulla macchina dell'utente sia nota all'utente, o che possa essere facilmente appresa dall'utente. (Questa è l'ipotesi giusta: non è difficile decodificare un file binario dell'applicazione per apprendere eventuali chiavi o segreti che possono essere incorporati in esso.)

Una volta compreso questo principio generale, tutto diventa facile. In sostanza, è necessario progettare il resto del sistema e il protocollo di autenticazione in modo che il software client possa autenticarsi utilizzando solo quelle credenziali che sono sicure da memorizzare sul client.

Esempio 1. Supponiamo di avere un ID di app e una chiave Facebook, associati alla tua app (cioè, associati al tuo account sviluppatore). Incorporate l'ID app e la chiave nel software desktop che spedite agli utenti? No! Assolutamente no. Sicuramente non lo fai, perché ciò consentirebbe a qualsiasi dei tuoi utenti di apprendere l'ID e la chiave dell'app e di inviare le proprie richieste, danneggiando potenzialmente la tua reputazione.

Invece, trovi un altro modo. Ad esempio, potresti configurare il tuo server che ha l'ID e la chiave dell'app ed è responsabile di effettuare le richieste alla piattaforma Facebook (soggetto a limitazioni e limiti tariffari appropriati). Quindi, il tuo client si connette al tuo server. Forse tu autentichi ogni cliente avendo ogni utente impostato il proprio account utente sul proprio server, memorizzando le credenziali dell'account sul client e facendo in modo che il client si autentichi utilizzando queste credenziali.

Puoi renderlo totalmente invisibile all'utente, facendo in modo che l'app client generi un nuovo account utente alla prima esecuzione (generando le proprie credenziali di accesso, archiviandole localmente e inviandole al server). L'app client può utilizzare queste credenziali memorizzate per connettersi in futuro (ad esempio su SSL) e accedere automaticamente ogni volta che viene eseguita l'applicazione.

Nota come l'unica cosa memorizzata sul computer di un utente sono le credenziali che consentono di accedere all'account dell'utente, ma nulla che possa consentire l'accesso agli account di altre persone e nulla che possa esporre le chiavi dell'app sviluppatore.

Esempio 2. Supponiamo che tu scriva un'app che deve accedere ai dati dell'utente nel loro account Google. Gli chiedi il nome utente e la password di Google e li memorizzano nella memoria locale dell'app? Potresti: sarebbe OK, perché le credenziali dell'utente sono memorizzate sul computer dell'utente. L'utente non ha alcun incentivo a provare a hackerare la propria macchina, perché già conosce le proprie credenziali.

Ancora meglio: usa OAuth per autorizzare la tua app. In questo modo la tua app memorizza un token OAuth nella sua memoria locale dell'app, che consente alla tua app di accedere all'account Google dell'utente. Evita anche la necessità di memorizzare la password Google dell'utente (che è particolarmente sensibile) nella memoria locale dell'app, quindi riduce il rischio di compromissione.

Esempio 3. Supponiamo che tu stia scrivendo un'app con un backend del database MySQL condiviso da tutti gli utenti. Prendi il database MySQL e lo incorpori nel binario dell'app? No! Qualcuno dei tuoi utenti potrebbe estrarre la password e ottenere l'accesso diretto al tuo database MySQL.

Invece, si imposta un servizio che fornisce le funzionalità necessarie. L'app client si connette al servizio, si autentica da sé e invia la richiesta al servizio. Il servizio può quindi eseguire questa richiesta sul database MySQL. La password MySQL rimane memorizzata in modo sicuro sulla macchina del server e non è mai accessibile sulla macchina di un utente. Il server può imporre qualsiasi restrizione o controllo di accesso che desideri.

Ciò richiede che l'app client sia in grado di autenticare il servizio. Un modo per farlo è quello di fare in modo che l'app client crei un nuovo account sul servizio al primo avvio, generi una credenziale di autenticazione casuale e acceda automaticamente al servizio ogni volta successiva. Potresti usare SSL con una password casuale, o ancora meglio, usare qualcosa come SSL con un certificato client univoco per ogni cliente.

L'altra regola è: non si inseriscono le credenziali nel programma. Se stai memorizzando le credenziali sul computer dell'utente, memorizzale in qualche luogo privato: forse un file di configurazione o in una directory, preferibilmente uno che sia leggibile solo da questa particolare app o da questo particolare utente (non un file leggibile da tutto il mondo).

    
risposta data 18.09.2012 - 07:10
fonte
4

È un classico problema di sicurezza senza soluzioni perfette, solo imperfette, e si riduce al problema più generale di proteggere il software da manomissioni e reverse engineering.

  1. Utilizzare un metodo di autenticazione esterno che l'utente deve fornire attivamente per raggiungere le credenziali: una password immessa manualmente (il cui hash digest, ad esempio, viene utilizzato per decrittografare le credenziali), una chiave di autenticazione sicura contenente un certificato e corrispondente chiave privata che deve essere inserita in una porta USB, un lettore di impronte digitali che fornisce l'impronta digitale corretta ecc. Idealmente, il risultato di questa operazione non sarà una semplice risposta sì / no al programma, in quanto può essere sovrascritto / applicato / modificato ma un valore reale (una chiave crittografica) richiesto per decrittografare le credenziali (o qualsiasi altra cosa si stia tentando di proteggere), derivata direttamente dall'autenticatore. Un approccio multi-sorgente in cui la chiave di decodifica è calcolata al volo da varie fonti (su quali fonti, questo dipende davvero dal tuo sistema) potrebbe essere ancora migliore.

  2. Molto pesantemente (automaticamente e in modo massiccio) offusca il tuo programma per ostacolare il reverse engineering. Abbastanza vero, gli strumenti di analisi statici sono diventati all'avanguardia, ma ci sono strumenti di offuscamento [proprietari, costosi] là fuori (compilatori, pacchetti, ecc. Offuscanti) che rendono il reverse engineering molto dispendioso in termini di tempo, impegnativo e laborioso, abbastanza da mandare gli attaccanti a cercare obiettivi più facili. L'aggiunta di meccanismi di protezione contro i metodi di debugging e resistenza alla manomissione può rafforzare ulteriormente la sicurezza del tuo programma. Abbastanza vero, Java come linguaggio bytecode è particolarmente vulnerabile in questo senso, poiché decompilarlo (rispetto al decompilare / disassemblare il codice nativo) è piuttosto semplice.

risposta data 17.09.2012 - 20:28
fonte

Leggi altre domande sui tag