質問

.NETのSecureStringの目的を理解しようとしています。 MSDNから:

  

System.Stringクラスのインスタンスは不変であり、不要になったときにプログラムでガベージコレクションのスケジュールを設定することはできません。つまり、インスタンスは作成後は読み取り専用になり、インスタンスがコンピューターのメモリから削除される時期を予測することはできません。そのため、Stringオブジェクトにパスワード、クレジットカード番号、個人データなどの機密情報が含まれている場合、アプリケーションがコンピューターのメモリからデータを削除できないため、使用後に情報が明らかになるリスクがあります。

     

SecureStringオブジェクトは、テキスト値を持つという点でStringオブジェクトに似ています。ただし、SecureStringオブジェクトの値は自動的に暗号化され、アプリケーションが読み取り専用としてマークするまで変更でき、アプリケーションまたは.NET Frameworkガベージコレクターのいずれかによってコンピューターのメモリから削除できます。

     

SecureStringのインスタンスの値は、インスタンスが初期化されるとき、または値が変更されるときに自動的に暗号化されます。アプリケーションは、MakeReadOnlyメソッドを呼び出すことにより、インスタンスを不変にレンダリングし、それ以上の変更を防ぐことができます。

自動暗号化は大きな見返りですか?

そして、なぜ私が言うことができないのか:

SecureString password = new SecureString("password");

の代わりに

SecureString pass = new SecureString();
foreach (char c in "password".ToCharArray())
    pass.AppendChar(c);

SecureStringのどの部分が欠けていますか?

役に立ちましたか?

解決

現在 を使用しているフレームワークの一部SecureString

主な目的は、攻撃対象を排除するのではなく、攻撃対象を減らすことです。 SecureStrings は&quot ;ピン留め"ガベージコレクターがRAM内で移動したり、コピーしたりしないようにします。また、プレーンテキストがスワップファイルまたはコアダンプに書き込まれないようにします。暗号化は難読化に似ており、ハッカーを断固として止めません。ハッカーは暗号化および復号化に使用される対称キー

他の人が言ったように、 SecureString 文字ごとに行うのは、別の方法で行う最初の明らかな欠陥です。おそらく、単純な文字列としての秘密の値をすでに持っているので、何がポイントなのでしょうか?

SecureString は鶏と卵の問題を解決するための最初のステップであるため、ほとんどの現在のシナリオでは、それらを通常の文字列に変換して使用する必要がありますが、フレームワークに存在することにより、未来-少なくともあなたのプログラムが弱いリンクである必要はありません。

他のヒント

多くの素晴らしい答え;ここで説明した内容の簡単な概要を示します。

Microsoftは、機密情報(クレジットカード、パスワードなど)によるセキュリティを強化するためにSecureStringクラスを実装しています。自動的に提供されます:

  • 暗号化(メモリダンプの場合 またはページキャッシュ)
  • メモリの固定
  • 読み取り専用としてマークする機能(さらなる変更を防ぐため)
  • 定数文字列の受け渡しを許可しないことによる安全な構築

現在、SecureStringの使用は制限されていますが、将来的にはより良い採用が期待されています。

この情報に基づいて、SecureStringのコンストラクターは、文字列を取得してchar配列にスライスするだけではなく、文字列のスペルがSecureStringの目的に反するためです。

追加情報:

  • .NETセキュリティからの投稿 ほぼ同じことについて話しているブログ ここで覆われています。
  • および別の 1つ 再訪してツールについて言及する その内容をダンプすることができます SecureString。

編集:良い情報がたくさんあるので、最良の答えを選ぶのは難しいことがわかりました。アシストされた回答オプションがないのは残念です。

簡単な回答

  

なぜ私は言うことができません:

SecureString password = new SecureString("password");

メモリに password があるため、消去する方法はありません-これはまさに SecureString のポイントです。

ロングアンサー

SecureString が存在する理由は、完了後に機密データを消去するために ZeroMemory を使用できないためです。 CLRの原因に存在する問題を解決するために存在します。

通常のネイティブアプリケーションでは、 SecureZeroMemory

  

メモリブロックをゼロで埋めます。

:SecureZeroMemoryは ZeroMemory ただし、コンパイラは最適化を行いません。

問題は、.NET内で ZeroMemory または SecureZeroMemory 呼び出せないことです。 .NETでは、文字列は不変です。他の言語でできるように文字列の内容を上書きすることさえできません:

//Wipe out the password
for (int i=0; i<password.Length; i++)
   password[i] = \0;

では、何ができますか?パスワードまたはクレジットカード番号をメモリから消去する機能を.NETで提供するにはどうすればよいですか?

それを行う唯一の方法は、ネイティブメモリブロックに文字列を配置することです。ここでできる ZeroMemory を呼び出します。次のようなネイティブメモリオブジェクト:

  • BSTR
  • HGLOBAL
  • CoTaskMemアンマネージメモリ

SecureStringは失われた能力を取り戻します

.NETでは、文字列を使い終わったときに消去することはできません。

  • これらは不変です。内容を上書きすることはできません
  • それらを破棄することはできません
  • それらのクリーンアップはガベージコレクターに委ねられています

SecureStringは、文字列の安全性を回避する方法として存在し、必要なときにクリーンアップを保証できます。

質問をした:

  

なぜ私は言うことができません:

String connectionString = secureConnectionString.ToString()

メモリに password があるため、それを拭く方法はありません。 CLRがそのメモリを再利用することを決定するまで、そこに留まります。あなたは私たちを始めたところに戻しました。削除できないパスワードを使用して実行中のアプリケーション、およびメモリダンプ(またはプロセスモニター)がパスワードを表示できる場所。

SecureStringは、データ保護APIを使用して、暗号化された文字列をメモリに保存します。そのようにすると、文字列はスワップファイル、クラッシュダンプ、または同僚があなたを見るべきローカル変数ウィンドウにも存在しなくなります。

パスワードの読み方

次に質問があります:文字列とどのようにやり取りしますか?次のような方法は絶対に望まない

SqlCredential cred = new SqlCredential(userid, password); //password is SecureString
SqlConnection conn = new SqlConnection(connectionString);
conn.Credential = cred;
conn.Open();

今、あなたはあなたが始めた場所に戻っているので-あなたが取り除くことができないパスワード。デリケートな文字列を開発者に強制させて、メモリから消去できるようにする必要があります。

それが、.NETがSecureStringをアンマネージメモリにマーシャリングする3つの便利なヘルパー関数を提供する理由です:

1つのフラットなインスタンス化の代わりに文字を追加する必要がある理由は、バックグラウンドで「パスワード」を渡すためだと思います。 SecureStringのコンストラクタに&quot; password&quot;セキュリティで保護された文字列の目的を無効にするメモリ内の文字列。

追加することにより、文字を一度にメモリに入れるだけで、物理的に互いに隣接しないようにして、元の文字列を再構築するのがはるかに難しくなります。私はここで間違っている可能性がありますが、それは私に説明された方法です。

このクラスの目的は、メモリダンプまたは同様のツールを介して安全なデータが公開されるのを防ぐことです。

MSは、サーバー(デスクトップなど)をクラッシュさせる特定のインスタンスで、ランタイム環境がメモリダンプを行ってメモリ内の内容を公開する場合があることを発見しました。 Secure Stringは、メモリ内で暗号化して、攻撃者が文字列のコンテンツを取得できないようにします。

SecureStringの大きな利点の1つは、ページのキャッシュによりデータがディスクに保存される可能性を回避することになっていることです。メモリにパスワードがあり、大きなプログラムまたはデータセットをロードすると、プログラムがメモリ外にページングされるときにパスワードがスワップファイルに書き込まれる可能性があります。 SecureStringを使用すると、少なくともデータがクリアテキストでディスク上に無期限に存在することはありません。

それは、文字列が安全であることを意図しているからだと思います。つまり、ハッカーはそれを読むことができないはずです。文字列で初期化すると、ハッカーは元の文字列を読み取ることができます。

まあ、説明が述べているように、値は暗号化されて保存されます。つまり、プロセスのメモリダンプは文字列の値を明らかにしません(かなり深刻な作業なし)。

定数文字列からSecureStringを構築できないのは、暗号化されていないバージョンの文字列をメモリに保存する必要があるためです。文字列を分割して作成するように制限すると、文字列全体が一度にメモリに格納されるリスクが減少します。

SecureStringの使用を停止します。 PGの連中がサポートをやめているようです。将来的にはプルする可能性もあります- https://github.com / dotnet / apireviews / tree / master / 2015-07-14-securestring

  

.NET CoreのすべてのプラットフォームでSecureStringから暗号化を削除する必要があります-SecureStringを廃止する必要があります-SecureStringを.NET Coreで公開しないでください

別の使用例は、ペイメントアプリケーション(POS)を使用していて、慎重な開発者であるため、機密データを保存するために単に不変のデータ構造を使用できない場合です。たとえば、カードの機密データまたは認証メタデータを不変の文字列に保存する場合、このデータが破棄されてからかなりの時間メモリ内で利用可能になる場合が常にあります。単純に上書きすることはできません。そのような機密データが暗号化されたメモリに保持される別の大きな利点。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top