Domanda Perché char [] è preferito a String per le password?


In Swing, il campo della password ha a getPassword() (ritorna char[]) metodo invece del solito getText() (ritorna String) metodo. Allo stesso modo, ho trovato un suggerimento da non usare String gestire le password.

Perché lo fa String porre una minaccia alla sicurezza quando si tratta di password? È scomodo da usare char[].


2893
2018-01-16 14:20


origine


risposte:


Le stringhe sono immutabili. Ciò significa che una volta creato il String, se un altro processo può scaricare la memoria, non c'è modo (a parte riflessione) puoi sbarazzarti dei dati prima raccolta dei rifiuti butta dentro.

Con un array, puoi cancellare i dati in modo esplicito dopo aver finito. Puoi sovrascrivere l'array con qualsiasi cosa tu voglia e la password non sarà presente in nessun punto del sistema, anche prima della garbage collection.

Quindi sì, questo è un problema di sicurezza, ma anche l'utilizzo char[] riduce solo la finestra di opportunità per un aggressore, ed è solo per questo specifico tipo di attacco.

Come notato nei commenti, è possibile che gli array che vengono spostati dal garbage collector lascino in memoria le copie vaganti dei dati. Credo che questo sia specifico dell'implementazione, il garbage collector potrebbe cancella tutta la memoria mentre va, per evitare questo genere di cose. Anche se lo fa, c'è ancora il tempo durante il quale il char[] contiene i personaggi reali come una finestra di attacco.


3714
2018-01-16 14:26



Mentre altri suggerimenti qui sembrano validi, c'è un altro buon motivo. Con semplice String hai molte più possibilità di stampare accidentalmente la password per i registri, monitor o qualche altro posto insicuro. char[] è meno vulnerabile.

Considera questo:

public static void main(String[] args) {
    Object pw = "Password";
    System.out.println("String: " + pw);

    pw = "Password".toCharArray();
    System.out.println("Array: " + pw);
}

stampe:

String: Password
Array: [C@5829428e

1078
2018-01-16 19:37



Per citare un documento ufficiale, il Guida all'architettura di crittografia Java dice questo char[] vs. String password (sulla crittografia basata su password, ma questo è più in generale sulle password, ovviamente):

Sembrerebbe logico raccogliere e memorizzare la password in un oggetto   di tipo java.lang.String. Tuttavia, ecco l'avvertenza: Objects di   genere String sono immutabili, cioè non ci sono metodi che lo definiscono   consente di modificare (sovrascrivere) o azzerare il contenuto di a String   dopo l'uso. Questa caratteristica rende String oggetti inadatti per   memorizzazione di informazioni sensibili alla sicurezza come password utente. tu   dovrebbe sempre raccogliere e archiviare informazioni sensibili per la sicurezza in a    char matrice invece.

Linea guida 2-2 delle Linee guida per la codifica sicura per Java Programming Language, Versione 4.0 dice anche qualcosa di simile (sebbene sia originariamente nel contesto della registrazione):

Linea guida 2-2: non registrare informazioni altamente sensibili

Alcune informazioni, come numeri di previdenza sociale (SSN) e   password, è altamente sensibile. Questa informazione non dovrebbe essere mantenuta   più a lungo del necessario, né dove possa essere visto, anche da   amministratori. Ad esempio, non dovrebbe essere inviato a file di registro e   la sua presenza non dovrebbe essere rilevabile attraverso le ricerche. Alcuni transitori   i dati possono essere conservati in strutture dati mutabili, come array di caratteri e   eliminato immediatamente dopo l'uso. La cancellazione delle strutture dati è stata ridotta   efficacia sui tipici sistemi di runtime Java man mano che gli oggetti vengono spostati   memoria in modo trasparente al programmatore.

Questa linea guida ha anche implicazioni per l'implementazione e l'uso di   librerie di livello inferiore che non hanno conoscenza semantica dei dati   loro stanno trattando. Ad esempio, un parsing di stringhe di basso livello   la biblioteca può registrare il testo su cui lavora. Un'applicazione può analizzare un SSN   con la biblioteca. Ciò crea una situazione in cui sono gli SSN   disponibile per gli amministratori con accesso ai file di registro.


610
2018-01-17 03:20



Array di caratteri (char[]) può essere cancellato dopo l'uso impostando ogni carattere su zero e Stringhe no. Se qualcuno può in qualche modo vedere l'immagine di memoria, può vedere una password in testo normale se vengono usate le stringhe, ma se char[] viene utilizzato, dopo aver eliminato i dati con 0, la password è sicura.


305
2018-01-16 14:27



Alcune persone credono che sia necessario sovrascrivere la memoria utilizzata per memorizzare la password quando non è più necessaria. Ciò riduce la finestra temporale in cui un utente malintenzionato deve leggere la password dal proprio sistema e ignora completamente il fatto che l'utente malintenzionato ha già bisogno di accesso sufficiente per dirottare la memoria JVM per farlo. Un aggressore con un tale accesso può catturare i tuoi eventi chiave rendendolo completamente inutile (AFAIK, quindi correggimi se sbaglio).

Aggiornare

Grazie ai commenti devo aggiornare la mia risposta. Apparentemente ci sono due casi in cui questo può aggiungere un (molto) minore miglioramento della sicurezza in quanto riduce il tempo che una password potrebbe atterrare sul disco rigido. Comunque penso che sia eccessivo per la maggior parte dei casi d'uso.

  • Il tuo sistema di destinazione potrebbe essere configurato male o devi supporre che sia e devi essere paranoico sui core dump (può essere valido se i sistemi non sono gestiti da un amministratore).
  • Il tuo software deve essere eccessivamente paranoico per prevenire perdite di dati con l'hacker che ha accesso all'hardware - usando cose come TrueCrypt (Fuori produzione), veracrypt, o CipherShed.

Se possibile, disabilitare i core dump e il file di swap si prenderà cura di entrambi i problemi. Tuttavia, richiederebbero i diritti di amministratore e potrebbero ridurre la funzionalità (meno memoria da utilizzare) e la rimozione della RAM da un sistema in esecuzione rappresenterebbe ancora un problema valido.


183
2018-01-16 14:32



  1. Le stringhe sono immutabili in Java se si memorizza la password come testo normale sarà disponibile in memoria finché Garbage Collector non lo cancella e dal momento che le stringhe vengono utilizzate nel pool di stringhe per la riutilizzabilità ci sono possibilità piuttosto elevate che rimanga in memoria per una lunga durata, pone una minaccia alla sicurezza. Dal momento che chiunque abbia accesso al dump della memoria può trovare la password in chiaro
  2. Raccomandazione Java utilizzando getPassword() metodo di JPasswordField che restituisce un carattere [] e deprecato getText() metodo che restituisce la password in chiaro, indicando il motivo di sicurezza.
  3. accordare() c'è sempre il rischio di stampare testo normale nel file di registro o nella console, ma se si utilizza Array non si stamperà il contenuto dell'array, ma si stamperà la sua posizione di memoria.

    String strPwd = "passwd";
    char[] charPwd = new char[]{'p','a','s','s','w','d'};
    System.out.println("String password: " + strPwd );
    System.out.println("Character password: " + charPwd );
    

    Parola d'ordine stringa: passwd

    Password caratteri: [C @ 110b2345

Pensieri finali: Anche se l'uso di char [] non è sufficiente, è necessario cancellare il contenuto per renderlo più sicuro. Suggerisco anche di lavorare con hash o password cifrata invece di testo normale e di cancellarlo dalla memoria non appena l'autenticazione è completata.


117
2017-12-27 20:22



Non penso che questo sia un suggerimento valido, ma, posso almeno indovinare il motivo.

Penso che la motivazione sia quella di voler essere sicuro di poter cancellare tutte le tracce della password in memoria prontamente e con certezza dopo l'uso. Con un char[] potresti sovrascrivere ogni elemento dell'array con uno spazio vuoto o qualcosa di sicuro. Non è possibile modificare il valore interno di a String quel modo.

Ma quella sola non è una buona risposta; perché non assicurarti solo un riferimento al char[] o String non sfugge? Quindi non c'è alcun problema di sicurezza. Ma la cosa è questa String gli oggetti possono essere intern()ed in teoria e mantenuto vivo all'interno della piscina costante. Suppongo di usare char[] vieta questa possibilità.


72
2018-01-16 14:27



La risposta è già stata data, ma mi piacerebbe condividere un problema che ho scoperto ultimamente con le librerie standard Java. Mentre si preoccupano ora di sostituire le stringhe di password con char[] ovunque (che ovviamente è una buona cosa), altri dati critici per la sicurezza sembrano essere trascurati quando si tratta di cancellarlo dalla memoria.

Sto pensando ad es. il PrivateKey classe. Considera uno scenario in cui devi caricare una chiave RSA privata da un file PKCS # 12, utilizzandola per eseguire alcune operazioni. Ora, in questo caso, il solo sniffing della password non sarebbe di grande aiuto fin tanto che l'accesso fisico al file chiave fosse opportunamente limitato. Come attaccante, sarebbe molto meglio se ottenessi direttamente la chiave invece della password. Le informazioni desiderate possono essere trapelate molteplici, core dump, una sessione di debugger o file di swap sono solo alcuni esempi.

E come risulta, non c'è nulla che ti permetta di cancellare le informazioni private di a PrivateKey dalla memoria, perché non ci sono API che consentono di cancellare i byte che formano le informazioni corrispondenti.

Questa è una brutta situazione, come questa carta descrive come questa circostanza potrebbe essere potenzialmente sfruttata.

La libreria OpenSSL, ad esempio, sovrascrive le sezioni di memoria critica prima che le chiavi private vengano liberate. Poiché Java è stato sottoposto a raccolta dei dati inutili, occorrerebbero metodi espliciti per cancellare e invalidare le informazioni private per le chiavi Java, che devono essere applicate immediatamente dopo l'uso della chiave.


58
2018-01-19 19:39