2013-02-22 6 views
13

Una linea guida di sicurezza Java comune per la gestione di dati riservati (== password) consiglia di non utilizzare mai un oggetto String per archiviare i dati e utilizzare invece una matrice di byte o caratteri. Sto cercando di applicare questa linea guida in un gestore HttpServlet. In particolare, sto usando un approccio simile all'autenticazione di base in cui le credenziali vengono passate in un'intestazione (questa è una richiesta GET, quindi nessun corpo).In Java, come si estrae una password da un'intestazione HttpServletRequest senza generare un oggetto String?

Il problema che sto incontrando è che sembra impossibile arrivare ai dati di intestazione senza generare un oggetto String, che viola le linee guida dall'inizio. Ho cercato una soluzione abbastanza a fondo e non ho trovato nessuna discussione pertinente. Qualcuno ha qualche approfondimento su questo problema?

NOTA: questo avviene su HTTPS, quindi non vi è alcun problema di sicurezza di connessione qui.

+0

Isnt tutto 1s e 0s .. Come è una stringa più di una minaccia alla sicurezza di un byte []? – smk

+1

@smk: Perché 'String's può essere internato, il che significa che rimangono nella memoria molto tempo dopo averli usati. –

+6

@smk Le stringhe sono immutabili. Una volta che ne hai uno, si blocca in memoria fino a quando non viene raccolto nella spazzatura (molto tempo dopo aver finito con esso). Con un 'byte []', una volta terminato, è possibile sovrascrivere il contenuto per impedire la lettura dei dati. – cheeken

risposta

12

La risposta semplice è che non è possibile ottenere il parametro in una forma diversa da String. Almeno, non usando le API standard del servlet. Ma ci sono un paio di possibili "uscite".

  1. Se siete preparati per ottenere veramente brutto, è possibile infatti rompere l'astrazione dell'oggetto String, e raggiungere in e sovrascrivere i caratteri. (Le stringhe sono effettivamente modificabili se si è pronti a violare le regole. Questa è una delle poche situazioni in cui ciò potrebbe essere giustificato)

  2. Potrebbe esserci un'estensione API non standard nell'implementazione del contenitore Web di (diciamo) HttpServletRequest per farlo. In caso contrario, potresti essere in grado di ottenere il codice sorgente e aggiungerne uno. (Supponendo che si sta utilizzando un web container open-source.)


Detto questo, IMO l'approccio "No Strings" per la sicurezza Java è sbagliata, o per lo meno sopravvalutato in termini di ciò che raggiunge.

L'approccio "senza stringhe" impedisce la possibilità che qualcosa possa attraversare lo spazio degli indirizzi dell'applicazione, individuare elementi simili a stringhe e individuare possibili password. In teoria, questo potrebbe essere fatto da:

  • un hack che rompe modello di esecuzione della JVM e guarda al ricordo grezzo,
  • collegare un debugger Java e pesca a strascico attraverso gli oggetti raggiungibili,
  • utilizzando "/ dev/mem" o simili per leggere la memoria processo dall'esterno,
  • accedere ai resti di immagine di scambio di un programma sul disco rigido, o
  • qualche facendolo core dump e leggendo la discarica.

Tuttavia, tutto tranne il primo di questi richiede che il malintenzionato abbia già infranto la sicurezza del sistema. E se il cattivo ha fatto questo ci sono altri (probabilmente più semplici) modi per rubare le password dal tuo programma ... che l'approccio "senza stringhe" non impedirà.

E se sei preoccupato per un hack che sfrutta un difetto di sicurezza di Java per leggere la memoria grezza, quel difetto potrebbe probabilmente essere utilizzato in altri modi; per esempio. iniettare il codice per modificare il modo in cui le password vengono gestite dal codice.

Quindi, in sintesi, "no string" protegge sia contro gli hack veramente difficili, sia contro i casi in cui la sicurezza è già esplosa. IMO, non ne vale la pena ... a meno che non si sia richiesto per implementare la sicurezza di livello militare.

+0

Per quanto riguarda il numero 1, Java definisce quali possibili conseguenze potrebbero esserci? Diciamo che esiste già una stringa uguale in memoria da qualche parte, ad esempio come chiave in una tabella hash. L'implementazione Java è autorizzata ad associare entrambe le stringhe allo stesso "supporto di testo" in questo caso (scusa non conosco la terminologia Java precisa qui)? Se è così, eliminando esplicitamente le stringhe che arrivano con i pacchetti HTTP, potrei in effetti aprire un vizioso buco di sicurezza DOS nella mia applicazione. –

+1

Potrebbe farlo. Ma in pratica, lo farà solo se qualcosa chiama 'String.intern()' su ENTRAMBI delle stringhe. L'altra possibilità è che la stringa della password condivide il backup con una stringa più grande; per esempio. la stringa che rappresenta la riga dell'intestazione. Non mi aspetterei che uno di questi scenari sia un problema. –

+0

In realtà, c'è un altro scenario. Quelle sono le JVM più vecchie in cui l'implementazione di 'String' condividerebbe l'array di backup' char [] 'tra stringhe diverse in alcune situazioni. L'implementazione di String è stata riscritta in Java 1.7.0_u6 per risolvere questo problema. (Era una fonte di perdite di memoria!) –