.NETでSecureStringが必要になるのはいつですか?
-
02-07-2019 - |
質問
.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
:
- WPFの
System.Windows.Controls .PasswordBox
コントロールは、パスワードを内部的にSecureStringとして保持します(PasswordBox :: SecurePassword
を介してコピーとして公開されます) -
System.Diagnostics.ProcessStartInfo :: Password
プロパティはですSecureString
-
X509Certificate2のコンストラクター
は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つの便利なヘルパー関数を提供する理由です:
- SecureStringToBSTR ( ZeroFreeCoTaskMemUnicode )
-
現在のバージョンのフレームワークでSecureStringを賢明に使用できるシナリオはほとんどありません。これは、アンマネージAPIとの対話にのみ有効です。Marshal.SecureStringToGlobalAllocUnicodeを使用してマーシャリングできます。
System.Stringに変換したり、System.Stringから変換したりすると、その目的は無効になります。
MSDN サンプルは、一度に1文字ずつSecureStringを生成します。コンソール入力し、安全な文字列をアンマネージAPIに渡します。かなり複雑で非現実的です。
.NETの将来のバージョンでは、SecureStringがより便利になるSecureStringのサポートが増えると思われるかもしれません。例:
-
SecureString Console.ReadLineSecure()など。サンプルの複雑なコードを一切使用せずにコンソール入力をSecureStringに読み込みます。
-
パスワードを安全に入力できるように、TextBox.Textプロパティを安全な文字列として保存するWinForms TextBoxの置換。
-
パスワードをSecureStringとして渡すことを許可するセキュリティ関連APIの拡張。
上記がなければ、SecureStringの値は制限されます。
-
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)を使用していて、慎重な開発者であるため、機密データを保存するために単に不変のデータ構造を使用できない場合です。たとえば、カードの機密データまたは認証メタデータを不変の文字列に保存する場合、このデータが破棄されてからかなりの時間メモリ内で利用可能になる場合が常にあります。単純に上書きすることはできません。そのような機密データが暗号化されたメモリに保持される別の大きな利点。