"Annullare" una variabile in ruby ​​[duplicato]

Dec 06 2020

Ho un caso d'uso in cui ho bisogno di smaltire alcuni dati nel momento stesso in cui non ne ho più bisogno , per motivi di sicurezza.

Sto scrivendo un server in Ruby che si occupa di login e password. Uso BCrypt per memorizzare le password nel mio database. Il mio server riceve la password, ne crea un hash bcrypt e quindi non usa più la password originale.

Conosco una sorta di attacco informatico che comporta il furto di dati direttamente dalla RAM e temo che un utente malintenzionato possa rubare la password di un utente sotto forma di stringa grezza nel periodo di tempo in cui la password è ancora in memoria. Non sono sicuro che il semplice utilizzo password_in_string_form = nilsia sufficiente.

Voglio annullare la variabile che contiene la password dell'utente nel momento in cui ho finito con essa. Per nullify intendo qualcosa di simile all'uso di / dev / null per riempire qualcosa con zeri. L'obiettivo finale è la distruzione irreversibile dei dati .

Risposte

4 JohnBollinger Dec 06 2020 at 03:47

Non sono sicuro che il semplice utilizzo password_in_string_form = nilsia sufficiente.

No, non sarebbe abbastanza. L'oggetto potrebbe o non potrebbe essere sottoposto a Garbage Collection immediatamente e, anche se lo fosse, ciò non causerà la cancellazione del contenuto dalla memoria.

Tuttavia, a meno che non siano state congelate, le stringhe di Ruby sono modificabili . Quindi, fintanto che non congeli la stringa della password, puoi sostituirne il contenuto con zeri, o caratteri casuali, o qualsiasi altra cosa prima di lasciarla andare. In particolare, questo dovrebbe funzionare, fatte salve alcune clausole, trattate in seguito:

(0 ... password_in_string_form.length).each do |i|
    password_in_string_form[i] = ' '
end

Ma bisogna fare attenzione, perché questo approccio, che può sembrare più idomatico, non funziona:

# SURPRISE! This does not reliably remove the password from memory!
password_in_string_form.replace(' ' * password_in_string_form.length)

Piuttosto che aggiornare i contenuti della stringa di destinazione sul posto, replace()rilascia i contenuti all'allocatore interno di Ruby (che non li modifica) e sceglie una strategia per i nuovi contenuti in base ai dettagli della sostituzione.

La differenza di effetto tra questi due approcci dovrebbe essere un grande segnale di avvertimento per te, tuttavia. Ruby è un linguaggio piuttosto di alto livello. Ti dà molta leva, ma a costo del controllo sui dettagli più fini, come se e per quanto tempo i dati vengono conservati in memoria.

E questo mi porta alle condizioni. Ecco i principali:

  • Man mano che gestisci la stringa della password, devi fare attenzione a non farne copie o a qualsiasi parte di essa, oppure a catturare tutte le copie e cestinarle anche tu. Ciò richiederà un po 'di disciplina e attenzione ai dettagli, perché è molto facile fare tali copie.

  • Cestinare la stringa della password stessa potrebbe non essere sufficiente per raggiungere il tuo obiettivo. È inoltre necessario eliminare tutte le altre copie della password in memoria, ad esempio dall'isolamento della stringa della password. Se la tua è un'applicazione web, ad esempio, ciò includerebbe il contenuto della richiesta HTTP in cui la password è stata consegnata alla tua applicazione, e probabilmente più stringhe derivate da essa rispetto alla semplice stringa della password isolata. Lo stesso vale per altri tipi di applicazioni.

  • le password potrebbero non essere l'unica cosa che devi proteggere. Se un avversario è in una posizione in cui può rubare le password dalla memoria della macchina host, allora è anche in grado di rubare i dati sensibili a cui gli utenti accedono dopo il login.

Per questi e altri motivi, se i requisiti di sicurezza per il tuo server impongono che le copie in memoria delle password utente vengano distrutte non appena non sono più necessarie, allora il (puro) Ruby potrebbe non essere un linguaggio di implementazione appropriato.

D'altra parte, se un avversario ottiene un accesso sufficiente per raschiare le password dalla memoria / scambio, probabilmente il gioco è già finito. Come minimo, avranno accesso a tutto ciò a cui può accedere la tua applicazione. Ciò non rende le password del tutto discutibili, ma dovresti tenerlo in considerazione nella tua valutazione di quanto impegno dedicare a questo problema.

1 JörgWMittag Dec 06 2020 at 03:27

Questo non è possibile in Ruby.

Dovrai scrivere un codice specifico per ciascuna implementazione (Opal, TruffleRuby, JRuby, Rubinius, MRuby, YARV, ecc.) Per assicurartelo. A seconda dell'implementazione, potrebbe non essere nemmeno possibile fare all'interno della memoria gestita dell'implementazione, senza avere un pezzo di memoria separato che gestisci tu stesso.

Cioè probabilmente avrai bisogno di un piccolo pezzo di codice nativo che gestisca il suo piccolo pezzo di memoria nativa e lo inietti nel tuo programma Ruby.