関数の戻り値は、.NET アプリでは、プロセス内の保護されたメモリに存在する「評価スタック」にプッシュされます。ただし、文字列について話しているのは参照型であるため、評価スタックにあるのは、ヒープ上のその文字列の場所へのポインターです。ヒープ メモリは、揮発性が高い評価スタックやコール スタックとは異なり、共有される可能性があり、GC が収集する必要があると判断しない限り存続するため、比較的安全ではありません。ただし、ヒープ メモリにアクセスするには、そのメモリを共有する必要があります。攻撃者は、そのメモリにアクセスするための OS と CLR からのアクセス許可を持つアプリを持っている必要があり、どこを見ればよいかを知っている必要があります。
攻撃者がそのようなアクセス権を持っている場合、コンピューターから平文のパスワードを取得するはるかに簡単な方法があります。キーロガーは入力されたパスワードを監視できます。または、別のスヌーパーが GDI UI の管理されていない側の実際のハンドルを監視し、Windows GUI に実際に表示されているテキスト ボックスがプレーンテキスト値を取得するのを確認できます (ディスプレイ上で難読化されているだけです)。.NET のコード アクセス セキュリティや保護されたメモリをクラックしようとすることすらありません。
攻撃者がこの種のコントロールを持っている場合、あなたは負けています。したがって、これが防御の最前線となるはずです。クライアント コンピューターにそのようなマルウェアがないこと、およびユーザーがログインしようとしているクライアント アプリのインスタンスがクラックされたそっくりなものに置き換えられていないことを確認してください。
インスタンス間の難読化されたパスワード ストレージに関する限り、メモリ スヌーピングが心配な場合、Rijndael のような対称アルゴリズムは防御にはなりません。攻撃者がクライアント コンピューターのメモリを見ることができれば、暗号化に使用されたキーを知っています。したがって、クライアント アプリにハードコードされるか、セキュリティで保護された文字列の近くに格納されます。繰り返しますが、攻撃者がこの種の制御を持っている場合、クライアント側で認証を行うと負けになります。
代わりに、物理的および電子的に保護されたマシン上のサービス レイヤーを使用して、攻撃者によって悪用された場合 (主にデータの取得/変更) に有害となるアプリの機能を提供します。このサービス レイヤーは、認証と、クライアント アプリが許可するすべての実行をユーザーに許可するために使用できます。
次の点を考慮してください。
- ユーザーは資格情報をクライアント アプリに入力します。これらの資格情報は AD 資格情報と同じにすることができますが、AD 資格情報としては使用されません。キーロガーやその他のマルウェアがこれを確認するのを防ぐ唯一の方法は、優れた AV ソフトウェアを適用して、そのようなマルウェアがコンピューターに存在しないようにすることです。
- クライアント アプリは、WCF を介してサービス エンドポイントに接続します。エンドポイントは X.509 証明書で署名できます。NSA レベルのセキュリティではありませんが、少なくとも、自分の管理下にあるサーバーと通信していると確信できます。
- 次に、クライアント アプリは、SHA-512 などの大きなダイジェストを生成するものを使用して、ユーザーのパスワードをハッシュします。これ自体は安全ではありません。速すぎて、ユーザーのパスワードのエントロピーが低すぎて、攻撃者がハッシュを解読できないようになっています。ただし、繰り返しになりますが、ハッシュを表示するにはコンピューターを制御する必要があり、さらに難読化する予定です。
- クライアント アプリは、クライアント コンピューターのユーザー名、パスワード、およびハードウェア ID を WCF チャネル経由で送信します。
- サーバーはこれらの資格情報を取得します。サーバーは平文のパスワードを取得しないことに注意してください。これには理由があります。
- サーバーは、ハッシュ化されたパスワードを 256 ビットの半分に分割します。前半部分は BCrypted され (適切に遅くなるように構成された実装を使用します。通常は 10 または 11 回の「ラウンド」で実行されます)、ユーザー データベースのハッシュ値と比較されます。それらが一致する場合、DB はユーザーの AD 資格情報を返します。これは、パスワード ハッシュの残りの半分で対称的に暗号化されています。これが、プレーンテキストのパスワードが送信されない理由です。サーバーはそれを知る必要はありませんが、攻撃者は盗んだユーザー データベースのコピーから何か意味のあるものを得るために、それを知る必要があります。
- サーバーは AD 資格情報を復号化して AD に送信し、そのユーザーの ID とセキュリティ コンテキストを表す IPrincipal を受け取ります。IPrincipal の実装には、ユーザーのアカウントのクラックに使用できる情報は含まれません。
- サーバーは、暗号的にランダムな 128 ビット値を生成し、128 ビットのハードウェア GUID を連結して、SHA512 でハッシュします。そのハッシュの半分を使用して、AD 資格情報の復号化に使用されたキー値を対称的に暗号化しました。次に、残りの半分を BCrypt し、そのハッシュを暗号化されたキーと一緒に保存します。
- 次に、サーバーは、セキュリティで保護された WCF チャネルを介して 3 つの情報を送り返します。AD が生成した IPrincipal、ハッシュされていない 128 ビットのランダム値 (「転送トークン」)、および任意の長さの別の暗号学的にランダムな値 (「セッション トークン」)。
- クライアント アプリはクライアント側で認証されるようになりました。つまり、AD ロール メンバーシップについて IPrincipal に問い合わせることで、コードへのユーザー アクセスを制御できます。また、サーバーは、セッション トークンを持つユーザーが実際のユーザーであることを確信できるようになりました。サービスをさらに呼び出す場合 (データの取得/永続化)、クライアントはネゴシエートされた WCF チャネルを使用し、そのセッション トークンを渡す必要があります。WCF チャネルとセッション トークンの組み合わせは、1 回限りで一意です。新しいチャネルで古いトークンを使用したり、同じチャネルで間違ったトークンを渡したりすると、セッションが侵害されたことを示します。とりわけ、クライアントまたはサーバーのいずれかにいつでもどこにでも保存されている永続データは、AD クレデンシャルの取得と認証に使用できません。
ここで、クライアント アプリケーションを閉じると、クライアントとサーバーの間のすべての「セッション状態」が失われます。セッション トークンは、他のネゴシエートされたチャネルでは無効です。つまり、認証が失われました。接続する次のクライアントは、彼らが誰であるかに関係なく、誰でもかまいません。これが「転送トークン」の出番です。
- 「転送トークン」は、システムへの無料パスです。発行後 18 時間使用しないと有効期限が切れます。
- クライアント アプリケーションは、閉じるときに 2 つの情報を新しいインスタンスに渡します (どのように選択しても)。ログインした人のユーザー名と「譲渡トークン」。
- クライアント アプリケーションの新しいインスタンスは、これら 2 つの情報を受け取り、クライアント マシンのハードウェア ID も取得します。WCF サービスとの安全な接続をネゴシエートし、これら 3 つの情報を渡します。
- ユーザーが最後に 18 時間以上前にログインした場合 (24 時間前ではないため、昨日ログインする 1 分前にログインしてアプリを再起動することはできません)、または本当に偏執的になりたい場合は、8 時間以上前に、アプリは、そのアカウントの転送トークンが期限切れであるというエラーをすぐに返します。
- このサービスは転送トークンを取得し、ハードウェア ID を連結し、それを SHA-512 し、半分を BCrypts し、その結果を格納されている 2 番目の検証値と比較します。転送トークンと最後にログインしたマシンの適切な組み合わせのみが、正しいハッシュを生成します。一致する場合、ハッシュの残りの半分を使用してキーを復号化し、AD 情報を復号化します。
- 次にサービスは、ユーザーがアプリケーション パスワード ハッシュを提供したかのように処理を進め、AD 情報を復号化し、IPrincipal を取得し、新しい転送トークンとセッション トークンを生成し、AD データのキーを再暗号化します。
- このプロセスのいずれかの部分が失敗した場合 (同じトークンを 2 回使用したり、別のマシンまたは別のユーザーのトークンを使用したりするなど、正しくないトークンを使用しようとした場合)、サービスは資格情報が無効であることを報告します。その後、クライアント アプリは標準のユーザー パスワード検証にフォールバックします。
これがこすりです。このシステムは、ユーザーの頭以外には保持されない秘密のパスワードに依存しているため、バックドアがありません。管理者は、失われたパスワードをクライアント アプリに取得できません。また、AD 資格情報を変更する必要がある場合、クライアント アプリ内からのみ変更できます。ユーザーは、Windows ログイン時に AD 自体によってパスワードを強制的に変更することはできません。これを行うと、クライアント アプリに入るために必要な認証スキームが破棄されるためです (暗号化された資格情報は機能しなくなり、クライアント アプリの資格情報は無効になります)。新しいものを再暗号化する必要があります)。AD 内でこの検証を傍受でき、クライアントのアプリ資格情報が AD 資格情報である場合、ユーザー アプリの資格情報を自動的に変更できますが、今では
最後に、このセキュリティ システムのこの変種は、1 つの原理のみで機能します。サーバーが現在攻撃者によって侵害されていないこと。誰かが入り込んでオフライン データをダウンロードすることができますが、彼らは立ち往生しています。しかし、メモリやトラフィックを監視するために何かをインストールできる場合は、資格情報 (ユーザー名/パスワード ハッシュまたは転送トークン/ハードウェア ID) が入って検証されると、攻撃者はユーザーのAD 資格情報。通常、クライアントは復号化キーを送信せず、ハッシュ化されたパスワードの半分の検証のみを送信し、サーバーは暗号化された資格情報を送信します。ただし、クライアントはサーバーよりも大きなセキュリティ リスクであると考えているため、それが真実である限り、