Active Directory: AD LDS における unicodePwd 属性値の謎

Active Directory ライトウェイト ディレクトリ サービスでは、高度な方法でパスワードの変換と認証が行われます。

Frank C. Rettig

最近、私のクライアントの中に、Active Directory からインターネット経由で特定の情報を公開する必要のある人物がいました。この意図は、(ログオン目的の) 外部のアプリケーションの認証を、認証に使用する特定の属性を公開せずに行うことでした。皆さんは、アプリケーション外で認証することに何の意味があるのか疑問に思われているかもしれませんが、こうすることにより、アプリケーションの提供者ではなくアプリケーションのユーザーが責任を負うようになるので、提供者の負担が減ります。

インターネットにドメイン コントローラーを公開するのは、基本的に好ましくなく、それは運用環境から直接公開する場合でも境界ネットワークで公開する場合でも同じです。適切な方法は、Active Directory ライトウェイト ディレクトリ サービス (AD LDS) の役割を持つ Windows Server 2008 サーバーを境界ネットワークに配置することです。

AD LDS は、元は Active Directory Application Mode (ADAM) と呼ばれていました。最初は Windows Server 2003 のアドオンとして提供されましたが、Windows Server 2003 R2 では製品に組み込まれるようになり、Windows Server 2008 または Windows 7 ではサーバーの役割として使用できるようになりました。多くの点において、AD LDS は AD と似ています。既に言われているように、AD LDS は、完全なエンタープライズ機能を持たない、AD が軽量化されたバージョンです。AD LDS は、どのバージョンの Windows でも同じように実装できますが、最適なのは Windows PowerShell 2.0 が同梱されている Windows Server 2008 R2 です。他の OS のバージョンとは異なり、新しいバージョンの Windows PowerShell では、AD 属性または AD LDS 属性の管理容易性が強化されています。

ライトウェイト ディレクトリ アクセス プロトコルの使用

AD と AD LDS のどちらに関心がある場合も、unicodePwd 属性があるのは変わりません。この属性は、ディレクトリ パーティションまたはアプリケーション パーティションに格納されています。ただし、これは、サーバーが AD ドメイン コントローラーに昇格されているか、AD LDS サーバーの属性を持つ適切な LDIF テンプレートが適用されていることを前提としています。

AD または AD LDS では、アプリケーションはライトウェイト ディレクトリ アクセス プロトコル (LDAP) のバージョン 3.0 を使用してディレクトリをクエリします。クエリを実行するには、アプリケーション (LDP.EXE、CSVDE.EXE、LDIFDE.EXE、ADSIEdit.exe、または独自に作成したアプリケーション) でアカウントとパスワードが提供される必要があります。十分簡単なように見えますが、決して簡単ではありません。パスワードを提供するのは簡単ですが、unicodePwd 属性に格納されているパスワードを取得するのは困難です。なぜなら、ほとんどのインタラクティブなディレクトリやアプリケーションでは、ネイティブな形式でパスワードを入力するよう求められることが多いからです。したがって、パスワードが car だとしたら、まさにそれが入力する必要のある文字だということになります。AD のフォレストまたはドメインにアクセスする場合や、特定のアカウントのパスワードを割り当てたり、リセットしたりするために ADSIedit または LDP を使用して AD LDS インスタンスにアクセスする場合も同様です。

一度に多くの追加や変更を行う必要がある場合に最適なツールは、LDIFDE.EXE プログラムです。unicodePwd 属性を追加または更新するためには、unicodePwd 属性の値を変換して、Unicode を Base64 でエンコードした形式にする必要があります。

Unicode を Base64 でエンコードするロジック

それでは、Unicode を Base64 でエンコードするにはどうすればよいでしょうか。お楽しみはここからです。願わくば、unicodePwd 属性 (および同じエンコーディングが必要なその他の属性) の謎を今月の記事で完全に解明したいところです。

まず、これ以降の文には注釈があります。図 1 の手順 1. ~ 12. を参照してください。パスワードを二重引用符で囲み、(引用符を含む) 各文字を、対応する Unicode 値に変換する必要があります。つまり、まず各文字に対応する ASCII 値を見つけて、各 ASCII 値から 16 進数値を派生させ、それから 16 ビットを表わすために各 16 進数値に 2 つのゼロを埋め込みます (最後の処理は Windows で UTF16 が使用されているため必要になります)。

Unicode 値に変換すると、0 が埋め込まれた 16 進数値は 1 行の長い文字列に結合されます。Base64 は 6 ビット ベースなので、この文字列は左側から 6 文字ずつ解析されます。6 文字に満たない 16 進数値が検出された場合は、6 文字になるまで右側に 0 が埋め込まれます。それから、16 進数の値が 6 文字を 1 組として 2 進数に変換されます。2 進数と同様に、解析は右側から 6 文字ごとに行われます。

必須ではありませんが、文字が 6 個に満たない 2 進数値には、6 個になるまで左側に 0 を埋め込んでください (先頭の 0 は、いくつあっても数値の 0 と同じです。他の組にも文字が 6 つあるので、こうすることで読みやすくなります)。それから、解析した各 2 進数値を、対応する 10 進数値に変換します。その数値をインデックスとして使用し、Base64 の表 (図 2) で対応する文字を見つけます。6 個の値が、埋め込まれた 0 のみで構成されている場合は、等号が使用されます。

図 1 では、手順 1. ~ 12. で、car という文字がどのように IgBjAGEAcgAiAA== に変換されるかを示しています。Unicode を Base64 でエンコードする過程において必要な右側への埋め込みは、青い文字で表わしています。赤い文字で表わしている左側への埋め込みは、単に文字の長さに一貫性を持たせ、他の 6 個 1 組の 2 進数値と比較する際に読みやすくするために行った処理です。

Unicode を Base64 でエンコードしたパスワードを作成する手順

図 1 Unicode を Base64 でエンコードしたパスワードを作成する手順

Base64 の対応表

図 2 Base64 の対応表

この無骨なロジックが本当に正しいかどうか疑問に思われる場合は、gbordier.com/gbtools/stringconverter.htm (英語) から Stringconverter.exe プログラムをダウンロードして、次の DOS プロンプトのコマンド文字列を実行してみてください。

stringconverter \"car\" /encode /unicode
IgBjAGEAcgAiAA==

ご覧のとおり、結果は同じです。

Unicode を Base64 でエンコードしたパスワードを作成する

まず、簡単なテストとして次の Excel 関数を使用すると、入力したすべてのテキストを、Base64 でエンコードされた Unicode 値に適切に変換できます (図 1 は、Excel で作成したものです)。

  • CODE(): 文字に対応する数値を返す
  • DEC2HEX(): 10 進数値を 16 進数値に変換する
  • Concatenate(): 数個の文字列を 1 つの文字列に結合する
  • BIN2DEC(): 2 進数値を 10 進数値に変換する
  • MID(): 文字列の中央から文字を返す

多数の unicodePwd 属性の値を生成する場合は、スクリプトを記述するのが最適です。Excel で VBA を使用してスクリプトを記述することで、すべての生成された値を確認し、値を Excel ブックに保存して、後で参照できます。また、別の VBA スクリプトを使用して、AD LDS インスタンスにインポートする LDIF ファイルを即座に生成することもできます。

Unicode が Base64 でエンコードされた unicodePwd 属性の値を更新する

unicodePwd 属性の値は LDIFDE.exe プログラムで操作されるので、unicodePwd 属性の値をアップロードする際には LDIF ファイル形式に従う必要があります。この決まりには、Windows Server 2008 R2 の AD LDS の役割も関係しているので、LDIF ファイル形式に従ったのは基本情報をアップロードするためです。次を参照して、unicodePwd 属性の値 car を IgBjAGEAcgAiAA== という値として持っている最初のユーザー アカウントが John Doe のものであることに注目してください。

 

dn: CN=JohnDoe,OU=Accounts,DC=CONTOSO,DC=COM
Changetype: add
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
cn: John Doe
givenName: John
sn: Doe
userPrincipalName: johnd@Contoso.COM
mail: johnd@Contoso.COM
unicodePwd::IgBjAGEAcgAiAA==\
msDS-UserAccountDisabled: FALSE

dn: CN=Jess  Wanders,OU=Accounts,DC=CONTOSO,DC=COM
Changetype: add
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user
cn: Jess Wanders
givenName: Jess
sn: Wanders
userPrincipalName: JessW@Contoso.COM
mail: JessW@Contoso.COM
unicodePwd::IgA3ACQANQBNAHMAIwA0AEQAaQBHACIA
msDS-UserAccountDisabled: FALSE

したがって、このファイルをインポートするには、ファイル名が Accounts.ldf であると仮定して、Windows Server 2008 R2 コマンド プロンプト コンソールで次の構文を入力します。

C:\Windows\system32\LDIFDE –i –f Accounts.ldf.

アカウントのパスワードのバインドとテストを行う

アプリケーション パーティションに新しく作成したアカウントをアップロードし、アカウントの userPrincipalName 属性と unicodePwd 属性の値を使用して LDAP サービスに接続またはバインドした後は、unicodePwd 属性の値が正しく変換され、Unicode が Base64 でエンコードされた形式になっているかどうかを確認することが重要です。一番便利で使いやすいツールは、LDP.exe です。このツールを使用する際に、入力するパスワードは IgBjAGEAcgAiAA== だと思われるかもしれませんが、そうではありません。このツールで入力する必要があるパスワードは、元々の形式である car です。

LDP.exe を使用して AD LDS に接続したら、アップロードしたアカウントの UPN にバインドして、パスワードを入力します。適切にロジックに従い、Unicode が Base64 でエンコードされた unicodePwd 属性の値を作成していたら、実際にそのアカウントを使用して、AD LDS インスタンスにバインドされていることが LDP ウィンドウで明確に表示されます。

Windows PowerShell を使用して unicodePwd 属性の値を更新する

LDIFDE.exe が unicodePwd 属性に数多くの変更を実行できる唯一のツールと位置付けるのは公平ではないでしょう。それでは、Unicode を Base64 でエンコードした値を生成する方法を理解した意味がありません。

Windows Server 2008 R2 では、Windows PowerShell 2.0 を使用することで、AD または AD LDS の特定の属性をもう少し細かく操作できます。AD LDS を操作しているとき、結果が先ほどの VBA スクリプトによって Excel ブック内で生成されるものと同じである、図 3 の構文を思い付きました (読みやすさのために、コマンド オプションは、それぞれ単独の行に記載しました)。

Windows PowerShell のコードを数行使用するだけで、Unicode を Base64 でエンコードした形式にパスワードをわざわざ変換しなくても、必要な変更処理をすばやく実行できることがわかります。これは Windows PowerShell の機能の強力なステートメントですが、バックグラウンドで行われるということを考慮すると、処理時間が増えるというデメリットがあります。特に、何百または何千ものアカウントを処理しているときに問題になります。

このため、いくつかのアカウントをときどき作成または更新する必要があるときには、Windows PowerShell を使用します。定期的に何百または何千ものアカウントを作成または更新する必要がある場合は、LDIFDE.exe を使用する方が、長い目で見ればずっと速く処理を実行できます。

Import-Csv c:\scripts\accounts.csv | 
New-ADUser
–Name $_.commonName
–GivenName $_.givenName
–Surname $_.sn

-EmailAddress $_.email
-Type user
-UserPrincipalName $_.userPrincipalName
–Server LDS01:389 |
Set-ADAccountPassword
-Identity $_.distinguishedName
-NewPassword (ConvertTo-SecureString -AsPlainText $_.Password -Force)
-Reset

-Server LDS01:389 |

Enable-ADAccount

-Identity $_.distinguishedName

-Server LDS01:389

図 3 アカウントのパスワードを更新する Windows PowerShell 2.0 のスクリプト

操作するのが AD でも AD LDS でも (ついでに言うと ADAM でも)、unicodePwd 属性を更新する方法はいくつかあります。変更するアカウントが 1 つだけなら、LDP.exe か ADSIEdit.exe がお勧めです。少数のアカウントをときどき変更する場合は、Windows Server 2008 R2 の AD か AD LDS に対して Windows PowerShell 2.0 を使用するのが最適です。

ただし、お使いのサーバーが Windows Server 2003 以降の (ただし、Windows Server 2008 R2 より古い) バージョンで、定期的に更新する必要があるアカウントが何百または何千とある場合は、Unicode が Base64 でエンコードされた unicodePwd 属性の値を生成するために、前もって準備を行うことをお勧めします。それから LDIFDE.exe を使用して、変更を一括でアップロードします。

Frank Rettig

Frank Rettig は、ワシントン D.C. 地区にある米国政府の事務所のコンサルタントで、国内外で 26 年の経験があります。ディレクトリ統合、ID 管理、モビリティ ソリューション、および政府のコンピューターの使用に関する標準化を専門としています。連絡先は frank.rettig@microsoft.com (英語のみ) です。

 

謝辞

この記事の正当性を確認していただいた、マイクロソフトの情報セキュリティ ACE Services チーム メンバーである、Roger Grimes (プリンシパル セキュリティ アーキテクト) と Shawn Rabourn (シニア セキュリティ コンサルタント)、この記事の内容を校閲していただいた、米国郵政公社連邦サービスの Anthony de Lagarde (シニア コンサルタント) に心より感謝いたします。

 

関連コンテンツ