Eine Variable in Ruby "aufheben" [duplizieren]

Dec 06 2020

Ich habe einen Anwendungsfall, in dem ich einige Daten aus Sicherheitsgründen in dem Moment entsorgen muss, in dem ich sie nicht mehr benötige .

Ich schreibe einen Server in Ruby, der sich mit Anmeldungen und Passwörtern befasst. Ich verwende BCrypt, um Passwörter in meiner Datenbank zu speichern. Mein Server empfängt das Passwort, erstellt daraus einen bcrypt-Hash und verwendet dann nicht mehr das ursprüngliche Passwort.

Ich kenne eine Art von Cyberangriffen, bei denen Daten direkt aus dem RAM gestohlen werden, und ich befürchte, dass ein Angreifer das Kennwort eines Benutzers in der Zeitspanne, in der sich das Kennwort noch im Speicher befindet, in Form einer rohen Zeichenfolge stehlen könnte. Ich bin mir nicht sicher, ob eine einfache Verwendung password_in_string_form = nilausreichen würde.

Ich möchte die Variable, die das Kennwort des Benutzers enthält, aufheben, sobald ich damit fertig bin. Mit nullify meine ich etwas, das der Verwendung von / dev / null ähnelt, um etwas mit Nullen zu füllen. Das Endziel ist die irreversible Zerstörung von Daten .

Antworten

4 JohnBollinger Dec 06 2020 at 03:47

Ich bin mir nicht sicher, ob eine einfache Verwendung password_in_string_form = nilausreichen würde.

Nein, das würde nicht reichen. Das Objekt kann sofort Müll sein oder auch nicht, und selbst wenn dies der Fall ist, wird der Inhalt nicht aus dem Speicher gelöscht.

Ruby-Zeichenfolgen sind jedoch veränderbar , sofern sie nicht eingefroren wurden . Solange Sie die Kennwortzeichenfolge nicht einfrieren, können Sie ihren Inhalt durch Nullen oder zufällige Zeichen oder was auch immer ersetzen, bevor Sie sie loslassen. Dies sollte insbesondere funktionieren, vorbehaltlich einiger Vorbehalte, die später behandelt werden:

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

Es muss jedoch vorsichtig vorgegangen werden, da dieser Ansatz, der idomatischer erscheint, nicht funktioniert:

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

Anstatt den Inhalt der Zielzeichenfolge direkt zu aktualisieren, replace()gibt der Inhalt an Rubys internen Allokator frei (der ihn nicht ändert) und wählt eine Strategie für den neuen Inhalt basierend auf den Details der Ersetzung aus.

Der Unterschied in der Wirkung zwischen diesen beiden Ansätzen sollte jedoch eine große Warnflagge für Sie sein. Ruby ist eine ziemlich hohe Sprache. Es bietet Ihnen viel Hebelkraft, jedoch auf Kosten der Kontrolle über feine Details, z. B. ob und wie lange Daten im Speicher verbleiben.

Und das bringt mich zu den Vorbehalten. Hier sind die wichtigsten:

  • Wenn Sie mit der Kennwortzeichenfolge umgehen, müssen Sie darauf achten, dass Sie keine Kopien davon oder von Teilen davon erstellen oder alle Kopien erfassen und auch in den Papierkorb werfen. Das erfordert etwas Disziplin und Liebe zum Detail, da es sehr einfach ist, solche Kopien anzufertigen.

  • Das Löschen der Kennwortzeichenfolge selbst reicht möglicherweise nicht aus, um Ihr Ziel zu erreichen. Sie müssen auch alle anderen Kopien des Kennworts im Speicher ablegen, z. B. vor dem Isolieren der Kennwortzeichenfolge. Wenn es sich bei Ihrer beispielsweise um eine Webanwendung handelt, enthält diese den Inhalt der HTTP-Anforderung, in der das Kennwort an Ihre Anwendung übermittelt wurde, und wahrscheinlich mehr davon abgeleitete Zeichenfolgen als nur die isolierte Kennwortzeichenfolge. Ähnliches gilt für andere Arten von Anwendungen.

  • Passwörter sind möglicherweise nicht das einzige, was Sie schützen müssen. Wenn sich ein Gegner in der Lage befindet, Kennwörter aus dem Speicher des Hostcomputers zu stehlen, kann er auch die vertraulichen Daten stehlen, auf die Benutzer nach dem Anmelden zugreifen.

Aus diesen und anderen Gründen ist (reines) Ruby möglicherweise keine geeignete Implementierungssprache, wenn die Sicherheitsanforderungen für Ihren Server vorschreiben, dass speicherinterne Kopien von Benutzerkennwörtern zerstört werden, sobald sie nicht mehr benötigt werden.

Wenn andererseits ein Gegner einen ausreichenden Zugriff erhält, um Passwörter aus dem Speicher / Swap zu entfernen, ist das Spiel wahrscheinlich bereits vorbei. Zumindest haben sie Zugriff auf alles, auf das Ihre Anwendung zugreifen kann. Das macht die Passwörter nicht ganz umstritten, aber Sie sollten dies bei Ihrer Bewertung berücksichtigen, wie viel Aufwand Sie für dieses Problem aufwenden müssen.

1 JörgWMittag Dec 06 2020 at 03:27

Dies ist in Ruby nicht möglich.

Sie müssen für jede Implementierung spezifischen Code schreiben (Opal, TruffleRuby, JRuby, Rubinius, MRuby, YARV usw.), um dies sicherzustellen. Abhängig von der Implementierung ist es möglicherweise überhaupt nicht möglich, innerhalb des verwalteten Speichers der Implementierung zu arbeiten, ohne über einen separaten Speicher zu verfügen , den Sie selbst verwalten.

Das heißt, Sie benötigen wahrscheinlich ein kleines Stück nativen Codes, der sein eigenes kleines Stück nativen Speichers verwaltet und in Ihr Ruby-Programm einfügt.