Credential Guard によるドメインの派生資格情報の保護

Windows 10 Enterprise で導入された Credential Guard では、仮想化ベースのセキュリティを使って、特権を持つシステム ソフトウェアのみがアクセスできるようにシークレットを分離します。これらのシークレットへの未承認のアクセスは、Pass-the-Hash や Pass-the-Ticket など、資格情報の盗難攻撃につながる可能性があります。

Credential Guard は、以下の機能と解決策を提供します。

  • ハードウェア セキュリティ Credential Guard は、セキュア ブートや仮想化を含む、プラットフォームのセキュリティ機能を活用して、ドメインの派生資格情報のセキュリティを向上させます。

  • 仮想化ベースのセキュリティ: 実行中のオペレーティング システムから分離された保護環境で、ドメインの派生資格情報およびその他の機密情報を管理する Windows サービスを実行します。

  • 高度な永続的脅威に対する保護の強化: 資格情報の盗難攻撃の手法および多くの標的型攻撃で使用されるツールをブロックする仮想化ベースのセキュリティを使用して、ドメインの派生資格情報を保護します。管理者特権を持っているオペレーティング システムで実行されるマルウェアは、仮想化ベースのセキュリティで保護されているシークレットを抽出できません。Credential Guard は強力な軽減策ですが、持続的な脅威による攻撃は新しい攻撃技術によく移行するため、Device Guard などのセキュリティ戦略およびアーキテクチャも組み込む必要があります。

  • 管理容易性: グループ ポリシー、WMI、コマンド プロンプト、Windows PowerShell を使って、Credential Guard を管理できます。

しくみ

資格情報ガードは、仮想化ベースのセキュリティを使用して、以前のバージョンの Windows でローカル セキュリティ機関 (LSA) に格納されたシークレットを分離します。Windows 10 より前は、オペレーティング システムのプロセス メモリで使われるシークレットは LSA に格納されていました。オペレーティング システムの LSA プロセスでは、Credential Guard を使用して、これらのシークレットを格納および保護する分離 LSA プロセスと呼ばれる新しいコンポーネントとやり取りします。分離 LSA プロセスによって格納されているデータは仮想化ベースのセキュリティを使って保護され、オペレーティング システムの他の部分からアクセスできません。LSA は、リモート プロシージャ コールを使って分離 LSA プロセスと通信します。

セキュリティ上の理由から、分離 LSA プロセスはデバイス ドライバーをホストしません。代わりに、セキュリティに必要なオペレーティング システムのバイナリの小さなサブセットのみをホストします。これらのバイナリはすべて、仮想化ベースのセキュリティによって信頼されている証明書で署名されます。これらの署名は、保護されている環境内でファイルを起動する前に検証されます。

Credential Guard は、既定の派生資格情報を使う場合、NTLM の古いバリアント、Kerberos の認証プロトコル、暗号も許可しません。たとえば、NTLMv1、MS-CHAPv2、強度の低い種類の Kerberos 暗号化 (DES など) が含まれます。

仮想化ベースのセキュリティを使用して LSA がどのように分離されるかについて、概要を以下に示します。

Mt483740.credguard(ja-jp,VS.85).png

新機能と変更された機能

Credential Guard の追加または変更内容を確認するには、「Credential Guard の新機能」を参照してください。

ハードウェアおよびソフトウェアの要件

PC は、Credential Guard を使用するために、次のハードウェアおよびソフトウェアの要件を満たす必要があります。

要件 説明

Windows 10 Enterprise

PC では、Windows 10 Enterprise が実行されている必要があります。

UEFI ファームウェア バージョン 2.3.1 以上とセキュア ブート

ファームウェアが UEFI バージョン 2.3.1 以上とセキュア ブートを使用していることを確認するには、Windows ハードウェア互換性プログラムの要件 System.Fundamentals.Firmware.CS.UEFISecureBoot.ConnectedStandby を使って検証します。

仮想化拡張機能

仮想化ベースのセキュリティをサポートするには、次の仮想化拡張機能が必要です。

  • Intel VT-x または AMD-V
  • Second Level Address Translation

x64 アーキテクチャ

Windows ハイパーバイザー上で仮想化ベースのセキュリティが使用する機能は、64 ビット PC でのみ実行できます。

VT-d または AMD-Vi IOMMU (入出力メモリ管理ユニット)

Windows 10 では、IOMMU によって、メモリ攻撃からのシステムの回復性を強化します。¹

トラステッド プラットフォーム モジュール (TPM) バージョン 1.2 または 2.0

TPM 1.2 および 2.0 は、ファームウェアに格納されている暗号化キーの保護を提供します。TPM 1.2 は、Windows 10 (ビルド 10240) ではサポートされていませんが、Windows 10 バージョン 1511 (ビルド 10586) 以降でサポートされています。

  TPM がインストールされていない場合でも Credential Guard は有効になりますが、Credential Guard を暗号化するために使われるキーは TPM によって保護されません。
 

安全なファームウェア更新プロセス

ファームウェアが安全なファームウェア更新プロセスに準拠していることを確認するには、Windows ハードウェア互換性プログラムの要件 System.Fundamentals.Firmware.UEFISecureBoot を使って検証します。

セキュア MOR の実装に対応するために更新されたファームウェア

Credential Guard は、特定のメモリ攻撃を防ぐためにセキュア MOR ビットを必要とします。

物理 PC

Windows 10 を実行している PC の場合、仮想マシンで Credential Guard を実行することはできません。

 

¹ グループ ポリシーの設定で [セキュア ブートと DMA 保護] を選んだ場合、IOMMU が必要です。グループ ポリシーの [セキュア ブート] オプションを選ぶと、IOMMU のないデバイスで Credential Guard を実行できます。

Credential Guard の管理

Credential Guard を使用する前に、Credential Guard で使用される仮想化ベースのセキュリティ機能を各 PC で有効にしておく必要があります。

グループ ポリシーを使った Credential Guard の有効化

グループ ポリシーを使うことにより、仮想化に基づくセキュリティ機能が追加されるため、Credential Guard を有効にすることができます。

  1. グループ ポリシー管理コンソールから、[コンピューターの構成][管理用テンプレート][システム][Device Guard] の順に移動します。

  2. [仮想化ベースのセキュリティを有効にする] をダブルクリックし、[有効] をクリックします。

  3. [プラットフォームのセキュリティ レベルを選択する] ボックスで、[セキュア ブート] または [セキュア ブートと DMA 保護] を選びます。

  4. [Credential Guard Configuration] (Credential Guard の構成) ボックスで、[Enabled with UEFI lock] (UEFI ロックありで有効化) をクリックしてから [OK] をクリックします。Credential Guard をリモートでオフにできるようにする場合は、[Enabled without lock] (ロックなしで有効化) を選択します。

    Mt483740.CredGuard_GP(ja-jp,VS.85).png

  5. グループ ポリシー管理コンソールを閉じます。

イメージへの Credential Guard の追加

Credential Guard をイメージに追加する場合は、仮想化ベースのセキュリティ機能を追加し、Credential Guard を有効にすることでこれを実行できます。

仮想化ベースのセキュリティ機能の追加

最初に、仮想化ベースのセキュリティ機能を追加する必要があります。コントロール パネルまたは展開イメージのサービスと管理ツール (DISM) を使うことでこれを行うことができます。

  グループ ポリシーを使って Credential Guard を有効にする場合、次の手順は必要ありません。グループ ポリシーによって、この機能がインストールされます。

 

Mt483740.wedge(ja-jp,VS.85).gif[プログラムと機能] を使って仮想化ベースのセキュリティ機能を追加する

  1. コントロール パネルの [プログラムと機能] を開きます。

  2. [Windows の機能の有効化または無効化] をクリックします。

  3. [分離ユーザー モード] チェック ボックスをオンにします。

  4. [Hyper-V]Hyper-V プラットフォーム] の順に移動し、[Hyper-V Hypervisor] チェック ボックスをオンにします。

  5. [OK] をクリックします。

Mt483740.wedge(ja-jp,VS.85).gifDISM を使って仮想化ベースのセキュリティ機能をオフライン イメージに追加する

  1. 管理者特権でのコマンド プロンプトを開きます。

  2. 次のコマンドを実行して Hyper-V Hypervisor を追加します。

    dism /image:<WIM file name> /Enable-Feature /FeatureName:Microsoft-Hyper-V-Hypervisor
    
  3. 次のコマンドを実行して分離ユーザー モードを追加します。

    dism /image:<WIM file name> /Enable-Feature /FeatureName:IsolatedUserMode
    

  

DISM または Configuration Manager を使用して、これらの機能をオンライン イメージに追加することもできます。

 

Credential Guard の有効化

グループ ポリシーを使わない場合は、レジストリを使って Credential Guard を有効にすることができます。

Mt483740.wedge(ja-jp,VS.85).gifレジストリを使って Credential Guard を有効にする

  1. レジストリ エディターを開きます。

  2. 仮想化ベースのセキュリティを有効にします。

    • HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\DeviceGuard に移動します。

    • EnableVirtualizationBasedSecurity という名前の新しい DWORD 値を追加します。仮想化ベースのセキュリティを有効にするには、このレジストリ設定の値を 1 に設定します。無効にするには、0 に設定します。

    • RequirePlatformSecurityFeatures という名前の新しい DWORD 値を追加します。[セキュア ブート] のみを使用するには、このレジストリ設定の値を 1 に設定します。[セキュア ブートと DMA 保護] を使用するには、2 に設定します。

  3. Credential Guard を有効にします。

    • HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\LSA に移動します。

    • LsaCfgFlags という名前の新しい DWORD 値を追加します。Credential Guard を UEFI ロックありで有効にするにはレジストリ設定の値を 1 に設定し、ロックなしで Credential Guard を有効にするには 2 に設定し、無効化するには 0 に設定します。

  4. レジストリ エディターを閉じます。

  

FirstLogonCommands 無人設定のレジストリ エントリを設定して Credential Guard を有効にすることもできます。

 

Credential Guard の削除

PC で Credential Guard を削除する場合、次の操作を実行する必要があります。

  1. グループ ポリシーを使用した場合は、Credential Guard を有効にするために使用したグループ ポリシー設定 ([コンピューターの構成][管理用テンプレート][システム]Device Guard][仮想化ベースのセキュリティを有効にする]) を無効にします。

  2. レジストリ設定 HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\DeviceGuard\LsaCfgFlags を削除します。

  3. bcdedit を使って Credential Guard の EFI 変数を削除します。

Mt483740.wedge(ja-jp,VS.85).gifCredential Guard の EFI 変数を削除する

  1. 管理者特権のコマンド プロンプトで、次のコマンドを入力します。

    mountvol X: /s
    copy %WINDIR%\System32\SecConfig.efi X:\EFI\Microsoft\Boot\SecConfig.efi /Y
    bcdedit /create {0cb3b571-2f2e-4343-a879-d86a476d7215} /d "DebugTool" /application osloader
    bcdedit /set {0cb3b571-2f2e-4343-a879-d86a476d7215} path "\EFI\Microsoft\Boot\SecConfig.efi"
    bcdedit /set {bootmgr} bootsequence {0cb3b571-2f2e-4343-a879-d86a476d7215}
    bcdedit /set {0cb3b571-2f2e-4343-a879-d86a476d7215} loadoptions DISABLE-LSA-ISO
    bcdedit /set {0cb3b571-2f2e-4343-a879-d86a476d7215} device partition=X:
    mountvol X: /d
    
  2. PC を再起動します。

  3. Credential Guard を無効にすることを確認するメッセージを受け入れます。

  4. または、仮想化ベースのセキュリティ機能を無効にすることで、Credential Guard を無効にすることができます。

  

EFS で暗号化されたファイルなどのコンテンツの暗号化を解除するために、PC にはドメイン コントローラーへの 1 回限りのアクセスが必要です。

Credential Guard と仮想化ベースのセキュリティの両方を無効にする場合は、すべての仮想化ベースのセキュリティのグループ ポリシーとレジストリの設定を無効にした後、次の bcdedit コマンドを実行します。

bcdedit /set {0cb3b571-2f2e-4343-a879-d86a476d7215} loadoptions DISABLE-LSA-ISO,DISABLE-VBS

仮想化ベースのセキュリティと Device Guard について詳しくは、「Device Guard 展開ガイド」を参照してください。

 

Credential Guard が実行されていることの確認

システム情報を使って、Credential Guard が PC で実行されていることを確認できます。

  1. [スタート] をクリックし、「msinfo32.exe」と入力して、[システム情報] をクリックします。

  2. [システムの概要] をクリックします。

  3. [Credential Guard][実行中の Device Guard セキュリティ サービス] の横に表示されることを確認します。

    次に例を示します。

    Mt483740.CredGuard_MSInfo32(ja-jp,VS.85).png

Credential Guard を使用する場合の考慮事項

  • デバイスがドメインに参加した後、デバイスで資格情報ガードを有効にした場合、ユーザーとデバイスのシークレットは既に侵害されている可能性があります。PC がドメインに参加する前に、資格情報ガードを有効にすることをお勧めします。

  • Credential Guard が有効になっている PC についても通常のレビューを実行する必要があります。これは、セキュリティ監査ポリシーまたは WMI クエリによって実行できます。検索する WinInit イベント ID の一覧を次に示します。

    • イベント ID 13 Credential Guard (LsaIso.exe) が開始され、LSA 資格情報が保護されます。

    • イベント ID 14Credential Guard (LsaIso.exe) の構成: 0x1、0

      • 最初の変数: 0x1 は、Credential Guard の実行が構成されていることを意味します。0x0 は、実行するように構成されていないことを意味します。
      • 2 番目の変数: 0 は保護モードで実行するように構成されていることを意味します。1 は、テスト モードで実行するように構成されていることを意味します。この変数は常に 0 である必要があります。
    • イベント ID 15 Credential Guard (LsaIso.exe) が構成されていますが、セキュリティで保護されたカーネルが実行されていないため、Credential Guard なしで続行しています。

    • イベント ID 16 Credential Guard (LsaIso.exe) を起動できませんでした: [エラー コード]

    • イベント ID 17 Credential Guard (LsaIso.exe) の UEFI 構成の読み取りエラー: [エラー コード]

    次のイベントをチェックしてキーの保護で TPM が使われていることを確認することもできます。[Microsoft] -> [Windows] -> [カーネル ブート] イベント ソース。TPM を使って実行している場合、TPM PCR マスクの値は 0 以外の値になります。

    • イベント ID 51 VSM マスター暗号化キーをプロビジョニングします。キャッシュ済みコピーの使用状態: 0x0。キャッシュ済みコピーのシール解除状態: 0x1。新しいキーの生成状態: 0x1。シール状態: 0x1。TPM PCR マスク: 0x0。
  • パスワードはまだ脆弱であるため、組織が Credential Guard を展開しパスワードからその他の認証方法 (物理スマート カード、仮想スマート カード、Microsoft Passport、Microsoft Passport for Work など) に移行することをお勧めします。

  • 一部のサード パーティのセキュリティ サポート プロバイダー (SSP や AP) は、資格情報ガードと互換性がない場合があります。Credential Guard は、サード パーティの SSP が LSA にパスワード ハッシュを要求することを許可していません。ただし、ユーザーがログオンやパスワードを変更したときに SSP や AP がパスワードの通知を受け取ることもあります。カスタム SSP/AP 内での文書化されていない API の使用はサポートされません。SSP/AP のカスタム実装は Credential Guard を使ってテストし、SSP/AP が文書化されていない動作やサポートされていない動作に依存していないことを確認することをお勧めします。たとえば、KerbQuerySupplementalCredentialsMessage API の使用はサポートされません。NTLM または Kerberos SSP をカスタム SSP/AP に置き換えないでください。詳しくは、MSDN のセキュリティ パッケージの登録とインストールの制限に関するページをご覧ください。

  • Credential Guard によって提供される保護がより深く、より広くなるにつれて、Windows 10 の今後のリリースで Credential Guard を実行した場合に、以前は機能していたシナリオに影響を及ぼす可能性があります。 たとえば、Credential Guard によって、脆弱性を悪用するマルウェアを防止する特定の種類の資格情報や特定のコンポーネントの使用がブロックされる場合があります。 そのため、Credential Guard を実行しているデバイスをアップグレードする前に、組織内の業務に必要なシナリオをテストすることをお勧めします。

  • MS-CHAPv2 に基づく Wi-Fi および VPN エンド ポイントを使っている場合、それらは NTLMv1 の場合と同様に攻撃の対象となります。組織では Wi-Fi 接続および VPN 接続に証明書ベースの認証を使うことをお勧めします。

  • Windows 10 バージョン 1511 以降、資格情報マネージャーを使って保存されるドメイン資格情報は Credential Guard で保護されています。資格情報マネージャーでは、Web サイトやネットワーク上の他のコンピューターにログオンするために使われるユーザー名とパスワードなどの資格情報を格納できます。資格情報マネージャーのための Credential Guard による保護には、次の考慮事項が適用されます。

    • リモート デスクトップ サービスで保存された資格情報は、パスワードを入力せずに別のコンピューターにリモートで接続するために使うことはできません。

    • 資格情報マネージャーからドメインの派生資格情報を抽出するアプリケーションは、それらの資格情報を使えなくなります。

    • Credential Guard がオンになっている PC から資格情報がバックアップされている場合は、資格情報マネージャーのコントロール パネルを使って資格情報を復元することができません。資格情報をバックアップする必要がある場合は、Credential Guard を有効にする前に行う必要があります。それ以外の場合は、それらの資格情報を復元できません。

Credential Guard によって保護されないシナリオ

次のような資格情報の格納方法は、Credential Guard によって保護されません。

  • Windows 機能の保護の外部にある資格情報を管理するソフトウェア

  • ローカル アカウントと Microsoft アカウント

  • ドメイン コント ローラーやリモート デスクトップ ゲートウェイなどの特定のサーバーの役割を実行する Windows Server 2016 Technical Preview サーバー。Windows Server 2016 Technical Preview サーバーをクライアント PC として使用している場合は、Windows 10 Enterprise を実行している場合と同様に保護されます。

  • キー ロガー

  • 物理的な攻撃

  • 攻撃者が PC 上のマルウェアを使って、資格情報に関連付けられている特権を使用することを防止しません。IT 担当者や、組織内の重要な資産にアクセスできるユーザーなど、重要性の高いアカウントには専用の PC を使うことをお勧めします。

その他の軽減策

Credential Guard では、派生資格情報への攻撃に対する軽減策を提供でき、盗まれた資格情報を他の場所で使用できないようにすることができます。ただし、Credential Guard によって派生資格情報が保護されている場合でも、 PC は特定の攻撃に対して脆弱である可能性があります。このような攻撃には、侵害されたデバイスからの直接の特権の悪用と派生資格情報の使用、Device Guard より前に盗難された資格情報の再利用、管理ツールと脆弱なアプリケーション構成の悪用などが含まれます。そのため、ドメイン環境の堅牢性を高めるために、追加の軽減策を展開することも必要になります。

資格情報の盗難攻撃によって、攻撃者は、1 つのデバイスからのシークレットを盗みを別のデバイスからそれらを使用できます。Windows Server 2012 R2 またはそれ以降のドメインで複合認証を使う認証ポリシーを展開することで、ユーザーが特定のドメインに参加しているデバイスからのみサインインできるように制限できます。ただし、デバイスは認証用の共有シークレットも使用しているため、攻撃者はそれらのシークレットも盗むことができます。Credential Guard でデバイス証明書を展開することによって、認証ポリシーでは、デバイスが秘密キーを使って認証することを要求できます。これにより、盗まれたデバイスの共有シークレットを、盗まれたユーザー パスワードまたは Kerberos シークレット キーと共に使用して、ユーザーとしてサインオンすることを防止します。

デバイス証明書の認証には、次の要件があります。

  • デバイスのドメインが Windows Server 2012 以上であり、すべてのドメイン コントローラーに証明書があり、その証明書が厳密な KDC の検証を満たしている (KDC EKU があり、DNS ドメイン名が SubjectAltName (SAN) 拡張の DNSName フィールドと一致する)。

  • Windows 10 デバイスに、エンタープライズ ストア内のドメイン コント ローラーの証明書を発行する CA がある。

  • ユーザーにスマート カードを発行する前にユーザーの ID と信頼性を確立する方法と同様の方法で、デバイスの ID と信頼性を確認するためのプロセスが確立されている。

その他のグループ ポリシー設定

いくつかグループ ポリシー設定を有効にすることによって、資格情報への攻撃に対する保護を強化できます。

  • ドメイン コントローラーで、グループ ポリシーを使って、"KDC で信頼性情報、複合認証、および Kerberos 防御をサポートする" システムを構成します。[KDC で信頼性情報、複合認証、および Kerberos 防御をサポートする] グループ ポリシー設定を、[サポート] または [常に信頼性情報を提供する] に設定します。

  • Windows 10 を実行するデバイスでも、グループ ポリシーを使ってこの機能を有効にすることができます。これを行うには、[コンピューターの構成][管理用テンプレート][システム][Kerberos] の順に移動して、[Kerberos クライアントで信頼性情報、複合認証、および Kerberos 防御をサポートする][常に複合認証を先に送信する] グループ ポリシー設定を有効にします。

複合認証

複合認証は、ドメインおよびリソースへの認証時に、ユーザー ID にデバイス ID を追加します。複合認証を使わない場合は、ユーザーのシークレットのみが検証されます。複合認証を使う場合、Kerberos クライアントにユーザーのシークレットとデバイスのシークレットの両方が必要です。

複合認証を有効にすると、Kerberos 防御も有効になり、さらに 2 つの利点が得られます。

  • ドメインに参加しているデバイスでのユーザー認証が防御されます。これは、暗号化された Kerberos の初期認証がネットワークのキャプチャに含まれることを意味します。適切なデバイス キーがない場合、Kerberos AS-REQ はオフライン辞書攻撃から保護されます。

  • KDC のエラーは署名され、エラーのスプーフィング攻撃に対する保護が提供されます。

コンピューターの証明書の展開

組織内のドメイン コント ローラーが Windows Server 2016 Technical Preview を実行している場合で、Credential Guard が有効になっており、PC がドメインに参加しているときには、Windows 10 を実行しているデバイスは自動的にコンピューターの証明書を登録します。

ドメイン コント ローラーが Windows Server 2012 R2 を実行している場合は、各デバイスをコンピューターの証明書で手動でプロビジョニングする必要があります。これを行うには、ドメイン コントローラーまたは証明書機関で証明書テンプレートを作成して、各デバイスにコンピューターの証明書を展開します。

ユーザーにスマート カードを発行するために使われるのと同じセキュリティ手順をコンピューターの証明書に適用する必要があります。

  1. 証明書マネージャーのコンソールから、[証明書テンプレート] を右クリックし、[管理] をクリックします。

  2. [ワークステーション認証] を右クリックし、[テンプレートの複製] をクリックします。

  3. 新しいテンプレートを右クリックし、[プロパティ] をクリックします。

  4. [拡張機能] タブの [アプリケーション ポリシー] をクリックし、[編集] をクリックします。

  5. [クライアント認証] をクリックし、[削除] をクリックします。

  6. ID-PKInit-KPClientAuth EKU を追加します。[追加] をクリックし、[新規作成] をクリックして、次の値を指定します。

    • 名前: Kerberos Client Auth

    • オブジェクト識別子: 1.3.6.1.5.2.3.4

  7. [拡張機能] タブの [発行ポリシー] をクリックし、[編集] をクリックします。

  8. [発行ポリシー][高保証] をクリックします。

  9. [サブジェクト名] タブで、[DNS 名] チェック ボックスをオンにし、[ユーザー プリンシパル名 (UPN)] チェック ボックスをオフにします。

Credential Guard を実行しているデバイスで、次のコマンドを実行することにより、コンピューターの認証証明書を使ってデバイスを登録します。

CertReq -EnrollCredGuardCert MachineAuthentication

  

コンピューターの認証証明書を登録した後、デバイスを再起動する必要があります。

 

発行ポリシーのグループへのリンク

認証ポリシーを使用することで、ユーザーが Credential Guard を実行しているデバイスにのみサインインできるように設定できます。ただし、認証ポリシーを展開する前に、環境を設定するためにいくつかのスクリプトを実行する必要があります。

  • get-IssuancePolicy.ps1 は、証明期間で利用できるすべての発行ポリシーを表示します。

    Windows PowerShell のコマンド プロンプトで、次のコマンドを入力します。

    .\get-IssuancePolicy.ps1 –LinkedToGroup:All
    
  • set-IssuancePolicyToGroupLink.ps1 は、ユニバーサル セキュリティ グループを作成し、組織単位を作成して、発行ポリシーをそのユニバーサル セキュリティ グループにリンクします。

    Windows PowerShell のコマンド プロンプトで、次のコマンドを入力します。

    .\set-IssuancePolicyToGroupLink.ps1 –IssuancePolicyName:”<name of issuance policy>” –groupOU:”<Name of OU to create>” –groupName:”<name of Universal security group to create>”
    

認証ポリシーの展開

認証ポリシーをセットアップする前に、KDC で認証ポリシーの適用の失敗をログに記録しておく必要があります。これを行うには、イベント ビューアーで、アプリケーションとサービス ログ\Microsoft\Windows\認証に移動し、AuthenticationPolicyFailures-DomainController を右クリックして [ログの有効化] をクリックします。

これで、認証ポリシーをセットアップして Credential Guard を使用できます。

Mt483740.wedge(ja-jp,VS.85).gifCredential Guard の認証ポリシーを追加するには

  1. ドメイン コント ローラーが Windows Server 2012 R2 以上のドメインの機能レベルを実行していることを確認します。

  2. この認証ポリシーが適用される PC を識別するために使用されるセキュリティ グループを作成します。

  3. このセキュリティ グループにコンピューター アカウントを追加します。

  4. Active Directory 管理センターを開きます。

  5. [認証] をクリックし、[新規作成] をクリックして、[認証ポリシー] をクリックします。

  6. [表示名] ボックスに、この認証ポリシーの名前を入力します。

  7. [アカウント] の見出しの下にある [追加] をクリックします。

  8. [ユーザー、コンピューター、またはサービス アカウントの選択] ダイアログ ボックスで、ユーザー アカウントの名前を入力し、[OK] をクリックします。

  9. [ユーザー] の見出しの下で、ユーザー アカウントに対応する [編集] をクリックします。

  10. [条件の追加] をクリックします。

  11. [アクセス制御条件の編集] ボックスで、[ユーザー][グループ][次のそれぞれに所属する][値] が表示されることを確認し、[項目の追加] をクリックします。

  12. [ユーザー、コンピューター、またはサービス アカウントの選択] ダイアログ ボックスで、set-IssuancePolicyToGroupLink スクリプトを使って作成したセキュリティ グループの名前を入力し、[OK] をクリックします。

  13. [OK] をクリックして [アクセス制御条件の編集] ボックスを閉じます。

  14. [OK] をクリックして認証ポリシーを作成します。

  15. Active Directory 管理センターを閉じます。

  

Credential Guard で実施モードの認証ポリシーが展開されると、ユーザーはコンピューターの認証証明書がプロビジョニングされていないデバイスを使ってサインインすることができなくなります。これは、ローカルおよびリモートの両方のサインインのシナリオに適用されます。

 

付録: スクリプト

このトピックに記載されているスクリプトの一覧を示します。

証明機関で利用できる発行ポリシーを取得する

このスクリプト ファイルを get-IssuancePolicy.ps1 という名前で保存します。

#######################################
##     Parameters to be defined      ##
##     by the user                   ##
#######################################

Param (
$Identity,
$LinkedToGroup
)

#######################################
##     Strings definitions           ##
#######################################
Data getIP_strings {
# culture=\"en-US\"
ConvertFrom-StringData -stringdata @'
help1 = This command can be used to retrieve all available Issuance Policies in a forest. The forest of the currently logged on user is targetted.
help2 = Usage:
help3 = The following parameter is mandatory:
help4 = -LinkedToGroup:<yes|no|all>
help5 = "yes" will return only Issuance Policies that are linked to groups. Checks that the linked Issuance Policies are linked to valid groups.
help6 = "no" will return only Issuance Policies that are not currently linked to any group. 
help7 = "all" will return all Issuance Policies defined in the forest. Checks that the linked Issuance policies are linked to valid groups.
help8 = The following parameter is optional:
help9 = -Identity:<Name, Distinguished Name or Display Name of the Issuance Policy that you want to retrieve>. If you specify an identity, the option specified in the "-LinkedToGroup" parameter is ignored.
help10 = Output: This script returns the Issuance Policy objects meeting the criteria defined by the above parameters.
help11 = Examples:
errorIPNotFound = Error: no Issuance Policy could be found with Identity "{0}"
ErrorNotSecurity = Error: Issuance Policy "{0}" is linked to group "{1}" which is not of type "Security".
ErrorNotUniversal = Error: Issuance Policy "{0}" is linked to group "{1}" whose scope is not "Universal".
ErrorHasMembers = Error: Issuance Policy "{0}" is linked to group "{1}" which has a non-empty membership. The group has the following members:
LinkedIPs = The following Issuance Policies are linked to groups:
displayName = displayName : {0}
Name = Name : {0}
dn = distinguishedName : {0}
        InfoName = Linked Group Name: {0} 
        InfoDN = Linked Group DN: {0}   
NonLinkedIPs = The following Issuance Policies are NOT linked to groups:
'@
}

##Import-LocalizedData getIP_strings


import-module ActiveDirectory


#######################################
##           Help                    ##
#######################################

function Display-Help {

    ""
    $getIP_strings.help1
    ""
$getIP_strings.help2
""
$getIP_strings.help3
"     " + $getIP_strings.help4
"             " + $getIP_strings.help5
    "             " + $getIP_strings.help6
    "             " + $getIP_strings.help7
""
$getIP_strings.help8
    "     " + $getIP_strings.help9
    ""
    $getIP_strings.help10
""
""    
$getIP_strings.help11
    "     " + '$' + "myIPs = .\get-IssuancePolicy.ps1 -LinkedToGroup:All"
    "     " + '$' + "myLinkedIPs = .\get-IssuancePolicy.ps1 -LinkedToGroup:yes"
    "     " + '$' + "myIP = .\get-IssuancePolicy.ps1 -Identity:""Medium Assurance"""
""
}


$root = get-adrootdse
$domain = get-addomain -current loggedonuser
$configNCDN = [String]$root.configurationNamingContext


if ( !($Identity) -and !($LinkedToGroup) ) {
display-Help
break
}

if ($Identity) {
    $OIDs = get-adobject -Filter {(objectclass -eq "msPKI-Enterprise-Oid") -and ((name -eq $Identity) -or (displayname -eq $Identity) -or (distinguishedName -like $Identity)) } -searchBase $configNCDN -properties *

    if ($OIDs -eq $null) {
$errormsg = $getIP_strings.ErrorIPNotFound -f $Identity
write-host $errormsg -ForegroundColor Red
    }
    
    foreach ($OID in $OIDs) {
    
        if ($OID."msDS-OIDToGroupLink") {
            # In case the Issuance Policy is linked to a group, it is good to check whether there is any problem with the mapping.
            $groupDN = $OID."msDS-OIDToGroupLink"
            $group = get-adgroup -Identity $groupDN
    $groupName = $group.Name
            
            # Analyze the group
            if ($group.groupCategory -ne "Security") {
$errormsg = $getIP_strings.ErrorNotSecurity -f $Identity, $groupName
                write-host $errormsg -ForegroundColor Red
            }
            if ($group.groupScope -ne "Universal") {
                $errormsg = $getIP_strings.ErrorNotUniversal -f $Identity, $groupName
write-host $errormsg -ForegroundColor Red
            }
            $members = Get-ADGroupMember -Identity $group
            if ($members) {
                $errormsg = $getIP_strings.ErrorHasMembers -f $Identity, $groupName
write-host $errormsg -ForegroundColor Red
                foreach ($member in $members) {
                    write-host "          "  $member -ForeGroundColor Red
                }
            }
        }
        
    }
    return $OIDs
    break
}

if (($LinkedToGroup -eq "yes") -or ($LinkedToGroup -eq "all")) {
    $LDAPFilter = "(&(objectClass=msPKI-Enterprise-Oid)(msDS-OIDToGroupLink=*)(flags=2))"
    $LinkedOIDs = get-adobject -searchBase $configNCDN -LDAPFilter $LDAPFilter -properties *

    write-host ""    
    write-host "*****************************************************"
    write-host $getIP_strings.LinkedIPs
    write-host "*****************************************************"
    write-host ""
    if ($LinkedOIDs -ne $null){
      foreach ($OID in $LinkedOIDs) {
  
          # Display basic information about the Issuance Policies
          ""
  $getIP_strings.displayName -f $OID.displayName
  $getIP_strings.Name -f $OID.Name
  $getIP_strings.dn -f $OID.distinguishedName
       
          
          # Get the linked group.
          $groupDN = $OID."msDS-OIDToGroupLink"
          $group = get-adgroup -Identity $groupDN
          $getIP_strings.InfoName -f $group.Name
          $getIP_strings.InfoDN -f $groupDN
          
          # Analyze the group
          $OIDName = $OID.displayName
    $groupName = $group.Name
          if ($group.groupCategory -ne "Security") {
          $errormsg = $getIP_strings.ErrorNotSecurity -f $OIDName, $groupName
          write-host $errormsg -ForegroundColor Red
          }
          if ($group.groupScope -ne "Universal") {
          $errormsg = $getIP_strings.ErrorNotUniversal -f $OIDName, $groupName
          write-host $errormsg -ForegroundColor Red
          }
          $members = Get-ADGroupMember -Identity $group
          if ($members) {
          $errormsg = $getIP_strings.ErrorHasMembers -f $OIDName, $groupName
          write-host $errormsg -ForegroundColor Red
              foreach ($member in $members) {
                  write-host "          "  $member -ForeGroundColor Red
              }
          }
          write-host ""
      }
    }else{
write-host "There are no issuance policies that are mapped to a group"
    }
    if ($LinkedToGroup -eq "yes") {
        return $LinkedOIDs
        break
    }
}    

if (($LinkedToGroup -eq "no") -or ($LinkedToGroup -eq "all")) {  
    $LDAPFilter = "(&(objectClass=msPKI-Enterprise-Oid)(!(msDS-OIDToGroupLink=*))(flags=2))"
    $NonLinkedOIDs = get-adobject -searchBase $configNCDN -LDAPFilter $LDAPFilter -properties *

    write-host ""    
    write-host "*********************************************************"
    write-host $getIP_strings.NonLinkedIPs
    write-host "*********************************************************"
    write-host ""
    if ($NonLinkedOIDs -ne $null) {
      foreach ($OID in $NonLinkedOIDs) {

# Display basic information about the Issuance Policies
write-host ""
$getIP_strings.displayName -f $OID.displayName
$getIP_strings.Name -f $OID.Name
$getIP_strings.dn -f $OID.distinguishedName
write-host ""
      }
    }else{
write-host "There are no issuance policies which are not mapped to groups"
    }
    if ($LinkedToGroup -eq "no") {
        return $NonLinkedOIDs
        break
    }
}

  

このスクリプトの実行に問題がある場合は、ConvertFrom-StringData パラメーターの後の単一引用符を置き換えてみてください。

 

発行ポリシーをグループにリンクする

このスクリプト ファイルを set-IssuancePolicyToGroupLink.ps1 という名前で保存します。

#######################################
##     Parameters to be defined      ##
##     by the user                   ##
#######################################

Param (
$IssuancePolicyName,
$groupOU,
$groupName
)

#######################################
##     Strings definitions           ##
#######################################

Data ErrorMsg {
# culture=\"en-US\"
ConvertFrom-StringData -stringdata @'
help1 = This command can be used to set the link between a certificate issuance policy and a universal security group.
help2 = Usage:
help3 = The following parameters are required:
help4 = -IssuancePolicyName:<name or display name of the issuance policy that you want to link to a group>
help5 = -groupName:<name of the group you want to link the issuance policy to>. If no name is specified, any existing link to a group is removed from the Issuance Policy.
help6 = The following parameter is optional:
help7 = -groupOU:<Name of the Organizational Unit dedicated to the groups which are linked to issuance policies>. If this parameter is not specified, the group is looked for or created in the Users container.
help8 = Examples:
help9 = This command will link the issuance policy whose display name is "High Assurance" to the group "HighAssuranceGroup" in the Organizational Unit "OU_FOR_IPol_linked_groups". If the group or the Organizational Unit do not exist, you will be prompted to create them.
help10 = This command will unlink the issuance policy whose name is "402.164959C40F4A5C12C6302E31D5476062" from any group.
MultipleIPs = Error: Multiple Issuance Policies with name or display name "{0}" were found in the subtree of "{1}"
NoIP = Error: no issuance policy with name or display name "{0}" could be found in the subtree of "{1}".
IPFound = An Issuance Policy with name or display name "{0}" was successfully found: {1}
MultipleOUs = Error: more than 1 Organizational Unit with name "{0}" could be found in the subtree of "{1}".
confirmOUcreation = Warning: The Organizational Unit that you specified does not exist. Do you want to create it?
OUCreationSuccess = Organizational Unit "{0}" successfully created.
OUcreationError = Error: Organizational Unit "{0}" could not be created.
OUFoundSuccess = Organizational Unit "{0}" was successfully found.
multipleGroups = Error: More than one group with name "{0}" was found in Organizational Unit "{1}".  
confirmGroupCreation = Warning: The group that you specified does not exist. Do you want to create it?
groupCreationSuccess = Univeral Security group "{0}" successfully created.
groupCreationError = Error: Univeral Security group "{0}" could not be created.
GroupFound = Group "{0}" was successfully found.
confirmLinkDeletion = Warning: The Issuance Policy "{0}" is currently linked to group "{1}". Do you really want to remove the link?
UnlinkSuccess = Certificate issuance policy successfully unlinked from any group.
UnlinkError = Removing the link failed.
UnlinkExit = Exiting without removing the link from the issuance policy to the group.
IPNotLinked = The Certificate issuance policy is not currently linked to any group. If you want to link it to a group, you should specify the -groupName option when starting this script.
ErrorNotSecurity = Error: You cannot link issuance Policy "{0}" to group "{1}" because this group is not of type "Security".
ErrorNotUniversal = Error: You cannot link issuance Policy "{0}" to group "{1}" because the scope of this group is not "Universal".
ErrorHasMembers = Error: You cannot link issuance Policy "{0}" to group "{1}" because it has a non-empty membership. The group has the following members:
ConfirmLinkReplacement = Warning: The Issuance Policy "{0}" is currently linked to group "{1}". Do you really want to update the link to point to group "{2}"?
LinkSuccess = The certificate issuance policy was successfully linked to the specified group.
LinkError = The certificate issuance policy could not be linked to the specified group.
ExitNoLinkReplacement = Exiting without setting the new link.
'@
}

# import-localizeddata ErrorMsg

function Display-Help {
""
write-host $ErrorMsg.help1
""
write-host $ErrorMsg.help2
""
write-host $ErrorMsg.help3
write-host "`t" $ErrorMsg.help4
write-host "`t" $ErrorMsg.help5
""
write-host $ErrorMsg.help6
write-host "`t" $ErrorMsg.help7
""
""
write-host $ErrorMsg.help8
""
write-host $ErrorMsg.help9
".\Set-IssuancePolicyToGroupMapping.ps1 -IssuancePolicyName ""High Assurance"" -groupOU ""OU_FOR_IPol_linked_groups"" -groupName ""HighAssuranceGroup"" "
""
write-host $ErrorMsg.help10
'.\Set-IssuancePolicyToGroupMapping.ps1 -IssuancePolicyName "402.164959C40F4A5C12C6302E31D5476062" -groupName $null '
""
}



# Assumption:  The group to which the Issuance Policy is going 
#              to be linked is (or is going to be created) in 
#              the domain the user running this script is a member of.
import-module ActiveDirectory
$root = get-adrootdse
$domain = get-addomain -current loggedonuser


if ( !($IssuancePolicyName) ) {
display-Help
break
}

#######################################
##     Find the OID object           ##
##     (aka Issuance Policy)         ##
#######################################

$searchBase = [String]$root.configurationnamingcontext
$OID = get-adobject -searchBase $searchBase -Filter { ((displayname -eq $IssuancePolicyName) -or (name -eq $IssuancePolicyName)) -and (objectClass -eq "msPKI-Enterprise-Oid")} -properties *

if ($OID -eq $null) {
$tmp = $ErrorMsg.NoIP -f $IssuancePolicyName, $searchBase  
write-host $tmp -ForeGroundColor Red
break;
}
elseif ($OID.GetType().IsArray) {
$tmp = $ErrorMsg.MultipleIPs -f $IssuancePolicyName, $searchBase  
write-host $tmp -ForeGroundColor Red
break;
}
else {
$tmp = $ErrorMsg.IPFound -f $IssuancePolicyName, $OID.distinguishedName
write-host $tmp -ForeGroundColor Green
}



#######################################
##  Find the container of the group  ##
#######################################

if ($groupOU -eq $null) {
# default to the Users container
$groupContainer = $domain.UsersContainer
} 
else {
$searchBase = [string]$domain.DistinguishedName
$groupContainer = get-adobject -searchBase $searchBase -Filter { (Name -eq $groupOU) -and (objectClass -eq "organizationalUnit")}
if ($groupContainer.count -gt 1) {
$tmp = $ErrorMsg.MultipleOUs -f $groupOU, $searchBase
write-host $tmp -ForegroundColor Red
break;
}
elseif ($groupContainer -eq $null) {
$tmp = $ErrorMsg.confirmOUcreation
write-host $tmp " ( (y)es / (n)o )" -ForegroundColor Yellow -nonewline
$userChoice = read-host
if ( ($userChoice -eq "y") -or ($userChoice -eq "yes") ) {
new-adobject -Name $groupOU -displayName $groupOU -Type "organizationalUnit" -ProtectedFromAccidentalDeletion $true -path $domain.distinguishedName
if ($?){
$tmp = $ErrorMsg.OUCreationSuccess -f $groupOU
write-host $tmp -ForegroundColor Green
}
else{
$tmp = $ErrorMsg.OUCreationError -f $groupOU
write-host $tmp -ForeGroundColor Red 
break;
}
$groupContainer = get-adobject -searchBase $searchBase -Filter { (Name -eq $groupOU) -and (objectClass -eq "organizationalUnit")}
}
else {
break;
}
}
else {
$tmp = $ErrorMsg.OUFoundSuccess -f $groupContainer.name
write-host $tmp -ForegroundColor Green
}
}

#######################################
##  Find the group               ##
#######################################

if (($groupName -ne $null) -and ($groupName -ne "")){
##$searchBase = [String]$groupContainer.DistinguishedName
$searchBase = $groupContainer
$group = get-adgroup -Filter { (Name -eq $groupName) -and (objectClass -eq "group") } -searchBase $searchBase
if ($group -ne $null -and $group.gettype().isarray) {
$tmp = $ErrorMsg.multipleGroups -f $groupName, $searchBase
write-host $tmp -ForeGroundColor Red
break;
}
elseif ($group -eq $null) {
$tmp = $ErrorMsg.confirmGroupCreation
write-host $tmp " ( (y)es / (n)o )" -ForegroundColor Yellow -nonewline
$userChoice = read-host
if ( ($userChoice -eq "y") -or ($userChoice -eq "yes") ) {
new-adgroup -samAccountName $groupName -path $groupContainer.distinguishedName -GroupScope "Universal" -GroupCategory "Security"
if ($?){
$tmp = $ErrorMsg.GroupCreationSuccess -f $groupName
write-host $tmp -ForegroundColor Green
}else{
$tmp = $ErrorMsg.groupCreationError -f $groupName
write-host $tmp -ForeGroundColor Red 
break
}
$group = get-adgroup -Filter { (Name -eq $groupName) -and (objectClass -eq "group") } -searchBase $searchBase
}
else {
break;
}
}
else {
$tmp = $ErrorMsg.GroupFound -f $group.Name
write-host $tmp -ForegroundColor Green
}
} 
else {
## If the group is not specified, we should remove the link if any exists
if ($OID."msDS-OIDToGroupLink" -ne $null) {
$tmp = $ErrorMsg.confirmLinkDeletion -f $IssuancePolicyName, $OID."msDS-OIDToGroupLink"
write-host $tmp " ( (y)es / (n)o )" -ForegroundColor Yellow -nonewline
$userChoice = read-host
if ( ($userChoice -eq "y") -or ($userChoice -eq "yes") ) {
set-adobject -Identity $OID -Clear "msDS-OIDToGroupLink"
if ($?) {
$tmp = $ErrorMsg.UnlinkSuccess
write-host $tmp -ForeGroundColor Green
}else{
$tmp = $ErrorMsg.UnlinkError
write-host $tmp -ForeGroundColor Red
}
} 
else { 
$tmp = $ErrorMsg.UnlinkExit
write-host $tmp
break 
}
}
else {
$tmp = $ErrorMsg.IPNotLinked
write-host $tmp -ForeGroundColor Yellow
}
break;
}


#######################################
##  Verify that the group is         ##
##  Universal, Security, and         ## 
##  has no members                   ##
#######################################

if ($group.GroupScope -ne "Universal") {
$tmp = $ErrorMsg.ErrorNotUniversal -f $IssuancePolicyName, $groupName
write-host $tmp -ForeGroundColor Red
break;
}
if ($group.GroupCategory -ne "Security") {
$tmp = $ErrorMsg.ErrorNotSecurity -f $IssuancePolicyName, $groupName
write-host $tmp -ForeGroundColor Red
break;
}
$members = Get-ADGroupMember -Identity $group
if ($members -ne $null) {
$tmp = $ErrorMsg.ErrorHasMembers -f $IssuancePolicyName, $groupName
write-host $tmp -ForeGroundColor Red
foreach ($member in $members) {write-host "   $member.name" -ForeGroundColor Red}
break;
}


#######################################
##  We have verified everything. We  ##
##  can create the link from the     ## 
##  Issuance Policy to the group.    ##
#######################################

if ($OID."msDS-OIDToGroupLink" -ne $null) {
$tmp = $ErrorMsg.ConfirmLinkReplacement -f $IssuancePolicyName, $OID."msDS-OIDToGroupLink", $group.distinguishedName
write-host $tmp  "( (y)es / (n)o )" -ForegroundColor Yellow -nonewline
$userChoice = read-host
if ( ($userChoice -eq "y") -or ($userChoice -eq "yes") ) {
$tmp = @{'msDS-OIDToGroupLink'= $group.DistinguishedName}
set-adobject -Identity $OID -Replace $tmp
if ($?) {
$tmp = $Errormsg.LinkSuccess
write-host $tmp -Foreground Green
}else{
$tmp = $ErrorMsg.LinkError
write-host $tmp -Foreground Red
}
} else { 
$tmp = $Errormsg.ExitNoLinkReplacement
write-host $tmp
break 
}
}
else {
$tmp = @{'msDS-OIDToGroupLink'= $group.DistinguishedName}
set-adobject -Identity $OID -Add $tmp
if ($?) {
$tmp = $Errormsg.LinkSuccess
write-host $tmp -Foreground Green
}else{
$tmp = $ErrorMsg.LinkError
write-host $tmp -Foreground Red
}
}

  

このスクリプトの実行に問題がある場合は、ConvertFrom-StringData パラメーターの後の単一引用符を置き換えてみてください。

 

関連トピック

Windows 10 の分離ユーザー モードに関する動画 (Dave Probert による説明) (Channel 9)

Windows 10 の分離ユーザー モードのプロセスと機能に関する動画 (Logan Gabriel による説明) (Channel 9)

Windows 10 の分離ユーザー モードのプロセスと機能の詳細に関する動画 (Dave Probert による説明) (Channel 9)

Windows 10 の分離ユーザー モードを使った、資格情報盗難の問題の軽減に関する動画 (Channel 9)

Windows Kerberos での KDC の厳密な検証の有効化に関するページ

Windows Server 2012 の Kerberos 認証の新機能に関するページ

Windows Server 2008 R2 手順ガイドの AD DS 用の認証メカニズム保証

トラステッド プラットフォーム モジュール