ルビーの変数を「無効化」する[重複]
セキュリティ上の理由から、データが不要になった瞬間にデータを破棄する必要があるユースケースがあります。
ログインとパスワードを処理するサーバーをRubyで作成しています。私はBCryptを使用してパスワードをデータベースに保存しています。私のサーバーはパスワードを受け取り、それからbcryptハッシュを作成し、元のパスワードを使用しなくなります。
RAMから直接データを盗むことを伴う一種のサイバー攻撃を知っています。パスワードがまだメモリに残っている間に、攻撃者がユーザーのパスワードを生の文字列形式で盗む可能性があるのではないかと心配しています。単に使うだけpassword_in_string_form = nil
で十分かどうかはわかりません。
ユーザーのパスワードを保持している変数を使い終わった瞬間に無効にしたい。nullifyとは、/ dev / nullを使用して何かをゼロで埋めるのに似たものを意味します。最終目標は、データの不可逆的な破壊です。
回答
単に使うだけ
password_in_string_form = nil
で十分かどうかはわかりません。
いいえ、それだけでは十分ではありません。オブジェクトはすぐにガベージコレクションされる場合とされない場合があり、ガベージコレクションされたとしても、コンテンツがメモリから消去されることはありません。
ただし、凍結されていない限り、Ruby文字列は変更可能です。したがって、パスワード文字列をフリーズしない限り、パスワード文字列を手放す前に、その内容をゼロやランダムな文字などに置き換えることができます。特に、これは機能するはずですが、いくつかの条件を条件として、後で説明します。
(0 ... password_in_string_form.length).each do |i|
password_in_string_form[i] = ' '
end
しかし、注意を払う必要があります。これは、より理想的なように見えるかもしれないこのアプローチが機能しないためです。
# SURPRISE! This does not reliably remove the password from memory!
password_in_string_form.replace(' ' * password_in_string_form.length)
ターゲット文字列のコンテンツをインプレースで更新するのではなくreplace()
、コンテンツをRubyの内部アロケータ(コンテンツを変更しない)に解放し、置換の詳細に基づいて新しいコンテンツの戦略を選択します。
ただし、これら2つのアプローチの効果の違いは、大きな警告フラグになるはずです。Rubyはかなり高級言語です。それはあなたに多くのレバレッジを与えますが、データがメモリに保持されるかどうか、そしてどれくらいの期間保持されるかなどの細かい詳細を制御するという犠牲を払って。
そして、それは私を条件に導きます。主なものは次のとおりです。
パスワード文字列を処理するときは、パスワード文字列またはその一部のコピーを作成しないように注意する必要があります。そうでない場合は、すべてのコピーをキャプチャしてゴミ箱に移動することもできます。そのようなコピーを作成するのは非常に簡単なので、それは細部にいくらかの規律と注意を払うでしょう。
パスワード文字列自体を破棄するだけでは、目的を達成できない場合があります。また、パスワード文字列を分離するアップストリームなどから、メモリ内の他のパスワードのコピーをゴミ箱に移動する必要があります。たとえば、Webアプリケーションの場合、パスワードがアプリケーションに配信されたHTTPリクエストの内容と、分離されたパスワード文字列よりも多くの文字列が含まれている可能性があります。同様のことが他の種類のアプリケーションにも当てはまります。
保護する必要があるのはパスワードだけではない場合があります。攻撃者がホストマシンのメモリからパスワードを盗むことができる立場にある場合、敵対者は、ユーザーがログイン後にアクセスする機密データを盗む立場にもあります。
これらの理由やその他の理由により、サーバーのセキュリティ要件により、ユーザーパスワードのメモリ内コピーが不要になるとすぐに破棄されることが定められている場合、(純粋な)Rubyは適切な実装言語ではない可能性があります。
一方、攻撃者がメモリ/スワップからパスワードを取得するための十分なアクセス権を取得している場合は、おそらくすでにゲームオーバーです。少なくとも、アプリケーションがアクセスできるすべてのものにアクセスできます。それはパスワードを完全に無意味にするわけではありませんが、この問題にどれだけの努力を注ぐかを評価する際には、それを考慮に入れる必要があります。
これはRubyでは不可能です。
これを確実にするために、各実装(Opal、TruffleRuby、JRuby、Rubinius、MRuby、YARVなど)に固有のコードを作成する必要があります。実装によっては、自分で管理する別のメモリがないと、実装の管理対象メモリ内で実行することさえできない場合があります。
つまり、ネイティブメモリの小さな部分を管理し、それをRubyプログラムに挿入するネイティブコードの小さな部分が必要になる可能性があります。